Er lopen behoorlijk wat seriemoordenaars rond op deze wereld. Sommigen werden nooit gevat en lopen vermoedelijk nog altijd vrij rond, zonder dat we hun identiteit kennen. Dat is bijvoorbeeld het geval voor de Zodiac Killer1. Het pseudoniem van een Amerikaanse crimineel die van december 1968 tot oktober 1969 minstens vijf slachtoffers maakte. Hij daagde regelmatig politie en pers uit met handgeschreven brieven vol bedreigingen, verwijzingen naar nog niet ontdekte slachtoffers en gecodeerde berichten. Daarin beweerde hij dat het ontcijferen van die berichten zijn ware identiteit zou onthullen. Toch tastten de autoriteiten en vele codekrakers wereldwijd jaren in het duister.

Z-340
De brief met de Z-340 code die Zodiac op 8 november 1969 naar de San Francisco Chronicle stuurde, en die pas ontcijferd werd op 5 december 2020.

Meer dan 50 jaar nadat de Zodiac Killer de straten van Noord-Californië begon te terroriseren, werd op 5 december 20202 één van deze mysterieuze berichten eindelijk ontcijferd. Het gaat om een gecodeerd bericht van 340 symbolen — bekend als Z-340 — dat in november 1969 naar de San Fransisco Chronicle was gestuurd. Het internationaal team van amateur codekrakers dat daarin slaagde bestond uit David Oranchak (een softwareontwikkelaar uit Virginia, VSA), Sam Blake (een wiskundige uit Australië) en Jarl Van Eycke (een magazijnier uit België). Helaas bevat het bericht niet voldoende informatie om de Zodiac Killer te kunnen ontmaskeren.

Opgave

Bij het coderen van Z-340 maakte de Zodiac Killer gebruik van een klassieke truc: vervang elke letter door een symbool. Dat had men snel door. Maar het inzicht dat uiteindelijk leidde tot het kraken van de code was dat de letters niet van links naar rechts en van boven naar onder moesten uitgelezen worden. Hij begon nog altijd te schrijven in de linker bovenhoek, maar zette daarna elk volgend symbool één rij naar onder en twee kolommen naar rechts. Voorbij de rechterkant ging hij verder vanaf de linkerkant en voorbij de onderkant ging hij verder vanaf de bovenkant.

Nemen we bijvoorbeeld het bericht:

I've no plans to call on you, Clarice. The world is more interesting with you in it.

Dat bericht bestaat uit 84 karakters die als volgt in een rooster met 4 rijen en 21 kolommen ingevuld zouden worden:

volgorde
Volgorde waarin de cellen van een rooster met 4 rijen en 21 kolommen moeten ingevuld worden bij Zodiaccodering van een bericht met 84 karakters, waarbij we telkens één rij naar onder en twee kolommen naar rechts opschuiven. Voorbij de rechterkant gaan we verder vanaf de linkerkant en voorbij de onderkant gaan we verder vanaf de bovenkant.

Als we deze posities vervangen door hun corresponderende karakters uit het bericht, dan ziet het gecodeerde bericht er als volgt uit:

codering
Ingevuld rooster met 4 rijen en 21 kolommen bij Zodiaccodering van het bericht I've no plans to call on you, Clarice. The world is more interesting with you in it., waarbij we telkens één rij naar onder en twee kolommen naar rechts opschuiven. Voorbij de rechterkant gaan we verder vanaf de linkerkant en voorbij de onderkant gaan we verder vanaf de bovenkant.

We zullen dit de Zodiaccodering over 1 verticale en 2 horizontale posities noemen, ook al laten we het vervangen van karakters door symbolen achterwege. In tekstuele vorm is dit dus de Zodiaccodering van ons voorbeeldbericht over 4 regels:

Iatsou   e    ,ephhlm
 o'ri r yin.wcii rle 
 yorvintliono iastCea
snwoneecgodnut Ttl .l

Gevraagd wordt:

Voorbeeld

In onderstaande voorbeeldsessie gaan we ervan uit dat de tekstbestanden cijfertekst.01.txt3 en cijfertekst.02.txt4 zich in de huidige directory bevinden.

Opmerking

Om toe te laten dat onderstaande voorbeeldsessie rechtstreeks als doctest kan gebruikt worden, hebben we alle backslashes (in de notatie van newlines) vervangen door een dubbele backslash.

Testgevallen waarbij een resultaat afgedrukt (print) wordt, zullen mogelijks kapot gemaakt worden door editors die automatisch witruimte verwijderen op het einde van regels.

>>> bericht = "I've no plans to call on you, Clarice. The world is more interesting with you in it."

>>> lees_cijfertekst('cijfertekst.01.txt5')
['Iatsou   e    ,ephhlm', " o'ri r yin.wcii rle ", ' yorvintliono iastCea', 'snwoneecgodnut Ttl .l']
>>> decodeer('cijfertekst.01.txt6')
"I've no plans to call on you, Clarice. The world is more interesting with you in it."
>>> codeer(bericht, 4)
"Iatsou   e    ,ephhlm\\n o'ri r yin.wcii rle \\n yorvintliono iastCea\\nsnwoneecgodnut Ttl .l"
>>> print(codeer(bericht, 4))
Iatsou   e    ,ephhlm
 o'ri r yin.wcii rle 
 yorvintliono iastCea
snwoneecgodnut Ttl .l

>>> lees_cijfertekst('cijfertekst.02.txt7')
['Ioni TC seiwe  r ooihsrreual', ' d  lnv  tseantn teoococp.yi', ",la'ugnihlo  nirmwiy  t tel."]
>>> decodeer('cijfertekst.02.txt8', verticaal=2, horizontaal=3)
"I've no plans to call on you, Clarice. The world is more interesting with you in it."
>>> codeer(bericht, 3, verticaal=2, horizontaal=3)
"Ioni TC seiwe  r ooihsrreual\\n d  lnv  tseantn teoococp.yi\\n,la'ugnihlo  nirmwiy  t tel."
>>> print(codeer(bericht, 3, verticaal=2, horizontaal=3))
Ioni TC seiwe  r ooihsrreual
 d  lnv  tseantn teoococp.yi
,la'ugnihlo  nirmwiy  t tel.

Epiloog