Using playing cards to store hidden data:
The implied card method for
encoding data into playing cards
Using The Recursive Implied Card Method to encode text:
Because the Recursive Method reuses cards that represented 1s at the start of the pack, it becomes less useful when we are encoding text and are using as many zeroes as possible. For one thing, more zeroes mean that there are fewer cards to use for the Recursive Method. It becomes apparent that the choice between having lots of 0s (to let us use fewer cards overall) and lots of 1s (to enable more recursions), makes the best way of mapping numbers to letters, and the best bit length, a complicated matter. If we have lots of 1s in our numbers, we get to do more recursions, but on the other hand we use up more cards in each recursion. If we have lots of 0s then we reuse more cards, but have fewer to use for the recursions. A higher quantity of 0s also raises the chances of us not being able to use all the cards at the end of the pack on the first run. When that happens, it becomes more unlikely that we will be able to fit those numbers into the extra cards supplied by the Recursive method.
To demonstrate how the Recursive Method works when encoding text, we will use our previous long string, "Hello I am trying to encode as many characters of text as possible into a single pack of fifty two playing cards using a method that maps the cards on to carefully chosen binary numbers". We will use the mapping tables from when we were encoding text using the Basic Method.
Mapping Table 1 used letters of the English alphabet sorted by frequency, mapped against 5-bit binary numbers sorted by *numerical* order. Using this mapping, we can encode 29 characters of our message into the pack on the first run before we start the recursion. We fit in the letters: "Hello I am trying to encode as many c". [Remember that we are ignoring the spaces.] There are 4 cards left over: the 2, 4 and 7 of diamonds, and the 4 of spades.
We split the pack into Parts 1a, 1b and 2, and we are able to fit in an extra 6 characters. We have to stop with 7 cards remaining though because we have a run of 7 consecutive zeroes, which if encoded would not appear in the decoding. The numbers we are trying to encode, but cannot, are: 00000, 00111 ("e" followed by "r").
If we split the pack again into Parts 1a, 1b, 2a, 2b and 3, then Part 2a (= Part 3) only has 5 cards in it so we cannot use it to encode further cards. In all, we have managed to fit 35 characters into the pack. This amounts to having the message: "Hello I am trying to encode as many charact".
When using mapping table 2 (5-bit binary numbers sorted by the number of bits in them, mapped on to the letters of the alphabet sorted by frequency), we can encode 33 characters of our message into the pack before we start recursion. We fit in the letters, "Hello I am trying to encode as many chara". There are 4 cards left over: the 6 of clubs, the 7 and queen of hearts, and the 10 of diamonds.
We split the pack into Parts 1a, 1b and 2. Part 1a (= Part 2) has 15 cards in it. We encode an extra 7 characters ending up with 5 spare cards. We cannot encode into these cards, as there is a string of 6 zeroes starting in the 7th character and leading into the 8th. If we try, it will not decode properly.
If we split the pack into Parts 1a, 1b, 2a, 2b and 3, we will only have 3 cards in part 2a (= Part 3) so we cannot encode any more cards. In all, we have managed to fit 40 characters into the pack. This amounts to having the message: "Hello I am trying to encode as many characters of".
When using mapping table 3 (6-bit binary numbers sorted by the number of bits in them, mapped on to the letters of the alphabet sorted by frequency), we can encode 34 characters of our message into the pack before recursion. We fit in the letters, "Hello I am trying to encode as many charac". There are 6 cards left over: the 8 of diamonds, the 8 of spades, the king of spades, the 5 of clubs, the king of hearts and the 3 of diamonds. We cannot encode into the last 6 cards, as there are too many consecutive zeroes.
We split the pack into Parts 1a, 1b and 2. Part 1a (= Part 2) has 11 cards in it. We can encode just one more letter ("t"), then we have a string of ten consecutive 0s in the following letters ("e" and "r": 000000, 000011), so we cannot encode any more letters, and we end up with 10 unused cards.
In total, we have only encoded 35 characters, which is 5 fewer than before. This is mainly due to the long bit length making it hard to use the final few cards.
In this particular example, the Recursive Method did not take anything away from the encoding, but it did not particularly add to it either.
When we use mapping table 4 (7-bit binary numbers sorted by the number of bits in them, mapped on to the letters of the alphabet sorted by frequency), we can only encode 31 characters before recursion ("Hello I am trying to encode as many cha"). This is because we have a sequence of 11 consecutive zeroes when we have only 11 cards left to use. When we split the pack into Parts 1a and 1b, Part 1a only has 9 cards in it, so we cannot encode any more.
Just for interest's sake, if we use 5-bit numbers sorted by the number of 1 bits in them *from highest to lowest* (instead of from lowest to highest), mapped on to the letters of the alphabet sorted by frequency, then our table looks like this:
Mapping table 6:
Numbers without any 1s:
00000 (00): [Unassigned]
Numbers with one occurrence of 1:
00001 (01): [Unassigned]
00010 (02): [Unassigned]
00100 (04): [Unassigned]
01000 (08): [Unassigned]
10000 (16): z
Numbers with two occurrences of 1s:
00011 (03): q
00101 (05): j
00110 (06): x
01001 (09): k
01010 (10): v
01100 (12): b
10001 (17): y
10010 (18): w
10100 (20): g
11000 (24): p
00111 (07): f
01011 (11): m
01101 (13): u
01110 (14): c
10011 (19): d
10101 (21): l
10110 (22): h
11001 (25): r
11010 (26): s
11100 (28): n
01111 (15): i
10111 (23): o
11011 (27): a
11101 (29): t
11110 (30): e
11111 (31): Not a character: End of the pack
Using this table, we can encode 15 characters on the first run, which amounts to "Hello I am trying t". We have 2 cards left over. We have not encoded many letters, but we have 36 cards available for our Part 2 (= Part 1a).
In our first recursion (with Part 2), we encode another 10 characters. Despite having only four cards for the last character, we manage to encode it correctly. We end up with 1 leftover card. Our Part 3 (= Part 2a) will have 26 cards in it, so we can continue encoding.
In our second recursion (with Part 3), we encode another 7 characters. We have 4 cards leftover. Our Part 4 (= Part 3a) will have 16 cards in it, so we can continue encoding.
In our third recursion (with Part 4), we encode another 3 characters. We have 5 cards left over, but we cannot use them as the next number we need to encode is 11110 and the final 0 would appear as a 1 when it gets decoded. We have 12 cards to use in our future Part 5.
In our fourth recursion (with Part 5), we encode another 2 characters. We have 5 cards leftover, which we cannot use because the next number ends in a zero again. We have 9 cards available for our future Part 6.
In our fifth recursion (with Part 6), we encode another 2 characters. We have 2 cards left over. We have 6 cards available for our future Part 7 (Part 6a).
In our 6th recursion (with Part 7), we encode just one more character. We have 3 cards left over. We have 4 cards available for our future Part 8 (Part 7a), but that will not be enough to encode our next character, so we stop here.
In all, we have managed to encode 40 characters: "Hello I am trying to encode as many characters of". This is exactly the same amount as when we used 5-bit numbers sorted by the number of bits from lowest to highest, using recursion. Of course, how we encoded them was a lot more complicated this time, but it shows that the Recursive Method can compensate for a lack of zeroes.
Two Part Mappings:
The recursive method is most productive when there are plenty of 1s in the first run of the pack of cards. However, cards that are not going to be used recursively are most efficient when there are plenty of 0s. For an encoded piece of text to work well with both parts, that would need quite a lot of luck. Therefore, a solution that might seem to make sense is to have two separate mappings depending on where in the pack the numbers are going to be encoded: a mapping that is "1 heavy" for the part of the pack that will produce future recursive sections, and a mapping that is "0 heavy" for the rest. In practice, this idea becomes complicated, and in most situations the chances of doing recursions becomes impossible. The problem with the idea is that if we are not extremely lucky, we can end up encoding numbers across boundaries between the two mapping systems. This will produce nonsense when decoded in either mapping system. If we decide to hold back those cards rather than use them, there is nowhere to put them where they will not cause just as much confusion. Therefore, using two (or more) mappings will only work if (a) we are extremely lucky or (b) someone thinks up a clever thing to do with the extra cards.