Ciphers

Straddling checkerboard

Letters to digits on a board of 28 cells. Eight letters get one digit and the rest get two. The first step of the VIC cipher and of a few puzzles.
IDstraddling-checkerboard23 / 55classical · fractionation
Cipher / Fractionation

Straddling Checkerboard

The VIC board, one digit for common letters and two for the rest.

Keyspace
28! boards × 90 ordered pairs of blanks
Decode
same options back
Works on
board cells, the rest dropped
Family
8 in fractionation
required 0 / 2

Options

keystring
default ETAONRISBCDFGHJKLMPQ/UVWXYZ.
The 28 cells row by row: each letter A-Z once and two fillers such as . and /
blanksstring
default 26
The two blank digits of the top row, each the first digit of a code of two

Access

Createcreate("straddling-checkerboard")
CLIciphers encode straddling-checkerboard 'ATTACK AT DAWN'
Tryplayground with the sample above
Kinpolybius, morse, bacon, tap-code +3

Letters in, digits out. The common letters get one digit each and the rest get two. The message comes out shorter than Polybius makes it. And nobody can tell where one letter ends and the next begins. Unless they have the board.

Swedish communist Per Meurling used it in 1937, in the Spanish Civil War. Later it became the first step of the VIC cipher. That one was the pencil and paper cipher of Reino Häyhänen, a Soviet spy.

The board

Three rows under the digits 0 to 9. The top row holds eight letters and leaves two cells blank. Those two blank digits label the other two rows, ten cells each. That's 28 cells, so 26 letters plus two fillers, usually . and /.

The default is the board from the English Wikipedia page, with 2 and 6 blank:

text
    0 1 2 3 4 5 6 7 8 9
    E T   A O N   R I S
2   B C D F G H J K L M
6   P Q / U V W X Y Z .

A sits on the top row, so it's 3. C is on row 2, column 1, so it's 21. Why does the decoder never get lost? Because a 2 or a 6 always starts a pair. Every other digit is a letter on its own.

ts
const board = create("straddling-checkerboard");
board.encode("ATTACK AT DAWN").text; // "3113212731223655"
board.decode("3113212731223655").text; // "ATTACKATDAWN"

Your own board

key is the board itself, all 28 cells row by row. Every letter A to Z goes in exactly once. The other two cells can be anything else, even the same character twice. blanks names the two blank digits in the order of their rows, so 14 and 41 are different boards.

The GSMG.IO puzzle has one. Its hint reads "A fubcd-king & oracle-queen, thingky mvps, on a sad board". Squash out the repeated letters, add the rest of the alphabet, and that's the board. Pretty, right?

ts
const gsmg = { key: "FUBCDORA.LETHINGKYMVPS/JQZXW", blanks: "14" };
board.decode("15165943121972409169171213758951813141543", gsmg).text;
// "INCASEYOUMANAGETOCRACKTHIS"

That's the first 41 digits of 149. The rest finish the sentence.

What it skips

Encoding turns the text uppercase and drops whatever isn't on the board. Spaces, commas and digits all go. Decoding reads digits only, so 31 13 21 27 is fine.

In the field / was a numeral escape, a digit spelled out after it. Here it's just a cell. It decodes to / and nothing reads the digits after it as numbers. Digits in the plaintext are gone before they could be escaped.

The VIC cipher didn't stop here either. It ran two transpositions over the digits. That part is yours. Alone, the board falls to the same frequency count as any other substitution.

Checked against

The Wikipedia example, both ways. Its second table too, where 3565257935743007 reads back as ANWHRSANROAEER. The GSMG.IO phase 3.2.2 digits give the sentence from the puzzle's public writeup. With / as the filler, and with a second . too.

Errors

A board that isn't 28 cells, or misses a letter, or has one twice, is an InvalidOptionError on key. So is a blanks that isn't two different digits. On decode, text with no digits at all is a CipherError. So is a code that ends on a blank digit, half a pair.