Michiel Florent van Langren1 (Amsterdam, 1598 – Brussel, 1675), die zijn naam verlatijnste als Michael Florentius Langrenus, was een ingenieur, cartograaf en astronoom die bekendheid verwierf doordat hij de eerste was die een kaart van de maan maakte.

maankaart van Langrenus
De maankaart van Michiel van Langren, met onder meer het 'Mare Belgicum' die nu 'Mare Tranquilitatis' heet. Daar vond in 1969 de eerste maanlanding plaats.

In 1634 beschreef hij een oplossing voor het bepalen van de positie van een schip op zee, meer bepaald de lengtegraad. Om te vermijden dat die vroegtijdig zou uitlekken, gebruikte hij een code die bijna 400 jaar lang niet kon ontcijferd worden. Tot de Belg Jarl Van Eycke in januari 2021 de code eindelijk kon kraken, kort nadat hij samen met een Amerikaan en een Australiër het wereldnieuws haalde met het ontcijferen van de vijftig jaar oude code van de beroemde "Zodiac Killer" seriemoordenaar.

code van Langrenus
Deel van de code van Langrenus die bijna 400 jaar lang niet kon ontcijferd worden.

Opgave

De code van Langrenus maakt gebruik van twee bewerkingen: verstrengelen en ontwarren van een bericht. Beide bewerkingen gebruiken een stapgrootte $$n \in \mathbb{N}_0$$ en heffen elkaar op: als we een bericht verstrengelen met stapgrootte $$n$$ en het resultaat terug ontwarren met dezelfde stapgrootte, dan krijgen we terug het oorspronkelijke bericht. Het omgekeerde geldt ook. We leggen uit hoe deze bewerkingen werken voor stapgrootte $$n=4$$ aan de hand van een bericht dat bestaat uit de letters van het alfabet.

alfabet
De $$m=26$$ letters van het alfabet.

Om een bericht van $$m$$ karakters te verstrengelen, maken we eerst een reeks van $$m$$ lege vakjes. We starten bij het eerste vakje waarin we de eerste letter van het bericht invullen. Daarna springen we telkens $$n$$ vakjes vooruit om de volgende letter van het bericht in te vullen, totdat we voorbij het laatste vakje van de reeks springen. Daarna herhalen we deze procedure door achtereenvolgens te starten bij het tweede vakje, het derde vakje, … en het $$n$$-de vakje, en blijven daarbij steeds de volgende letter van het bericht invullen. Voor de $$m=26$$ letters van het alfabet vullen we eerst van links naar rechts de blauwe de vakjes in, daarna de gele vakjes, de groene vakjes en ten slotte de oranje vakjes.

verstrengelen
Verstrengeling van de $$m=26$$ letters van het alfabet met stapgrootte $$n=4$$.

Om een bericht van $$m$$ karakters te ontwarren, starten we bij de eerste letter van het bericht en springen telkens $$n$$ letters vooruit totdat we voorbij het einde van het bericht springen. Daarna herhalen we deze procedure door achtereenvolgens te starten bij de tweede, de derde, … en de $$n$$-de letter van het bericht. Voor de $$m=26$$ letters van het alfabet lezen we eerst van links naar rechts de blauwe letters uit, daarna de gele letters, de groene letters en ten slotte de oranje letters.

ontwarren
Ontwarring van de $$m=26$$ letters van het alfabet met stapgrootte $$n=4$$.

Bij het coderen van een bericht worden eerst alle karakters geschrapt die geen letter zijn. Enkel de letters worden overgehouden en die worden omgezet naar kleine letters. Bovendien worden de eerste negen letters van het alfabet ook nog eens vervangen door een cijfer dat hun positie in het alfabet aangeeft: de letter a staat op positie 1, de letter b op positie 2, … en de letter i op positie 9. Op die manier wordt het bericht

When the sails are strong a ship has no reason to fear turbulence.

bijvoorbeeld eerst omgezet naar

w85nt85s19ls1r5stron71s89p81snor51sonto651rtur2ul5n35

Daarna wordt het bericht verstrengeld. Als we het voorgaande bericht verstrengelen met stapgrootte $$n=3$$ dan krijgen we

won8nt57on16ts588159rspt18u91rls2snu1olrr555ns13ts5ro

Gecodeerde berichten bestaan dus enkel uit cijfers en kleine letters. Om alles nog onleesbaarder te maken, voegt Langrenus op willekeurige plaatsen nog karakters toe die geen cijfers of kleine letters zijn, bijvoorbeeld spaties, hoofdletters of leestekens. Dan wordt het gecodeerde bericht van hierboven bijvoorbeeld verder aangevuld tot

won8ZT MnJWOM Rt5M7o n16ts5 88159r spKVt1 8u91rl s2snAu 1olrr5 55ns13 tsAIJH V5ro

Om een gecodeerd bericht te decoderen, schrappen we eerst alle karakters die geen cijfers of kleine letters zijn. Daarna zetten we de cijfers terug om naar hun corresponderende letter: het cijfer 1 wordt vervangen door de letter a, het cijfer 2 door de letter b, … en het cijfer 9 door de letter i. Het gecodeerd bericht uit bovenstaand voorbeeld wordt dan

wonhntegonaftsehhaeirsptahuiarlsbsnuaolrreeensactsero

Daarna wordt het bericht ontward. Als we bovenstaand bericht ontwarren met stapgrootte $$n=3$$ dan krijgen we terug de opeenvolgende (kleine) letters van het oorspronkelijke bericht:

whenthesailsarestrongashiphasnoreasontofearturbulence

Gevraagd wordt:

Voorbeeld

>>> letter2cijfer('c')
'3'
>>> letter2cijfer('e')
'5'
>>> letter2cijfer('i')
'9'
>>> letter2cijfer('s')
's'

>>> cijfer2letter('3')
'c'
>>> cijfer2letter('5')
'e'
>>> cijfer2letter('9')
'i'
>>> cijfer2letter('s')
's'

>>> ontwarren('abcdefghijklmnopqrstuvwxyz', 3)
'adgjmpsvybehknqtwzcfilorux'
>>> ontwarren('abcdefghijklmnopqrstuvwxyz', 4)
'aeimquybfjnrvzcgkoswdhlptx'
>>> ontwarren('abcdefghijklmnopqrstuvwxyz', 5)
'afkpuzbglqvchmrwdinsxejoty'

>>> decoderen('won8nt57on16ts588159rspt18u91rls2snu1olrr555ns13ts5ro')
'whenthesailsarestrongashiphasnoreasontofearturbulence'
>>> decoderen('won8ZT MnJWOM Rt5M7o n16ts5 88159r spKVt1 8u91rl s2snAu 1olrr5 55ns13 tsAIJH V5ro')
'whenthesailsarestrongashiphasnoreasontofearturbulence'
>>> decoderen('tol2r859 515skr9s n55n5ots 51tot44', stap=5)
'theseadoesnotliketoberestrained'
>>> decoderen('tol2ZTMr JWOMR85M 9515skr9 sn55n5ot KVs51tot 44', 5)
'theseadoesnotliketoberestrained'

>>> verstrengelen('abcdefghijklmnopqrstuvwxyz', 3)
'ajsbktcludmvenwfoxgpyhqzir'
>>> verstrengelen('abcdefghijklmnopqrstuvwxyz', 4)
'ahoubipvcjqwdkrxelsyfmtzgn'
>>> verstrengelen('abcdefghijklmnopqrstuvwxyz', 5)
'aglqvbhmrwcinsxdjotyekpuzf'

>>> coderen('When the sails are strong a ship has no reason to fear turbulence.')
'won8nt57on16ts588159rspt18u91rls2snu1olrr555ns13ts5ro'
>>> coderen('The sea does not like to be restrained.', stap=5)
'tol2r859515skr9sn55n5ots51tot44'