Task

Implement functions to encrypt and decrypt a message using the straddling checkerboard method. The checkerboard should take a 28 character alphabet (A-Z plus a full stop and an escape character) and two different numbers representing the blanks in the first row. The output will be a series of decimal digits.

Numbers should be encrypted by inserting the escape character before each digit, then including the digit unencrypted. This should be reversed for decryption.




package require Tcl 8.6
 
oo::class create StraddlingCheckerboardCypher {
    variable encmap decmap
    constructor table {
	# Sanity check the table
	foreach ch [lindex $table 0] i {"" 0 1 2 3 4 5 6 7 8 9} {
	    if {$ch eq "" && $i ne "" && [lsearch -index 0 $table $i] < 1} {
		error "bad checkerboard table"
	    }
	}
	# Synthesize the escaped number row
	foreach row $table {
	    if {"/" ni $row} continue
	    set pfx [lindex $row 0][expr {[lsearch -exact $row "/"]-1}]
	    lappend table [list $pfx 0 1 2 3 4 5 6 7 8 9]
	    break
	}
	# Build the actual per-character mapping
	foreach row $table {
	    foreach ch [lrange $row 1 end] n {0 1 2 3 4 5 6 7 8 9} {
		if {$ch in {"" "/"}} continue;  # Skip escape cases
		lappend encmap $ch [lindex $row 0]$n
		lappend decmap [lindex $row 0]$n $ch
	    }
	}
    }
 
    # These methods just sanitize their input and apply the map
    method encode msg {
	string map $encmap [regsub -all {[^A-Z0-9.]} [string toupper $msg] ""]
    }
    method decode msg {
	string map $decmap [regsub -all {[^0-9]} $msg ""]
    }
}