Test cases for the blog post Encoding tic-tac-toe in 15 bits.
Run like this:
# Base4 test
$ cc base4.c && ./a.out
# Base3 test
$ cc base3.c && ./a.out
Try changing the typedef for state
from uint32_t
to uint16_t
. Notice that
the base4 test fails, but the base3 test continues to succeed.
The entire game history (all possible moves / state) from the first move to the 9th move can be encoded into 18 bits. This also allows reconstruction of the game state after every move. The trick is to use the encoding logic for video compressors, start with a keyframe and encode delta frames. In this case, a delta frame would be to determine the number of available spaces, and store the next move. The number of available spaces decrements after every move, so you need less bits. A further space optimisation can be to reuse unused bit values from subsequent moves. Eg. for the 3rd move, there are 7 available fields. This can be packed into 3 bits, with one value spare. The spare can be borrowed to move 1, which has 9 fields. This allows the following optimisation:
1st / 9 / 3 bits (-1)
2nd / 8 / 3 bits (0)
3rd / 7 / 3 bits (+1) (used to complete 1st)
4th / 6 / 3 bits (+2)
5th / 5 / 2 bits (-1) (use 4th extra)
6th / 4 / 2 bits (0)
7th / 3 / 1 bit (-1) use 4th extra
8th / 2 / 1 bit (0)
9th / 1 / 0 bits
Total = 18 bits. This is for the entire game history, from the first to last move, and every board state in between. Decoding this 18 bit mask is not really that challenging, since there are only 3 special cases, and the 9th move requires no bits to store the move (since there is only one possible move). To reconstruct the state at any given time, you need to start from the keyframe and move forward.
18 bits for entire game history.