[2019 Day 22] In Review (Slam Shuffle)
Today we're still in space waiting for the ship to be repairs and shuffling cards. But we do get a fly-by of Halley's Comet (1P/Halley). Which has passed apoapsis since this this question originally ran, and is now closer to its next appearance than its last.
Today we're getting another scrambling problem. Part 1 with the small prime sized deck of 10007, and part 2 with a much larger (47-bit) prime. The part 2 deck would have a mass of about 1/1000th of Halley's Comet.
For part 1, it's easy to just manually do it, the shuffles are all simple things. It was not lost on me that this time there wasn't a non-linear thing like a swap in there. But I still put off doing the composition while doing a more efficient part 1 to think about if there wasn't some dynamic trick I might also be missing.
But ultimately, it came down to the fact that, this time, unlike previous scrambles, the shuffle methods are all linear and compositions of linear transformations are linear. I remember the first math class in high school to bring that up... it was right at the end of the term and just mentioned at the very end of the term, dropped like it needed to be in the curriculum and not explored or tested. It wasn't until years later in University that Linear Algebra made the point of how useful this is. And this problem is also a great example why.
The shuffles are (in mod p):
- deal into a new stack (-x - 1)
- cut c (x - c)
- deal with increment m (mx)
They're all linear of the form Ax+B and when you compose them you always get some A'x+B' (ie things don't suddenly explode into quadratics with an x^(2)).
For example, composing a stack deal with an existing Ax+B:
-(Ax+B) - 1 => -Ax + (-B-1), giving A' = -A and B' = -B-1
In general, for an Ax+B and Cx+D:
A(Cx+D) + B => ACx + AD+B, giving A' = AC and B' = AD + B
And with a function that does that, you can compose all the shuffles listed together into one A'x+B', and then compose that with itself the number of times you want to shuffle, producing some A"x + B" representing the entire transformation.
But the number of shuffles we need to do is also a 47-bit number. Fortunately, we can easily divide and conquer. Because if compose the initial full shuffle with itself you get the transformation for shuffling twice. If you compose that with itself, you get 4x, and again gets you 8x, and so on. We've done this for previous problems before. It just happens to be extra good here.
Because we still need to find the answer once we've got the constants for the linear transformation of all the shuffling. Which is to say, what x for our Ax + B ≡ 2020 mod p?
Ax + B ≡ 2020 mod p
Ax ≡ (2020 - B) mod p
x ≡ A^-1 * (2020 - B) mod p
That's our x, and so we're left with needing to find A^(-1), the multiplicative inverse of A mod p (to multiply 2020-B by). Which is where another theorem that's immensely useful comes in: Fermat's Little. Typically expressed as "a^(p) ≡ a mod p" or "a^(p-1) ≡ 1 mod p", but we want to see it as "a⸳a^(p-2) ≡ 1 mod p" here. Because that tells us what to multiple A by to get 1 (which is the inverse), namely A^(p-2). Which can be found with the same divide and conquer we used to shuffle... the exponentiation is just composing Ax with itself p-2 times (with x=1). There's the extra good.
I loved this little math based problem. Linear transformations and Fermat's Little Theorem are two very useful tools to know.