Michiel Florent van Langren1 (Amsterdam, 1598 – Brussels, 1675), who Latinized his name as Langrenus, was an astronomer and cartographer of the Low Countries in the service of the Spanish Monarchy. In 1645, he published the first known map of the Moon with a nomenclature.

Langren's lunar map
Michiel van Langren's lunar map, including the 'Mare Belgicum' (now called 'Mare Tranquilitatis') where the first moon landing took place in 1969.

In 1634 he described a solution for determining the position of a ship at sea, more specifically its longitude. To prevent it from being leaked prematurely, he used a code that could not be deciphered for nearly 400 years. Until the Belgian Jarl Van Eycke was finally able to crack the code in January 2021, shortly after he made world news together with an American and an Australian for deciphering the 50-year-old code of the famous "Zodiac Killer" serial killer.

code of Langrenus
Part of Langrenus's code that could not be decoded for nearly 400 years.

Assignment

Langrenus' cipher uses two operations: entangling and disentangling a message. Both operations use a step size $$n \in \mathbb{N}_0$$ and cancel each other out: if we entangle a message with step size $$n$$ and disentangle the result with the same step size, we get back the original message. The reverse is also true. We explain how these operations work for step size $$n=4$$ using a message consisting of the letters of the alphabet.

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

To entangle a message of $$m$$ characters, we first create a sequence of $$m$$ empty boxes. We start filling the first box with the first letter of the message. Then we repeatedly jump forward $$n$$ boxes and fill it with the next letter of the message, until we jump past the last box in the sequence. We then repeat this procedure by successively starting at the second box, the third box, … and the $$n$$-th box, while we continue filling the boxes with the next letters of the message. For the $$m=26$$ letters of the alphabet, we first fill the blue boxes from left to right, then the yellow boxes, the green boxes and finally the orange boxes.

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

To disentangle a message of $$m$$ characters, we start at the first letter of the message and repeatedly jump forward $$n$$ letters until we jump past the end of the message. Then we repeat this procedure starting with the second, third, … and the $$n$$-th letter of the message. For the $$m=26$$ letters of the alphabet, we first read the blue letters from left to right, then the yellow letters, the green letters and finally the orange letters.

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

Encoding a message starts by discarding all characters that are not letters. Only the letters are retained and are converted to lowercase. In addition, the first nine letters of the alphabet are also replaced by a digit that indicates their position in the alphabet: the letter a is at position 1, the letter b at position 2, … and the letter i at position 9. This way, the message

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

is converted to

w85nt85s19ls1r5stron71s89p81snor51sonto651rtur2ul5n35

The resulting message is entangled. If we entangle the previous message with step size $$n=3$$ we get

won8nt57on16ts588159rspt18u91rls2snu1olrr555ns13ts5ro

A ciphertext (an encoded message) therefore only contains digits and lowercase letters. To make everything even more illegible, Langrenus inserts some random characters that are no digits or lowercase letters, for example spaces, uppercase letters or punctuation. For example, the above ciphertext could be scrambled somewhat more as

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

Decoding a ciphertext starts by discarding all characters that are no digits or lowercase letters. Then, the digits are converted back to their corresponding letter: the digit 1 is replaced by the letter a, the digit 2 by the letter b, … and the digit 9 by the letter i. The ciphertext from the example above then becomes

wonhntegonaftsehhaeirsptahuiarlsbsnuaolrreeensactsero

The resulting message is disentangled. Disentangling the previous message with step size $$n=3$$ yields the consecutive (lowercase) letters of the original message:

whenthesailsarestrongashiphasnoreasontofearturbulence

Your task:

Example

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

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

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

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

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

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