We represent a move in the same way as (mp, mq), where mp describes how we permute the cubies with a single face rotation, so that cp[mp] is the resulting new arrangement of the cubies after applying the move. To determine the new *orientations* of the cubies, we first apply the same permutation to the initial orientations via cq[mp], then add the *change* in orientations resulting from the move via +mq. The mod 3 simply constrains the results to be in {0,1,2}.

So, how do we represent those changes in orientation? We actually have some freedom in choosing how we do this; that is, there are other choices of six mq vectors for the six face rotations that work. Having come back to look at this again 8 years later, it might be easier to visualize a different choice than the one that I used (more on this later):

Consider the cube to be positioned so that the cube is at the origin, with the front (F), right (R), and up (U) faces in the +x, +y, and +z-axis directions, respectively, as shown here, where we are “holding” the cube by the cubie that we can’t see located at (-1,-1,-1), and the remaining seven non-fixed cubies are numbered as shown.

Each non-fixed cubie could be in one of three different orientations; we need a way to encode these three possibilities. To do this, first note that each cubie has exactly one face that is either green (on the F[ront] face when solved) or blue (on the B[ack] face when solved). No matter where a particular cubie is located, let’s denote its orientation 0 if its green-or-blue face is currently on the F-or-B face, or +1 if it has been rotated counterclockwise (about a ray from the origin through the cubie) from that “0” orientation, or -1 (or +2 since we are working mod 3) if it has been rotated clockwise from that “0” orientation.

Then we can compute what the mq vector should be for each of the six possible face rotations: for both X+ and X- rotations, the mq vector is (0,0,0,0,0,0,0). For both Y+ and Y- rotations, the mq vector is (0,2,1,0,0,1,2), and for both Z+ and Z- rotations, the mq vector is (0,0,0,1,2,2,1).

You can verify that the code works with these mq vectors in the same way as the original code. (I originally enumerated all possible valid sets of mq vectors, and chose a set that minimized the number of non-zero vectors. In hindsight I think the above is much easier to explain :). Also, having settled on this particular choice of mq vectors, we can verify that any single face rotation preserves the invariant that the sum of orientations is zero mod 3.

]]>I really like your post and this representation of the state is super neat!

But I have some questions as well:

1. For the 6 hard-coded moves, I understand \pi, but I am really confused about q:

1) why q in the solved state is zeros(7)?

2) for example, for move X, why its corresponding q is [1, 0, 1, 0, 2, 0, 2]?

3) how does “(cq[mp] + mq) % 3” work exactly in move_cube()?

2. could you also explain why “the orientations of any 6 cubies determine the remaining orientation. We can impose this constraint by requiring the sum modulo 3 of elements of q to be zero.”?

Is there a proof of this?

Thank you!

]]>The “clumpiness” of purely iid Bernoulli trials is indeed a critical part of what’s going on, though. See this paper for a good overview of calculations of distributions of “run lengths.” I’ll follow up shortly with more details in another brief post describing motivation/context for this puzzle.

]]>“Will this one particular toss be T or H” has the answer: 50% chance of either, independent of other flips.

The other question is “How clumpy is the distribution that comes out of this RNG” which is an interesting question indeed but also it suddenly seems much less paradoxical when considered in that light. And now I’m more curious what the histogram of “lengths of streaks” is and how that changes as number of tosses increases. And how, if the “clumpiness” changes, how that would affect the outcome of the “fair bet.”

Does that make sense or am I missing something?

]]>Suppose that we have seen our streak of s = 4 heads and that only two flips remain. To this point we’ll assume that the number of head and number of tail ending streaks are equal. Or set the number of flips to 6 so that we know that no streaks have yet ended.

Then, if next flip is tails, it is no longer possible to start another streak. So, whether the final flip is heads or tails, that sequence ends having seen more tails following a streak of heads than having seen more heads following a streak.

Now consider if the next flip is heads.

If the final flip is a head, then we’d have 2 more heads ending streaks of heads than tails ending streaks. But that counts for only one bet settlement. The extra head is in some sense wasted.

If the final flip is a tail then a head would have ended one streak and a tail would have ended another resulting in a push.

In summary the final two flips and bet results are:

TH -> more tails ending streak.

TT-> more tails end streak.

HT -> push.

HH->more heads ending streak.

Thus 2 ways to have more tails ending a streak, 1 way to have more heads ending the streak and 1 way to have a push.

Bonus question: How does this result in the 15 cent per game advantage?

]]>Two flips only.

If the first flip is Tail, end of the game, result=Tail more (50%)

If the first flip is Head, one more flip, result=HH, Head more (25%) and HT Push(25%)

So, 50% +1, 25% +0, 25% -1,,,but overall, total number of H,T are the same.

]]>Also, in the modified experiment described in the last paragraph, there is an important detail: after each streak of s identical flips (either s heads or s tails), we note whether the subsequent flip is *different*, i.e., whether it “ends the streak” (call this +1) or “extends the streak” (call this -1). Add up the +1/-1 values over the course of the 100 flips, and win if the total is positive, lose if it’s negative, push if it’s zero. (This is not the same as scoring +1 for *heads* and -1 for *tails*. This is part of why I think this problem is interesting; it is not obvious that these two different games should yield different expected returns.)

]]>