Forty-Three Quintillion on a Commodore 64
By Michael Doornbos
- 9 minutes read - 1785 wordsA standard Rubik’s Cube has 43,252,003,274,489,856,000 reachable positions. People throw that number around in YouTube videos and trivia threads, and it always gets called “43 quintillion” because nobody wants to read all 20 digits out loud. I wanted to understand where it comes from, and then I wanted to compute it on a Commodore 64, which felt like a fair challenge. The C64’s BASIC interpreter only prints 9 significant digits before falling back to scientific notation, and 43 quintillion has 20.
So this is two posts in one. First, the math, which is beautiful once you see it. Then the trick that lets an 8-bit machine print a number twice as wide as its native float can hold.
The cube has 26 pieces, not 27
When you look at a 3x3x3 cube, you see 27 little cubies, but only 26 of them move. The piece in the middle of each face is fixed, attached to the spindle, and the very center of the whole cube is a piece nobody ever sees. The pieces that actually shuffle around split into two groups:
- 8 corner pieces, each showing 3 colors. These live at the corners of the cube.
- 12 edge pieces, each showing 2 colors. These live in the middles of the edges.
That’s it. Centers don’t count because they can’t move relative to each other, and they define which color belongs on which face. White is wherever the white center is.
Every legal scramble shuffles those 20 pieces (8 corners plus 12 edges) into a new configuration, and we want to count how many distinct configurations are reachable.
The four factors
A piece can change in two ways. It can move to a different slot and rotate within its slot. Counting configurations means counting both, separately, for both kinds of pieces.
Corners can be arranged in $8!$ ways. There are 8 corner pieces and 8 corner slots, so the first slot can hold any of 8 corners, the next any of the remaining 7, and so on. That’s $8 \cdot 7 \cdot 6 \cdot 5 \cdot 4 \cdot 3 \cdot 2 \cdot 1 = 40{,}320$.
Each corner has 3 possible orientations. A corner shows three colors, and you can rotate it three ways before it lines up the same way it did at the start. With 8 corners, that’s $3^8 = 6{,}561$ orientation combinations.
Edges can be arranged in $12!$ ways. Same reasoning. 12 edge pieces in 12 slots gives $12! = 479{,}001{,}600$.
Each edge has 2 possible orientations. An edge shows two colors, and there are two ways it can sit in its slot, flipped or not. $2^{12} = 4{,}096$.
Multiply all four together:
$$8! \cdot 3^8 \cdot 12! \cdot 2^{12} = 519{,}024{,}039{,}293{,}878{,}272{,}000$$That’s about 519 quintillion. Twelve times too big.
Why do we divide by 12
If you take a finished cube and pop one piece out, you can stick it back in any way you like. The cube’s mechanism doesn’t care. So the count above (519 quintillion) is the number of cubes you could build, not the number of cubes you can reach by turning faces.
Three of those configurations can’t be reached. They have to be divided out.
Corner orientations sum to a multiple of 3. If you assign each corner a number 0, 1, or 2 based on how it’s twisted, those numbers always add up to a multiple of 3 after any sequence of legal turns. You can’t twist one corner in place. If you tried, you’d have a sum that’s off by 1, which the cube’s geometry forbids. That kills 2/3 of the orientation possibilities. Divide by 3.
Edge orientations sum to an even number. Same idea. Each edge is either “good” or “flipped,” and the count of flipped edges stays even no matter what you do. You can’t flip a single edge. Divide by 2.
Corner and edge permutations have matching parity. This one’s subtler. Every face turn cycles 4 corners and 4 edges, which is an even number of swaps in each group. Whatever parity the corners are in, the edges have to match. You can’t swap two corners without also swapping two edges. Divide by 2.
Three constraints, each independent, so you multiply them. $3 \cdot 2 \cdot 2 = 12$. Divide the big product by 12 and you get:
$$\frac{8! \cdot 3^8 \cdot 12! \cdot 2^{12}}{12} = 43{,}252{,}003{,}274{,}489{,}856{,}000$$There it is.
Typing it into a C64
The obvious move is to just type the formula into BASIC and let the C64 do the work.
PRINT 8*7*6*5*4*3*2*1*3^8*12*11*10*9*8*7*6*5*4*3*2*1*2^12/12
The C64 happily computes this and prints something like:
4.32520033E+19
That’s not the answer. That’s the answer with the last 11 digits replaced by zeros and rounded to fit. The leading $4.32520033$ matches, and after that, we’re flying blind.
The reason is the C64’s number format. BASIC V2 stores every floating-point value in 5 bytes: one byte for the exponent, four bytes for the mantissa. Four bytes of mantissa are 32 bits, which is good for about 9.6 decimal digits of precision. The interpreter prints 9 of them and gives up. There’s no LONG INT or BIGNUM type to fall back on.
If you want all 20 digits, you have to build your own.
Multi-precision the dumb way
The dumb way is the right way for this problem. Pick a DIM array of single-digit numbers and treat each slot as one decimal digit. Position 0 is the ones place, position 1 is the tens, and so on up to however wide you need. Multiplying that array by a small integer is exactly what you learned in third grade. Multiply each digit, propagate the carry, write down the bottom of each result, and pass the top to the next column.
In BASIC:
1000 REM MULTIPLY D() BY M
1010 C=0
1020 FOR J=0 TO N-1
1030 P=D(J)*M+C
1040 D(J)=P-INT(P/10)*10
1050 C=INT(P/10)
1060 NEXT J
1070 IF C=0 THEN RETURN
1080 D(N)=C-INT(C/10)*10
1090 N=N+1
1100 C=INT(C/10)
1110 GOTO 1070
D() is the digit array, N is how many digits are currently in use, and M is the multiplier. The loop walks from low to high, computing each new digit and carry until nothing is left to propagate. If the carry runs off the top, lines 1070-1110 extend the array one digit at a time.
There’s no MOD operator in BASIC V2, so we fake it with P-INT(P/10)*10. That’s just P mod 10.
Now we need to call this for each factor. There’s a small algebra trick that makes the program shorter. We’re computing $8! \cdot 3^8 \cdot 12! \cdot 2^{12} / 12$, and the divisor 12 is $2^2 \cdot 3$. We’re already multiplying by lots of 2s and 3s, so absorb the divide into them:
$$\frac{8! \cdot 3^8 \cdot 12! \cdot 2^{12}}{12} = 8! \cdot 3^7 \cdot 12! \cdot 2^{10}$$Same answer, no division step needed, which saves us from writing a division routine that handles arbitrary-length digit arrays. The full program:
10 REM RUBIK'S CUBE COMBINATIONS ON A C64
20 REM BY MICHAEL DOORNBOS 2026
30 REM 8!*3^7*12!*2^10 = 43252003274489856000
40 PRINT CHR$(147);CHR$(5)
50 PRINT "TOTAL RUBIK'S CUBE POSITIONS"
60 PRINT
70 PRINT "8! * 3^7 * 12! * 2^10 ="
80 PRINT
90 TI$="000000"
100 DIM D(25):D(0)=1:N=1
110 FOR I=2 TO 8:M=I:GOSUB 1000:NEXT
120 FOR I=1 TO 7:M=3:GOSUB 1000:NEXT
130 FOR I=2 TO 12:M=I:GOSUB 1000:NEXT
140 FOR I=1 TO 10:M=2:GOSUB 1000:NEXT
150 FOR J=N-1 TO 0 STEP -1
160 PRINT MID$(STR$(D(J)),2);
170 NEXT J
180 PRINT
190 PRINT
200 PRINT "TOOK"TI/60"SECONDS"
210 END
1000 REM MULTIPLY D() BY M
1010 C=0
1020 FOR J=0 TO N-1
1030 P=D(J)*M+C
1040 D(J)=P-INT(P/10)*10
1050 C=INT(P/10)
1060 NEXT J
1070 IF C=0 THEN RETURN
1080 D(N)=C-INT(C/10)*10
1090 N=N+1
1100 C=INT(C/10)
1110 GOTO 1070
MID$(STR$(D(J)),2) strips the leading space that STR$ adds for positive numbers, so the digits print flush against each other. The array gets walked from high index to low, so the most significant digit comes out first.
Run it on a C64 and the outcome:
The ^ in the formula renders as ↑ because that’s how the C64’s character set draws the up-arrow exponent operator. It’s the same key on the same byte; the C64 just draws it differently.
This is the kind of thing slow computers are good at. You can watch the program do its work because each multiplication is a visible loop. On a modern machine, the same calculation finishes before you take your finger off the Enter key, and you learn nothing. On a C64, it takes long enough that you can almost feel the carries propagating.
Same algorithm, on a Timex 1000
The multi-precision approach doesn’t care what CPU it runs on. Here’s the same algorithm on a real Timex Sinclair 1000 (the US-branded ZX81).
Sinclair BASIC differs from Commodore BASIC in some small ways. Arrays are 1-indexed instead of 0-indexed. Every assignment needs an explicit LET. You can’t put multiple statements on one line, so the C64’s FOR I=2 TO 8:M=I:GOSUB 1000:NEXT becomes four lines. There’s a FAST mode that turns the display off during computation for a 4x speedup.
The formula reads a little weird, though. The ZX81 character set has no exclamation mark, no ^, and no ↑. When the program prints 8! and 12!, the ROM displays the character that occupies the byte’s slot in its tiny character ROM, which here is 5. The exponent gets written as ** because that’s the character pair Sinclair BASIC uses for power. So the formula reads “85 * 37 * 125 * 210 =” instead of “8! * 3^7 * 12! * 2^10 =”. The answer underneath is still right. The cube didn’t change shape because of a character set.
What this is really about
The Rubik’s Cube number is often quoted because it’s big and sounds like physics, but it’s purely combinatorics. Eight things in eight slots, three orientations each. Twelve things in twelve slots, two orientations each. Three parity constraints. Multiply everything out and divide by 12. That’s the number.
The reason it doesn’t fit in a C64 float isn’t anything special about the cube. It’s that 43 quintillion is bigger than $2^{32}$, and the C64’s mantissa is 32 bits. Any 20-digit number would have the same problem. The lesson is that floats are an approximation, and when you need exact answers, you have to count digits yourself, the same way you did in elementary school. The C64 is a great machine for that lesson because it makes the limits visible. The float overflow happens right where you can see it, and the workaround is short enough to type in by hand.
I’ll take “watching a 1-MHz machine compute every digit of 43 quintillion” over “computing it instantly on a laptop and learning nothing” any day.