I Let The Perpetrator Escape - Help!
Abi
on 25 Nov 2025
Latest activity Reply by Matt Tearle
on 1 Dec 2025
Hi Creative Coders!
I've been working my way through the problem set (and enjoying all the references), but the final puzzle has me stumped. I've managed to get 16/20 of the test cases to the right answer, and the rest remain very unsolvable for my current algorithm. I know there's some kind of leap of logic I'm missing, but can't figure out quite what it is. Can any of you help?
What I've Done So Far
My current algorithm looks a bit like this. The code is doing its best to embody spaghetti at the moment, so I'll refrain from posting the whole thing to spare you all from trying to follow my thought processes.
Step 1: Go through all the turns and fill out tables of 'definitely', 'maybe', and 'clue' based on the information provided in a single run through the turns. This means that the case mentioned in the problem where information from future turns affecting previous turns does not matter yet. 'Definitely' information is for when I know a card must belong to a certain player (or to no-one). 'Maybe' starts off with all players in all cells, and when a player is found to not be able to have a card, their number is removed from the cell. Think of Sudoku notes where someone has helpfully gone through the grid and put every single possible number in each cell. 'Clue' contains information about which cards players were hinted about.
Example from test case 1:
definitelyTable =
6×3 table
G1 G2 G3
____________ ____________ ____________
{[ 0]} {0×0 double} {0×0 double}
{0×0 double} {[ -1]} {[ 1]}
{0×0 double} {[ 6]} {[ 0]}
{[ 3]} {[ 4]} {0×0 double}
{0×0 double} {[ 0]} {0×0 double}
{[ 5]} {[ 3]} {0×0 double}
maybeTable =
6×3 table
G1 G2 G3
_________ _______ _______
{[ 0]} {[2 5]} {[1 2]}
{[ 4]} {[ 0]} {[ 0]}
{[2 4 6]} {[ 0]} {[ 0]}
{[ 0]} {[ 0]} {[1 4]}
{[ 1 4]} {[ 0]} {[ 1]}
{[ 0]} {[ 0]} {[2 4]}
clueTable =
6×3 table
G1 G2 G3
____________ ____________ ____________
{0×0 double} {[ 5 6]} {[ 2 4]}
{[ 4 6]} {[ 4 6]} {0×0 double}
{[ 2 6]} {[ 5 6]} {0×0 double}
{0×0 double} {[ 4]} {[ 4 5 6]}
{[ 4]} {0×0 double} {[ 1 4 6]}
{[ 2 5]} {0×0 double} {[ 2 4 5 6]}
(-1 indicates the card is in the envelope. 0 indicates the card is commonly known.)
Step 2: While a solution has not yet been found, loop through all the turns again. This is the part where future turn info can now be fed back into previous turns, and where my sticky test cases loop forever. I've coded up each of the implementation tips from the problem statement for this stage.
Where It All Comes Undone
The problem is, for certain test cases (e.g., case 5), I reach a point where going through all turns yields no new information. I either end up with an either-or scenario, where the potential culprit card is one of two choices, or with so little information it doesn't look like there is anywhere left to turn.
I solved some of the either-or cases by adding a snippet that assumes one of the values and then tries to solve the problem based on that new information. If it can't solve it, then it tries the other option and goes round again. Unfortunately, however, this results in an infinite flip-flop for some cases as neither guess resolves the puzzle.
Essentially guessing the solution and following through to a logical inconsistency for however many combinations of players and cards sounds a) inefficient and b) not the way this was intended to be solved. Does anyone have any hints that might get me on track to solve this mystery?
11 Comments
Time DescendingThat looks like a data structure you can work with. To simplify things further, you can put the knowledge about the envelope in the page assigned to your player (you know your own cards - no need to keep track of that). Follow these steps:
Eliminate all cards you know from the other players (incl. envelope) at the start.
While not all cards in the envelope known
For each hint
If result=-1, eliminate all cards from the answering player
If result>0, assign that card to the answering player and eliminate it for the others
If result=0 and from all cards being asked for exactly one is still 'maybe', assign that card to the answering player and eliminate it for the others
If exactly one card of a group remains 'maybe', it must be in the envelope (since the envelope contains all groups).
If the total number of assigned and 'maybe' cards of a player matches the required number of cards per player, assign all 'maybe' cards to that player and eliminate them for the others.
If a card is eliminated for all players and is neither in common cards nor in your cards, it must be in the envelope.
Update: I have started again from scratch and got up to 8/20 test cases passing. Fewer than I had with my spaghetti, but I think it's progress.
My knownCards is now a 3D matrix, where rows correspond to card number, columns are groups, and pages are player (@Stefan Abendroth, I think that's hopefully something along the lines of your suggestion?). I do a better job of setting up the hard truths at the start, filling in the confirmed cards players do or don't have, before going through all the cases where the player showed a card to someone else (and you don't know which).
I'm fairly confident I have:
- if number of 'yes' and 'maybe' cards is the total number a player should have, they own all those cards
- if all cards but one in a column have been assigned to a player, the remaining card is in the envelope
- if a player has all their cards, they cannot have any other cards
- for the 0 show case (shown card, you don't know which), I check the cards being asked against my knownCards matrix and eliminate ones that are already known. I skip over cards that I know are owned by the player being asked, since they could have shown that one. If there is only one card of which I don't already know the location, the player asked has that card
Annoyingly, there's an extra bit of logic that I'm missing since I rewrote that now loses me 8 test cases. Will have to come back to it tomorrow - any pointers to steps I might have missed always appreciated!
Abi,
The clue I overlooked at first is one that might be a little tricky to calculate from the way you've arranged your data, so maybe you've overlooked it too?
- Each player holds ncards cards. If you can identify 3n-ncards cards that a player definitely does not hold, then they must hold the remaining ncards cards. That is, if the no, yes, and maybe/unknown cards for a player are distributed such that there are ncards yes or maybe (and 3n-ncards no), then all the remaining maybes are yeses.
In your arrays above, for example, it looks like you know one of player 6's cards (G2 #3), and player 6 only appears once in your maybeTable. Since all the players have to have 2 cards, you can determine that player 6 must have card G1 #3.
I'm not sure I understand from your description how you're using the clueTable, but when you're going through the turns, remember to consider not just what was hinted, but also which cards were asked about together on the same turn. For example, if you know there was a turn where player 6 was asked about cards G1 #3, G2 #1, and G2 #6 and had one of them (but you don't know which one), and then you later determine someone else has cards G2 #3 and G3 #5, you can now say player 6 had G1 #3.
These are kind of just guesses, but maybe they'll give you some ideas to look into. It looks like you're off to a great start--I'm sure you'll get there!
-Abbey
Hi Abi,
you don't need any guessing for the test cases provided. Make sure to draw all possible conclusions from the knowledge you collected. Think about elimination of options.
Also consider putting all your knowledge in one place (one matrix or tensor), so you can take advantage of MATLABs powerful matrix operations.
Have fun learning and coding -
Stefan
Sign in to participate
