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.
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.
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:
Als we deze posities vervangen door hun corresponderende karakters uit het bericht, dan ziet het gecodeerde bericht er als volgt uit:
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:
Schrijf een functie lees_cijfertekst waaraan de locatie (str) moet doorgegeven worden van een tekstbestand met de Zodiaccodering van een bericht (een aantal regels die elk evenveel karakters bevatten). De functie moet een lijst (list) teruggeven met de opeenvolgende regels (str) van het gecodeerde bericht.
Schrijf een functie decodeer waaraan de locatie (str) moet doorgegeven worden van een tekstbestand met de Zodiaccodering van een bericht (een aantal regels die elk evenveel karakters bevatten). De functie heeft ook nog een tweede optionele parameter verticaal waaraan kan doorgegeven worden hoeveel posities verticaal naar onder geschoven werd bij het coderen van het bericht (int; standaardwaarde: 1). De functie heeft ook nog een derde optionele parameter horizontaal waaraan kan doorgegeven worden hoeveel posities horizontaal naar rechts geschoven werd bij het coderen van het bericht (int; standaardwaarde: 2). De functie moet het originele bericht (str) teruggeven.
Schrijf een functie codeer waaraan twee argumenten moeten doorgegeven worden: i) een bericht (str) en ii) een getal $$n \in \mathbb{N}_0$$ (int). De functie heeft ook nog een derde optionele parameter verticaal waaraan kan doorgegeven worden hoeveel posities verticaal naar onder moet geschoven worden bij het coderen van het bericht (int; standaardwaarde: 1). De functie heeft ook nog een vierde optionele parameter horizontaal waaraan kan doorgegeven worden hoeveel posities horizontaal naar rechts moet geschoven worden bij het coderen van het bericht (int; standaardwaarde: 2). De functie moet een string (str) met de $$n$$ regels van de Zodiaccodering van het gegeven bericht teruggeven. Hierbij mag de functie ervan uitgaan dat de lengte van het gegeven bericht een veelvoud is van $$n$$ en dat de codering alle cellen van het rooster opvult, zonder dat dit expliciet moet gecontroleerd worden.
In onderstaande voorbeeldsessie gaan we ervan uit dat de tekstbestanden cijfertekst.01.txt3 en cijfertekst.02.txt4 zich in de huidige directory bevinden.
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.