Storing binary data in playing cards (2014)
timwarriner.com
timwarriner.com
https://en.wikipedia.org/wiki/Lehmer_code
The python library 'permutation' has some functionality around this that's fun to play with:
https://permutation.readthedocs.io/en/stable/#permutation.Pe...
I found new joy in shuffling a deck of cards, after learning that every (proper) shuffle that every human's ever done has returned a unique deck that nobody's ever held before.
edit: I just remembered a guy who made a javascript demo that encodes small strings into a card deck order: https://jerde.net/peter/cards/cards.html (explanation page linked)
It's crazy things have sensible probabilities at all, but surprisingly often the virtual numerator and denominator are of comparable size, despite the magnitudes involved.
> 52!
= 80,658,175,170,943,878,571,660,636,856,403,766,975,289,505,440,883,277,824,000,000,000,000
> 2^225
= 53,919,893,334,301,279,589,334,030,174,039,261,347,274,288,845,081,144,962,207,220,498,432
> 2^226
= 107,839,786,668,602,559,178,668,060,348,078,522,694,548,577,690,162,289,924,414,440,996,864They inexplicably hired my know-it-all ass...
$ julia -E 'log2(factorial(big(52)))'
225.581003123702761946342444376665612911126819036757601937313805865615023286654
(It's also just math, of course, but it's nice to have a quick way to check these things.) echo 'l(f(52))/l(2)' | bc -l
225.58100312370276194868
(`l(x)` is natural log, hence the `/l(2)` to convert to `log2`)Annoyingly, GNU `bc` doesn't have `f(x)`.
> My method stores data within a deck of cards, whilst his uses the deck as a key to encrypt data kept elsewhere. His method is more useful if you want to encrypt a lot of data, while mine could be more useful if you want to smuggle a shorter hidden message without any possibility of detection
Shouldn't be too hard to do even with pen and paper since the 2-adic eval of 52! is large.
If you factor the number 52! (https://wolframalpha.com/input?i=factor+52%21), you can see the term 2^49. If you divide 52! by two 49 times, you are still left with an integer.
[1]: 52 factorial, 52*51*50*...*2*1, the number of different orderings of the 52 cards in a standard deck
The 2-adic valuation of a number is the largest number of times you can divide it by 2 and still get an integer.
https://math.stackexchange.com/questions/434931/elementary-q...Could you elaborate?
It's nothing fancy, get the prime power decomposition of your number and pick the exponent of p.
There's a clever way to do that for a factorial, but I have the Pari/GP app on my phone so I just did:
valuation(52!,2)
which gives the answer 49, so 52! is divisible by 2 forty-nine times. Interestingly chatgpt4 turbo got it right with no extra prodding needed.My calculator says 225 bits, and text suggests the same. Looks like chatgpt4 was wrong as usual:)
For just 52 for example 2 is a prime factor twice, because (52/2)/2 = 13, which is no longer divisible by 2.
Or in other words 52! / (2^49) is an integer, but 52! / (2^50) is not, thus 49 is the correct answer.
Could I recommend phrasing this kind of comment as a question in future? (Notwithstanding the lifehack of making a false statement in the internet being the shortest path to an answer.)
Let me elaborate:
I am not 100% sure what user qsort meant by "binary search", but one of the simplest manual algorithms I can think of is to use input bits as decision points in binary-search-like input state split: you start with 52 cards, depending on first input bit you take top or bottom half of the set, then use 2nd input bit to select top or bottom of the subset, and so on, repeat until you get to a single card. Then place it in the output, remove from input stack, and repeat the procedure again. Note there is no math at all, and this would be pretty trivial to do with just pen & paper.
What would be the resulting # of bits encoded this way? With 54 cards, you'd need to consume 5 to 6 bits, depending on input data. Once you are down to 32 cards, you'd need 5 bits exactly, 31 cards will need 4-5 bits depending on the data, and so on... If I'd calculated this correctly, that's at least 208 bits in the worst case, way more that 51 bits mentioned above.
(Unless there is some other meaning to "51" I am missing? but all I see in the thread are conversations about bit efficiently...)
If you wanted to turn this into an actual protocol, you would presumably flag some permutations as invalid and use the other ones. You would then encode one bit at a time doing a binary search of the set of valid permutations.
Because 52! has a large number of 2s in its factorization, for a careful choice of the valid permutations it should be practical (or at least not significantly more impractical than the OP's proposed method) to perform this by hand because you would be able to "eyeball" most splits of the binary search.
Because your recipient has to be able to determine the reference orientation of the deck, you get 51 bits of extra information from puppy orientation, and another 50 bits of extra information from face-up/face-down orientation.
To place the deck in correct orientation, in preparation for decoding, ensure that the top and bottom card are face up, and that the puppy on the back of the top card isn't upside-down.
An extra 101 bits of information is significant!
And some face cards are not mirror images, but that depends on the deck.
For decks with a symmetrical back design, the following cards have asymmetrical faces:
- The seven of diamonds.
- The ace, three, five, seven and nine of hearts, clubs and spades.
In my deck (a standard design), none of the face cards are asymmetrical.
So there are sixteen cards that carry orientation information, one of which must be used to define the reference orientation of the deck, yielding 15 additional bits of information.
https://sites.math.washington.edu/~billey/classes/562.winter...
https://web.archive.org/web/20180329104930/http://tcode.auck...
a0 + 52(a1 + 51(a2+ 50*(a3 + ...)))
Of course that information would be redundant.