Skip to content

Instantly share code, notes, and snippets.

@jan-g
Created December 9, 2022 13:35
Show Gist options
  • Save jan-g/7579eb2cc7e92d5537f98e8579a192a1 to your computer and use it in GitHub Desktop.
Save jan-g/7579eb2cc7e92d5537f98e8579a192a1 to your computer and use it in GitHub Desktop.
canonicalise cyphers
For simplicity, the cypher spec uses a pair of bytes for each entry: opcode, and (optional) argument
func (w *wrapper) simplify() {
idx := 0
remove := func(idx int) {
copy(w.cypher[idx:], w.cypher[idx+2:])
w.cypher = w.cypher[:len(w.cypher)-2]
}
write := func(idx int, bs ...byte) {
for i2, b := range bs {
w.cypher[idx+i2] = b
}
}
loop:
for idx < len(w.cypher) {
// Simplify the cypher - we could scan forwards rather than backwards; either works
prev, pAux := byte(0), byte(0)
if idx > 0 {
prev = w.cypher[idx-2]
pAux = w.cypher[idx-1]
}
curr, aux := w.cypher[idx], w.cypher[idx+1]
switch curr {
case reverseBits:
if prev == reverseBits {
remove(idx - 2)
remove(idx - 2)
idx -= 2 // Back up
continue loop
}
case xorN:
if aux == 0 {
remove(idx)
continue loop
}
switch prev {
case reverseBits:
write(idx-2, curr, revBits[aux], reverseBits, 0)
idx -= 2
continue loop
case xorN:
write(idx-2, xorN, pAux^aux)
remove(idx)
idx -= 2
continue loop
case xorPos:
// These two can be swapped harmlessly
write(idx-2, xorN, aux, xorPos, 0)
idx -= 2
continue loop
}
case addN:
if aux == 0 {
remove(idx)
continue loop
}
switch prev {
case addN:
write(idx-2, addN, pAux+aux)
remove(idx)
idx -= 2
continue loop
}
case addPos:
case xorPos:
switch prev {
case xorPos:
remove(idx - 2)
remove(idx - 2)
idx -= 2
continue loop
}
}
idx += 2
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment