5 <meta name=
"viewport" content=
"width=device-width, initial-scale=1, minimum-scale=1" />
6 <meta name=
"generator" content=
"pdoc 0.9.2" />
7 <title>szyfrow.cadenus API documentation
</title>
8 <meta name=
"description" content=
"Enciphering and deciphering using the [Cadenus cipher](https://www.thonky.com/kryptos/cadenus-cipher).
9 Also attempts to break messages that use a …" />
10 <link rel=
"preload stylesheet" as=
"style" href=
"https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity=
"sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin
>
11 <link rel=
"preload stylesheet" as=
"style" href=
"https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity=
"sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin
>
12 <link rel=
"stylesheet preload" as=
"style" href=
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin
>
13 <style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:
1.5em}#content{padding:
20px}#sidebar{padding:
30px;overflow:hidden}#sidebar
> *:last-child{margin-bottom:
2cm}.http-server-breadcrumbs{font-size:
130%;margin:
0 0 15px
0}#footer{font-size:
.75em;padding:
5px
30px;border-top:
1px solid #ddd;text-align:right}#footer p{margin:
0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:
30px}h1,h2,h3,h4,h5{font-weight:
300}h1{font-size:
2.5em;line-height:
1.1em}h2{font-size:
1.75em;margin:
1em
0 .50em
0}h3{font-size:
1.4em;margin:
25px
0 10px
0}h4{margin:
0;font-size:
105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:
.2em
0}a{color:#
058;text-decoration:none;transition:color
.3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^=
"header-"]{margin-top:
2em}.ident{color:#
900}pre code{background:#f8f8f8;font-size:
.8em;line-height:
1.4em}code{background:#f2f2f1;padding:
1px
4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:
0;border-top:
1px solid #ccc;border-bottom:
1px solid #ccc;margin:
1em
0;padding:
1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:
10%}#http-server-module-list p{margin-top:
0}.toc ul,#index{list-style-type:none;margin:
0;padding:
0}#index code{background:transparent}#index h3{border-bottom:
1px solid #ddd}#index ul{padding:
0}#index h4{margin-top:
.6em;font-weight:bold}@media (min-width:
200ex){#index .two-column{column-count:
2}}@media (min-width:
300ex){#index .two-column{column-count:
3}}dl{margin-bottom:
2em}dl dl:last-child{margin-bottom:
4em}dd{margin:
0 0 1em
3em}#header-classes + dl
> dd{margin-bottom:
3em}dd dd{margin-left:
2em}dd p{margin:
10px
0}.name{background:#eee;font-weight:bold;font-size:
.85em;padding:
5px
10px;display:inline-block;min-width:
40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name
> span:first-child{white-space:nowrap}.name.class
> span:nth-child(
2){margin-left:
.4em}.inherited{color:#
999;border-left:
5px solid #eee;padding-left:
1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:
400;font-size:
1.25em}.desc h3{font-size:
1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#
666;text-align:right;font-weight:
400;font-size:
.8em;text-transform:uppercase}.source summary
> *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:
1em}.source pre{max-height:
500px;overflow:auto;margin:
0}.source pre code{font-size:
12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\
2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:
1em}img{max-width:
100%}td{padding:
0 .5em}.admonition{padding:
.1em
.5em;margin-bottom:
1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}
</style>
14 <style media=
"screen and (min-width: 700px)">@media screen and (min-width:
700px){#sidebar{width:
30%;height:
100vh;overflow:auto;position:sticky;top:
0}#content{width:
70%;max-width:
100ch;padding:
3em
4em;border-left:
1px solid #ddd}pre code{font-size:
1em}.item .name{font-size:
1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:
1.5em}.toc
> ul
> li{margin-top:
.5em}}
</style>
15 <style media=
"print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#
000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:
" (" attr(href)
")";font-size:
90%}a[href][title]:after{content:none}abbr[title]:after{content:
" (" attr(title)
")"}.ir a:after,a[href^=
"javascript:"]:after,a[href^=
"#"]:after{content:
""}pre,blockquote{border:
1px solid #
999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:
100% !important}@page{margin:
0.5cm}p,h2,h3{orphans:
3;widows:
3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}
</style>
16 <script defer
src=
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity=
"sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin
></script>
17 <script>window.addEventListener('DOMContentLoaded', () =
> hljs.initHighlighting())
</script>
21 <article id=
"content">
23 <h1 class=
"title">Module
<code>szyfrow.cadenus
</code></h1>
25 <section id=
"section-intro">
26 <p>Enciphering and deciphering using the
<a href=
"https://www.thonky.com/kryptos/cadenus-cipher">Cadenus cipher
</a>.
27 Also attempts to break messages that use a Cadenus cipher.
</p>
28 <p>The plaintext is written out in a grid, with one column per letter of the
29 keyword. The plaintext is written out left to right in rows. The plaintext
30 needs to fill
25 rows: if it is shorter, the text is padded; if longer, it is
31 broken into
25-row chunks.
</p>
32 <p>For instance, the
100 letter chunk:
</p>
34 <p>Whoever has made a voyage up the Hudson must remember the Kaatskill mountains.
35 They are a dismembered branch of the great
</p>
37 <p>and the keyword
"wink" would written out as the leftmost grid below.
</p>
38 <p>The columns are then rotated according to the
<em>keycolumn
</em>. For each column, the
39 keyword letter in that column is found in the keycolumn. This identifies a
40 specific row in the grid. That column only is rotated upwards until the selected
41 row is at the top of the column. Each column is rotated independently, according
42 to its keyword letter.
</p>
43 <p>For instance, the middle grid below is formed from the leftmost grid by
44 rotating the first column up four positions, the second column up
17 positions,
45 and so on. (The letters chosen to head the new colums are capitalised in the
47 <p>Finally, each row is transposed given the alphabetic order of the keyword (as
48 seen in the rightmost grid below).
</p>
49 <p>The ciphertext is read out in rows, starting with the now-leftmost column. For
50 the example, the ciphertext would be
</p>
52 <p>antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned'
</p>
54 <pre><code>w i n k w i n k i k n w
55 ------- ------- -------
56 w h o e a o a t n a n t o
57 v e r h z e d l e d e l e
58 a s m a y h e u e e e u h
59 d e a v x d r i s r s i d
60 O y a g vw m r h b r b h m
61 e u p t u r h r d h d r r
62 h e h u t m h i n h n i m
63 d s o n s t e m f e f m t
64 m u s t r a h e g h g e a
65 r e m e q k e a t e t a k
66 m b e r p m s o e s e o m
67 t h e k o t e e h e h e t
68 a a T s n s y a a y a a s
69 k i l l m y u o v u v o y
70 m o u n l a e r g e g r a
71 t a i N k m s m t s t m m
72 s t h e j e u a u u u a e
73 y A r e i b e a n e n a b
74 a d i s h c b p t b t p c
75 m e m b g t h h e h e h t
76 e r e d f r a o r a r o r
77 b r a n e w i s k i k s w
78 c h o f d v o m s o s m v
79 t h e g c a a e l a l e a
80 r e a t b d t e n t n e d
82 <details class=
"source">
84 <span>Expand source code
</span>
86 <pre><code class=
"python">"""Enciphering and deciphering using the [Cadenus cipher](https://www.thonky.com/kryptos/cadenus-cipher).
87 Also attempts to break messages that use a Cadenus cipher.
89 The plaintext is written out in a grid, with one column per letter of the
90 keyword. The plaintext is written out left to right in rows. The plaintext
91 needs to fill
25 rows: if it is shorter, the text is padded; if longer, it is
92 broken into
25-row chunks.
94 For instance, the
100 letter chunk:
96 > Whoever has made a voyage up the Hudson must remember the Kaatskill mountains.
97 > They are a dismembered branch of the great
99 and the keyword
"wink
" would written out as the leftmost grid below.
101 The columns are then rotated according to the _keycolumn_. For each column, the
102 keyword letter in that column is found in the keycolumn. This identifies a
103 specific row in the grid. That column only is rotated upwards until the selected
104 row is at the top of the column. Each column is rotated independently, according
105 to its keyword letter.
107 For instance, the middle grid below is formed from the leftmost grid by
108 rotating the first column up four positions, the second column up
17 positions,
109 and so on. (The letters chosen to head the new colums are capitalised in the
112 Finally, each row is transposed given the alphabetic order of the keyword (as
113 seen in the rightmost grid below).
115 The ciphertext is read out in rows, starting with the now-leftmost column. For
116 the example, the ciphertext would be
118 > antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned
'
121 w i n k w i n k i k n w
122 ------- ------- -------
123 w h o e a o a t n a n t o
124 v e r h z e d l e d e l e
125 a s m a y h e u e e e u h
126 d e a v x d r i s r s i d
127 O y a g vw m r h b r b h m
128 e u p t u r h r d h d r r
129 h e h u t m h i n h n i m
130 d s o n s t e m f e f m t
131 m u s t r a h e g h g e a
132 r e m e q k e a t e t a k
133 m b e r p m s o e s e o m
134 t h e k o t e e h e h e t
135 a a T s n s y a a y a a s
136 k i l l m y u o v u v o y
137 m o u n l a e r g e g r a
138 t a i N k m s m t s t m m
139 s t h e j e u a u u u a e
140 y A r e i b e a n e n a b
141 a d i s h c b p t b t p c
142 m e m b g t h h e h e h t
143 e r e d f r a o r a r o r
144 b r a n e w i s k i k s w
145 c h o f d v o m s o s m v
146 t h e g c a a e l a l e a
147 r e a t b d t e n t n e d
151 from itertools import chain
152 import multiprocessing
153 from szyfrow.support.utilities import *
154 from szyfrow.support.language_models import *
157 def make_cadenus_keycolumn(doubled_letters =
'vw
', start=
'a
', reverse=False):
158 """Makes the key column for a Cadenus cipher (the column down between the
161 >>> make_cadenus_keycolumn()[
'a
']
163 >>> make_cadenus_keycolumn()[
'b
']
165 >>> make_cadenus_keycolumn()[
'c
']
167 >>> make_cadenus_keycolumn()[
'v
']
169 >>> make_cadenus_keycolumn()[
'w
']
171 >>> make_cadenus_keycolumn()[
'z
']
173 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'a
']
175 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'b
']
177 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'c
']
179 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'i
']
181 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'j
']
183 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'v
']
185 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'z
']
188 index_to_remove = string.ascii_lowercase.find(doubled_letters[
0])
189 short_alphabet = string.ascii_lowercase[:index_to_remove] + string.ascii_lowercase[index_to_remove+
1:]
191 short_alphabet = cat(reversed(short_alphabet))
192 start_pos = short_alphabet.find(start)
193 rotated_alphabet = short_alphabet[start_pos:] + short_alphabet[:start_pos]
194 keycolumn = {l: i for i, l in enumerate(rotated_alphabet)}
195 keycolumn[doubled_letters[
0]] = keycolumn[doubled_letters[
1]]
198 def cadenus_encipher(message, keyword, keycolumn, fillvalue=
'a
'):
199 """Encipher with the Cadenus cipher
201 >>> cadenus_encipher(sanitise(
'Whoever has made a voyage up the Hudson
' \
202 'must remember the Kaatskill mountains.
' \
203 'They are a dismembered branch of the great
'), \
205 make_cadenus_keycolumn(doubled_letters=
'vw
', start=
'a
', reverse=True))
206 'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned
'
207 >>> cadenus_encipher(sanitise(
'a severe limitation on the usefulness of
' \
208 'the cadenus is that every message must be
' \
209 'a multiple of twenty-five letters long
'), \
211 make_cadenus_keycolumn(doubled_letters=
'vw
', start=
'a
', reverse=True))
212 'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul
'
214 transpositions = transpositions_of(keyword)
215 enciphered_chunks = []
216 for message_chunk in chunks(message, len(transpositions) *
25,
217 fillvalue=fillvalue):
218 rows = chunks(message_chunk, len(transpositions), fillvalue=fillvalue)
220 rotated_columns = [col[start:] + col[:start] for start, col in zip([keycolumn[l] for l in keyword], columns)]
221 rotated_rows = zip(*rotated_columns)
222 transposed = [transpose(r, transpositions) for r in rotated_rows]
223 enciphered_chunks.append(cat(chain(*transposed)))
224 return cat(enciphered_chunks)
226 def cadenus_decipher(message, keyword, keycolumn, fillvalue=
'a
'):
228 >>> cadenus_decipher(
'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaa
' \
229 'suvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned
', \
231 make_cadenus_keycolumn(reverse=True))
232 'whoeverhasmadeavoyageupthehudsonmustrememberthekaatskillmountainstheyareadismemberedbranchofthegreat
'
233 >>> cadenus_decipher(
'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtof
' \
234 'arenuseieeieltarlmentieetogevesitfaisltngeeuvowul
', \
236 make_cadenus_keycolumn(reverse=True))
237 'aseverelimitationontheusefulnessofthecadenusisthateverymessagemustbeamultipleoftwentyfiveletterslong
'
239 transpositions = transpositions_of(keyword)
240 deciphered_chunks = []
241 for message_chunk in chunks(message, len(transpositions) *
25,
242 fillvalue=fillvalue):
243 rows = chunks(message_chunk, len(transpositions), fillvalue=fillvalue)
244 untransposed_rows = [untranspose(r, transpositions) for r in rows]
245 columns = zip(*untransposed_rows)
246 rotated_columns = [col[-start:] + col[:-start] for start, col in zip([keycolumn[l] for l in keyword], columns)]
247 rotated_rows = zip(*rotated_columns)
248 deciphered_chunks.append(cat(chain(*rotated_rows)))
249 return cat(deciphered_chunks)
253 def cadenus_break(message, wordlist=None,
254 doubled_letters=
'vw
', fitness=Pbigrams):
255 """Breaks a Cadenus cipher using a dictionary and
258 If `wordlist` is not specified, use
259 [`szyfrow.support.langauge_models.keywords`](support/language_models.html#szyfrow.support.language_models.keywords).
264 # c = make_cadenus_keycolumn(reverse=True)
265 # valid_words = [w for w in wordlist
266 # if len(transpositions_of(w)) == len(message) //
25]
267 with multiprocessing.Pool() as pool:
268 results = pool.starmap(cadenus_break_worker,
270 make_cadenus_keycolumn(doubled_letters=doubled_letters,
274 for s in string.ascii_lowercase
275 for r in [True, False]
276 # if max(transpositions_of(w))
<= len(
277 # make_cadenus_keycolumn(
278 # doubled_letters=doubled_letters, start=s, reverse=r))
280 # return list(results)
281 return max(results, key=lambda k: k[
1])
283 def cadenus_break_worker(message, keyword, keycolumn, fitness):
284 # message_chunks = chunks(message,
175)
285 # plaintext =
''.join(cadenus_decipher(c, keyword, keycolumn) for c in message_chunks)
286 plaintext = cadenus_decipher(message, keyword, keycolumn)
287 fit = fitness(plaintext)
288 return (keyword, keycolumn), fit
290 if __name__ ==
"__main__
":
291 import doctest
</code></pre>
299 <h2 class=
"section-title" id=
"header-functions">Functions
</h2>
301 <dt id=
"szyfrow.cadenus.cadenus_break"><code class=
"name flex">
302 <span>def
<span class=
"ident">cadenus_break
</span></span>(
<span>message, wordlist=None, doubled_letters='vw', fitness=
<function Pbigrams
>)
</span>
305 <div class=
"desc"><p>Breaks a Cadenus cipher using a dictionary and
306 frequency analysis
</p>
307 <p>If
<code>wordlist
</code> is not specified, use
308 <a href=
"support/language_models.html#szyfrow.support.language_models.keywords"><code>szyfrow.support.langauge_models.keywords
</code></a>.
</p></div>
309 <details class=
"source">
311 <span>Expand source code
</span>
313 <pre><code class=
"python">def cadenus_break(message, wordlist=None,
314 doubled_letters=
'vw
', fitness=Pbigrams):
315 """Breaks a Cadenus cipher using a dictionary and
318 If `wordlist` is not specified, use
319 [`szyfrow.support.langauge_models.keywords`](support/language_models.html#szyfrow.support.language_models.keywords).
324 # c = make_cadenus_keycolumn(reverse=True)
325 # valid_words = [w for w in wordlist
326 # if len(transpositions_of(w)) == len(message) //
25]
327 with multiprocessing.Pool() as pool:
328 results = pool.starmap(cadenus_break_worker,
330 make_cadenus_keycolumn(doubled_letters=doubled_letters,
334 for s in string.ascii_lowercase
335 for r in [True, False]
336 # if max(transpositions_of(w))
<= len(
337 # make_cadenus_keycolumn(
338 # doubled_letters=doubled_letters, start=s, reverse=r))
340 # return list(results)
341 return max(results, key=lambda k: k[
1])
</code></pre>
344 <dt id=
"szyfrow.cadenus.cadenus_break_worker"><code class=
"name flex">
345 <span>def
<span class=
"ident">cadenus_break_worker
</span></span>(
<span>message, keyword, keycolumn, fitness)
</span>
348 <div class=
"desc"></div>
349 <details class=
"source">
351 <span>Expand source code
</span>
353 <pre><code class=
"python">def cadenus_break_worker(message, keyword, keycolumn, fitness):
354 # message_chunks = chunks(message,
175)
355 # plaintext =
''.join(cadenus_decipher(c, keyword, keycolumn) for c in message_chunks)
356 plaintext = cadenus_decipher(message, keyword, keycolumn)
357 fit = fitness(plaintext)
358 return (keyword, keycolumn), fit
</code></pre>
361 <dt id=
"szyfrow.cadenus.cadenus_decipher"><code class=
"name flex">
362 <span>def
<span class=
"ident">cadenus_decipher
</span></span>(
<span>message, keyword, keycolumn, fillvalue='a')
</span>
365 <div class=
"desc"><pre><code class=
"language-python-repl">>>> cadenus_decipher('antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaa' 'suvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned', 'wink', make_cadenus_keycolumn(reverse=True))
366 'whoeverhasmadeavoyageupthehudsonmustrememberthekaatskillmountainstheyareadismemberedbranchofthegreat'
367 >>> cadenus_decipher('systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtof' 'arenuseieeieltarlmentieetogevesitfaisltngeeuvowul', 'easy', make_cadenus_keycolumn(reverse=True))
368 'aseverelimitationontheusefulnessofthecadenusisthateverymessagemustbeamultipleoftwentyfiveletterslong'
370 <details class=
"source">
372 <span>Expand source code
</span>
374 <pre><code class=
"python">def cadenus_decipher(message, keyword, keycolumn, fillvalue=
'a
'):
376 >>> cadenus_decipher(
'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaa
' \
377 'suvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned
', \
379 make_cadenus_keycolumn(reverse=True))
380 'whoeverhasmadeavoyageupthehudsonmustrememberthekaatskillmountainstheyareadismemberedbranchofthegreat
'
381 >>> cadenus_decipher(
'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtof
' \
382 'arenuseieeieltarlmentieetogevesitfaisltngeeuvowul
', \
384 make_cadenus_keycolumn(reverse=True))
385 'aseverelimitationontheusefulnessofthecadenusisthateverymessagemustbeamultipleoftwentyfiveletterslong
'
387 transpositions = transpositions_of(keyword)
388 deciphered_chunks = []
389 for message_chunk in chunks(message, len(transpositions) *
25,
390 fillvalue=fillvalue):
391 rows = chunks(message_chunk, len(transpositions), fillvalue=fillvalue)
392 untransposed_rows = [untranspose(r, transpositions) for r in rows]
393 columns = zip(*untransposed_rows)
394 rotated_columns = [col[-start:] + col[:-start] for start, col in zip([keycolumn[l] for l in keyword], columns)]
395 rotated_rows = zip(*rotated_columns)
396 deciphered_chunks.append(cat(chain(*rotated_rows)))
397 return cat(deciphered_chunks)
</code></pre>
400 <dt id=
"szyfrow.cadenus.cadenus_encipher"><code class=
"name flex">
401 <span>def
<span class=
"ident">cadenus_encipher
</span></span>(
<span>message, keyword, keycolumn, fillvalue='a')
</span>
404 <div class=
"desc"><p>Encipher with the Cadenus cipher
</p>
405 <pre><code class=
"language-python-repl">>>> cadenus_encipher(sanitise('Whoever has made a voyage up the Hudson ' 'must remember the Kaatskill mountains. ' 'They are a dismembered branch of the great'), 'wink', make_cadenus_keycolumn(doubled_letters='vw', start='a', reverse=True))
406 'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned'
407 >>> cadenus_encipher(sanitise('a severe limitation on the usefulness of ' 'the cadenus is that every message must be ' 'a multiple of twenty-five letters long'), 'easy', make_cadenus_keycolumn(doubled_letters='vw', start='a', reverse=True))
408 'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul'
410 <details class=
"source">
412 <span>Expand source code
</span>
414 <pre><code class=
"python">def cadenus_encipher(message, keyword, keycolumn, fillvalue=
'a
'):
415 """Encipher with the Cadenus cipher
417 >>> cadenus_encipher(sanitise(
'Whoever has made a voyage up the Hudson
' \
418 'must remember the Kaatskill mountains.
' \
419 'They are a dismembered branch of the great
'), \
421 make_cadenus_keycolumn(doubled_letters=
'vw
', start=
'a
', reverse=True))
422 'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned
'
423 >>> cadenus_encipher(sanitise(
'a severe limitation on the usefulness of
' \
424 'the cadenus is that every message must be
' \
425 'a multiple of twenty-five letters long
'), \
427 make_cadenus_keycolumn(doubled_letters=
'vw
', start=
'a
', reverse=True))
428 'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul
'
430 transpositions = transpositions_of(keyword)
431 enciphered_chunks = []
432 for message_chunk in chunks(message, len(transpositions) *
25,
433 fillvalue=fillvalue):
434 rows = chunks(message_chunk, len(transpositions), fillvalue=fillvalue)
436 rotated_columns = [col[start:] + col[:start] for start, col in zip([keycolumn[l] for l in keyword], columns)]
437 rotated_rows = zip(*rotated_columns)
438 transposed = [transpose(r, transpositions) for r in rotated_rows]
439 enciphered_chunks.append(cat(chain(*transposed)))
440 return cat(enciphered_chunks)
</code></pre>
443 <dt id=
"szyfrow.cadenus.cat"><code class=
"name flex">
444 <span>def
<span class=
"ident">cat
</span></span>(
<span>iterable, /)
</span>
447 <div class=
"desc"><p>Concatenate any number of strings.
</p>
448 <p>The string whose method is called is inserted in between each given string.
449 The result is returned as a new string.
</p>
450 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
452 <dt id=
"szyfrow.cadenus.lcat"><code class=
"name flex">
453 <span>def
<span class=
"ident">lcat
</span></span>(
<span>iterable, /)
</span>
456 <div class=
"desc"><p>Concatenate any number of strings.
</p>
457 <p>The string whose method is called is inserted in between each given string.
458 The result is returned as a new string.
</p>
459 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
461 <dt id=
"szyfrow.cadenus.make_cadenus_keycolumn"><code class=
"name flex">
462 <span>def
<span class=
"ident">make_cadenus_keycolumn
</span></span>(
<span>doubled_letters='vw', start='a', reverse=False)
</span>
465 <div class=
"desc"><p>Makes the key column for a Cadenus cipher (the column down between the
467 <pre><code class=
"language-python-repl">>>> make_cadenus_keycolumn()['a']
469 >>> make_cadenus_keycolumn()['b']
471 >>> make_cadenus_keycolumn()['c']
473 >>> make_cadenus_keycolumn()['v']
475 >>> make_cadenus_keycolumn()['w']
477 >>> make_cadenus_keycolumn()['z']
479 >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['a']
481 >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['b']
483 >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['c']
485 >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['i']
487 >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['j']
489 >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['v']
491 >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['z']
494 <details class=
"source">
496 <span>Expand source code
</span>
498 <pre><code class=
"python">def make_cadenus_keycolumn(doubled_letters =
'vw
', start=
'a
', reverse=False):
499 """Makes the key column for a Cadenus cipher (the column down between the
502 >>> make_cadenus_keycolumn()[
'a
']
504 >>> make_cadenus_keycolumn()[
'b
']
506 >>> make_cadenus_keycolumn()[
'c
']
508 >>> make_cadenus_keycolumn()[
'v
']
510 >>> make_cadenus_keycolumn()[
'w
']
512 >>> make_cadenus_keycolumn()[
'z
']
514 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'a
']
516 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'b
']
518 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'c
']
520 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'i
']
522 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'j
']
524 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'v
']
526 >>> make_cadenus_keycolumn(doubled_letters=
'ij
', start=
'b
', reverse=True)[
'z
']
529 index_to_remove = string.ascii_lowercase.find(doubled_letters[
0])
530 short_alphabet = string.ascii_lowercase[:index_to_remove] + string.ascii_lowercase[index_to_remove+
1:]
532 short_alphabet = cat(reversed(short_alphabet))
533 start_pos = short_alphabet.find(start)
534 rotated_alphabet = short_alphabet[start_pos:] + short_alphabet[:start_pos]
535 keycolumn = {l: i for i, l in enumerate(rotated_alphabet)}
536 keycolumn[doubled_letters[
0]] = keycolumn[doubled_letters[
1]]
537 return keycolumn
</code></pre>
540 <dt id=
"szyfrow.cadenus.wcat"><code class=
"name flex">
541 <span>def
<span class=
"ident">wcat
</span></span>(
<span>iterable, /)
</span>
544 <div class=
"desc"><p>Concatenate any number of strings.
</p>
545 <p>The string whose method is called is inserted in between each given string.
546 The result is returned as a new string.
</p>
547 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
560 <li><h3>Super-module
</h3>
562 <li><code><a title=
"szyfrow" href=
"index.html">szyfrow
</a></code></li>
565 <li><h3><a href=
"#header-functions">Functions
</a></h3>
567 <li><code><a title=
"szyfrow.cadenus.cadenus_break" href=
"#szyfrow.cadenus.cadenus_break">cadenus_break
</a></code></li>
568 <li><code><a title=
"szyfrow.cadenus.cadenus_break_worker" href=
"#szyfrow.cadenus.cadenus_break_worker">cadenus_break_worker
</a></code></li>
569 <li><code><a title=
"szyfrow.cadenus.cadenus_decipher" href=
"#szyfrow.cadenus.cadenus_decipher">cadenus_decipher
</a></code></li>
570 <li><code><a title=
"szyfrow.cadenus.cadenus_encipher" href=
"#szyfrow.cadenus.cadenus_encipher">cadenus_encipher
</a></code></li>
571 <li><code><a title=
"szyfrow.cadenus.cat" href=
"#szyfrow.cadenus.cat">cat
</a></code></li>
572 <li><code><a title=
"szyfrow.cadenus.lcat" href=
"#szyfrow.cadenus.lcat">lcat
</a></code></li>
573 <li><code><a title=
"szyfrow.cadenus.make_cadenus_keycolumn" href=
"#szyfrow.cadenus.make_cadenus_keycolumn">make_cadenus_keycolumn
</a></code></li>
574 <li><code><a title=
"szyfrow.cadenus.wcat" href=
"#szyfrow.cadenus.wcat">wcat
</a></code></li>
581 <p>Generated by
<a href=
"https://pdoc3.github.io/pdoc"><cite>pdoc
</cite> 0.9.2</a>.
</p>