Str8ts String Definitions 2.0
I'm excited to introduce a new scheme to capture and transport the board and progress in minimal fashion for Str8ts and variants continuing my collaboration with
Quintin May a.k.a.
Sasha. We have rolled out an efficient scheme for
Sudoku + variants and for
Killers + variants trying for the shortest strings that pack all important information. Quintin has created a comprehensive documentation library - and if you intend to code - I recommend you browse the following:
There are also some
Test Strings built into links to each solver.
The previous version of this packing algorithm (July 2024 to November 2024) needed three bytes per cell but this new version only requires 2 bytes per cell - so worth the change.
Unpacked Simple Strings
The old method passes the clues as an 81 character string + the black/white cells as an 81 character string, for example:
This will continue to be supported and is a fine definition since it is human readable and easy to construct.
Here is an example of a Str8ts X puzzle:
Packed Strings Version B
Let us consider the sorts of information we want to transport:
- All puzzles need the ability to store progress - which consists of solved cells and candidates.
- We should also retain which large numbers are clues.
- It will be very helpful to include a version header to give vital context for interpreting the data
I have chosen T, U, B and V to represent Str8ts, Str8ts X, Str8ts B and Str8ts BX. All these puzzles are 9x9 so the second symbol in the header is 9. This is version B of packed puzzle strings, so together we get the following four headers:
T9B,
U9B,
B9B and
V9B.
The following table shows that the packed string will essentially be the same for all four variants since we can assume diagonals and boxes based on the header letter. (For convenience the parameter "type=B" etc will also pass this fact in certain places).
Leave Out | |
Encode | |
|
Prefix |
Clues |
Solved |
Notes |
Boxes |
Cages |
Clue Operands |
Black Cells |
Bytes / Cell |
Str8ts |
T9B |
Yes |
Yes |
Yes |
- |
- |
- |
Yes |
? |
Str8ts X |
U9B |
Yes |
Yes |
Yes |
- |
- |
- |
Yes |
? |
Str8ts B |
B9B |
Yes |
Yes |
Yes |
Regular |
- |
- |
Yes |
? |
Str8ts BX |
V9X |
Yes |
Yes |
Yes |
Regular |
- |
- |
Yes |
? |
| |
OFF SET |
- |
- |
- |
OFF SET | |
An example is
The same Str8ts X as above but a couple of steps into the game:
The Body
There are four kinds of content in each cell and they are independent of each other. This means we can use an offset system to create a new number representing the content of the cell. Unlike setting aside certain bits in an integer for each kind of content the offset methods results in a smaller over all number. The four things are:
- White clue
- Black clue
- Solution large number (which will always be a white cell)
- Candidates (also a white cell)
Zero represents an empty cell which will be common in a player but is an illegal number in the solver.
The candidates are the largest payload. We need to store all of 1 to 9 and any combination. This can be done in nine bits if we let each bit represent a number in this way: 1=1, 2=2, 3=4, 4=8, 5=16, 6=32, 7=64, 8=128 and 9=256.
- Whatever the candidate number we will add 29 to it.
- White cell solutions will have 20 added to them so they fall in the range of 20 to 28
- Black cell clues will have 10 added to them so they fall into the range of 10 to 19
(An empty black cell will be 10 in this scheme) - A white cell clue will have 0 added so they fall into the range of 1 to 9.
0 will indicate an empty white cell.
A bit of JavaScript code shows how this is done
for (y = 0; y < 9; y++)
for (x = 0; x < 9; x++) {
n = 0;
if( !isblack && candidates ) // white cell candidates
n = get the candidates as bits
n += 29;
else if( !isblack && solved ) // White cell solution
n = get the solved cell number
n += 20;
else if ( isBlack && cell_num > 0 ) // Black cell clue
n = cell_num;
n += 10;
else if( isBlack ) n = 10; // empty black cell
h = n.toString(36); // convert to base 36
if (h.length < 2) h = '0' + h; // pad the number if not two digits
s += h; // append to string being made
}
To unpack a string we do the following
// This splits a string into an array of elements each 2 characters long
var narr = theString.match(/.{1,2}/g);
if (narr.length != 81) return false; // Sanity length check
for (y = 0; y < 9; y++)
for (x = 0; x < 9; x++) {
n = parseInt(narr[y * 9 + x], 36); // convert base 36 to decimal
clue = false;
black = false;
if( n < 29 ) { // big number
clue = true;
if ( n >= 20 ) { // White cell solution
clue = false;
n -= 20;
} else if ( n >= 10 ) { // black cell clue
clue = (n==10) ? false : true;
black = true;
n -= 10;
} // else White cell clue
cell_num = n; // set the big number for that cell
}
else // number must be candidates
candidates = n - 29;
}
Any problems or questions, let me know in the comments below
Comments
... by: Kai
But anyhow, i love it and willl keep on playing every sunday
Thank you and best regards
Kai
- [Del]