Started on documentation
[szyfrow.git] / docs / szyfrow / bifid.html
1 <!doctype html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
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.bifid API documentation</title>
8 <meta name="description" content="Enciphering and deciphering using the [Bifid cipher](https://en.wikipedia.org/wiki/Bifid_cipher).
9 Also attempts to break messages that use a Bifid …" />
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>
18 </head>
19 <body>
20 <main>
21 <article id="content">
22 <header>
23 <h1 class="title">Module <code>szyfrow.bifid</code></h1>
24 </header>
25 <section id="section-intro">
26 <p>Enciphering and deciphering using the <a href="https://en.wikipedia.org/wiki/Bifid_cipher">Bifid cipher</a>.
27 Also attempts to break messages that use a Bifid cipher.</p>
28 <details class="source">
29 <summary>
30 <span>Expand source code</span>
31 </summary>
32 <pre><code class="python">&#34;&#34;&#34;Enciphering and deciphering using the [Bifid cipher](https://en.wikipedia.org/wiki/Bifid_cipher).
33 Also attempts to break messages that use a Bifid cipher.
34 &#34;&#34;&#34;
35 import multiprocessing
36 from szyfrow.support.utilities import *
37 from szyfrow.support.language_models import *
38 from szyfrow.keyword_cipher import KeywordWrapAlphabet, keyword_cipher_alphabet_of
39
40 def bifid_grid(keyword, wrap_alphabet, letter_mapping):
41 &#34;&#34;&#34;Create the grids for a Bifid cipher
42 &#34;&#34;&#34;
43 cipher_alphabet = keyword_cipher_alphabet_of(keyword, wrap_alphabet)
44 if letter_mapping is None:
45 letter_mapping = {&#39;j&#39;: &#39;i&#39;}
46 translation = &#39;&#39;.maketrans(letter_mapping)
47 cipher_alphabet = cat(collections.OrderedDict.fromkeys(cipher_alphabet.translate(translation)))
48 f_grid = {k: ((i // 5) + 1, (i % 5) + 1)
49 for i, k in enumerate(cipher_alphabet)}
50 r_grid = {((i // 5) + 1, (i % 5) + 1): k
51 for i, k in enumerate(cipher_alphabet)}
52 return translation, f_grid, r_grid
53
54 def bifid_encipher(message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a,
55 letter_mapping=None, period=None, fillvalue=None):
56 &#34;&#34;&#34;Bifid cipher
57
58 &gt;&gt;&gt; bifid_encipher(&#34;indiajelly&#34;, &#39;iguana&#39;)
59 &#39;ibidonhprm&#39;
60 &gt;&gt;&gt; bifid_encipher(&#34;indiacurry&#34;, &#39;iguana&#39;, period=4)
61 &#39;ibnhgaqltm&#39;
62 &gt;&gt;&gt; bifid_encipher(&#34;indiacurry&#34;, &#39;iguana&#39;, period=4, fillvalue=&#39;x&#39;)
63 &#39;ibnhgaqltzml&#39;
64 &#34;&#34;&#34;
65
66 if period:
67 if not fillvalue:
68 raise ValueError(&#34;fillvalue must be given if period is given&#34;)
69 else:
70 p_message = message + pad(len(message), period, fillvalue)
71 else:
72 p_message = message
73
74 translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)
75
76 t_message = p_message.translate(translation)
77 pairs0 = [f_grid[l] for l in sanitise(t_message)]
78 if period:
79 # chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
80 # if len(chunked_pairs[-1]) &lt; period and fillvalue:
81 # chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
82 chunked_pairs = chunks(pairs0, period, fillvalue=None)
83 else:
84 chunked_pairs = [pairs0]
85
86 pairs1 = []
87 for c in chunked_pairs:
88 items = sum(list(list(i) for i in zip(*c)), [])
89 p = [(items[i], items[i+1]) for i in range(0, len(items), 2)]
90 pairs1 += p
91
92 return cat(r_grid[p] for p in pairs1)
93
94
95 def bifid_decipher(message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a,
96 letter_mapping=None, period=None, fillvalue=None):
97 &#34;&#34;&#34;Decipher with bifid cipher
98
99 &gt;&gt;&gt; bifid_decipher(&#39;ibidonhprm&#39;, &#39;iguana&#39;)
100 &#39;indiaielly&#39;
101 &gt;&gt;&gt; bifid_decipher(&#34;ibnhgaqltm&#34;, &#39;iguana&#39;, period=4)
102 &#39;indiacurry&#39;
103 &gt;&gt;&gt; bifid_decipher(&#34;ibnhgaqltzml&#34;, &#39;iguana&#39;, period=4)
104 &#39;indiacurryxx&#39;
105 &#34;&#34;&#34;
106 if period:
107 if not fillvalue:
108 raise ValueError(&#34;fillvalue must be given if period is given&#34;)
109 else:
110 p_message = message + pad(len(message), period, fillvalue)
111 else:
112 p_message = message
113
114 translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)
115
116 t_message = message.translate(translation)
117 pairs0 = [f_grid[l] for l in sanitise(t_message)]
118 if period:
119 # chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
120 # if len(chunked_pairs[-1]) &lt; period and fillvalue:
121 # chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
122 chunked_pairs = chunks(pairs0, period, fillvalue=None)
123 else:
124 chunked_pairs = [pairs0]
125
126 pairs1 = []
127 for c in chunked_pairs:
128 items = [j for i in c for j in i]
129 gap = len(c)
130 p = [(items[i], items[i+gap]) for i in range(gap)]
131 pairs1 += p
132
133 return cat(r_grid[p] for p in pairs1)
134
135
136 def bifid_break(message, wordlist=None, fitness=Pletters, max_period=10,
137 number_of_solutions=1, chunksize=500):
138 &#34;&#34;&#34;Breaks a keyword substitution cipher using a dictionary and
139 frequency analysis
140
141 If `wordlist` is not specified, use
142 [`szyfrow.support.langauge_models.keywords`](support/language_models.html#szyfrow.support.language_models.keywords).
143
144 &gt;&gt;&gt; bifid_break(bifid_encipher(&#39;this is a test message for the &#39; \
145 &#39;keyword decipherment&#39;, &#39;elephant&#39;, wrap_alphabet=KeywordWrapAlphabet.from_last), \
146 wordlist=[&#39;cat&#39;, &#39;elephant&#39;, &#39;kangaroo&#39;]) # doctest: +ELLIPSIS
147 ((&#39;elephant&#39;, &lt;KeywordWrapAlphabet.from_last: 2&gt;, 0), -52.834575011...)
148 &gt;&gt;&gt; bifid_break(bifid_encipher(&#39;this is a test message for the &#39; \
149 &#39;keyword decipherment&#39;, &#39;elephant&#39;, wrap_alphabet=KeywordWrapAlphabet.from_last), \
150 wordlist=[&#39;cat&#39;, &#39;elephant&#39;, &#39;kangaroo&#39;], \
151 number_of_solutions=2) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
152 [((&#39;elephant&#39;, &lt;KeywordWrapAlphabet.from_last: 2&gt;, 0), -52.834575011...),
153 ((&#39;elephant&#39;, &lt;KeywordWrapAlphabet.from_largest: 3&gt;, 0), -52.834575011...)]
154 &#34;&#34;&#34;
155 if wordlist is None:
156 wordlist = keywords
157
158 with multiprocessing.Pool() as pool:
159 helper_args = [(message, word, wrap, period, fitness)
160 for word in wordlist
161 for wrap in KeywordWrapAlphabet
162 for period in range(max_period+1)]
163 # Gotcha: the helper function here needs to be defined at the top level
164 # (limitation of Pool.starmap)
165 breaks = pool.starmap(bifid_break_worker, helper_args, chunksize)
166 if number_of_solutions == 1:
167 return max(breaks, key=lambda k: k[1])
168 else:
169 return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]
170
171 def bifid_break_worker(message, keyword, wrap_alphabet, period, fitness):
172 plaintext = bifid_decipher(message, keyword, wrap_alphabet,
173 period=period, fillvalue=&#39;e&#39;)
174 fit = fitness(plaintext)
175 return (keyword, wrap_alphabet, period), fit
176
177 if __name__ == &#34;__main__&#34;:
178 import doctest</code></pre>
179 </details>
180 </section>
181 <section>
182 </section>
183 <section>
184 </section>
185 <section>
186 <h2 class="section-title" id="header-functions">Functions</h2>
187 <dl>
188 <dt id="szyfrow.bifid.bifid_break"><code class="name flex">
189 <span>def <span class="ident">bifid_break</span></span>(<span>message, wordlist=None, fitness=&lt;function Pletters&gt;, max_period=10, number_of_solutions=1, chunksize=500)</span>
190 </code></dt>
191 <dd>
192 <div class="desc"><p>Breaks a keyword substitution cipher using a dictionary and
193 frequency analysis</p>
194 <p>If <code>wordlist</code> is not specified, use
195 <a href="support/language_models.html#szyfrow.support.language_models.keywords"><code>szyfrow.support.langauge_models.keywords</code></a>.</p>
196 <pre><code class="language-python-repl">&gt;&gt;&gt; bifid_break(bifid_encipher('this is a test message for the ' 'keyword decipherment', 'elephant', wrap_alphabet=KeywordWrapAlphabet.from_last), wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
197 (('elephant', &lt;KeywordWrapAlphabet.from_last: 2&gt;, 0), -52.834575011...)
198 &gt;&gt;&gt; bifid_break(bifid_encipher('this is a test message for the ' 'keyword decipherment', 'elephant', wrap_alphabet=KeywordWrapAlphabet.from_last), wordlist=['cat', 'elephant', 'kangaroo'], number_of_solutions=2) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
199 [(('elephant', &lt;KeywordWrapAlphabet.from_last: 2&gt;, 0), -52.834575011...),
200 (('elephant', &lt;KeywordWrapAlphabet.from_largest: 3&gt;, 0), -52.834575011...)]
201 </code></pre></div>
202 <details class="source">
203 <summary>
204 <span>Expand source code</span>
205 </summary>
206 <pre><code class="python">def bifid_break(message, wordlist=None, fitness=Pletters, max_period=10,
207 number_of_solutions=1, chunksize=500):
208 &#34;&#34;&#34;Breaks a keyword substitution cipher using a dictionary and
209 frequency analysis
210
211 If `wordlist` is not specified, use
212 [`szyfrow.support.langauge_models.keywords`](support/language_models.html#szyfrow.support.language_models.keywords).
213
214 &gt;&gt;&gt; bifid_break(bifid_encipher(&#39;this is a test message for the &#39; \
215 &#39;keyword decipherment&#39;, &#39;elephant&#39;, wrap_alphabet=KeywordWrapAlphabet.from_last), \
216 wordlist=[&#39;cat&#39;, &#39;elephant&#39;, &#39;kangaroo&#39;]) # doctest: +ELLIPSIS
217 ((&#39;elephant&#39;, &lt;KeywordWrapAlphabet.from_last: 2&gt;, 0), -52.834575011...)
218 &gt;&gt;&gt; bifid_break(bifid_encipher(&#39;this is a test message for the &#39; \
219 &#39;keyword decipherment&#39;, &#39;elephant&#39;, wrap_alphabet=KeywordWrapAlphabet.from_last), \
220 wordlist=[&#39;cat&#39;, &#39;elephant&#39;, &#39;kangaroo&#39;], \
221 number_of_solutions=2) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
222 [((&#39;elephant&#39;, &lt;KeywordWrapAlphabet.from_last: 2&gt;, 0), -52.834575011...),
223 ((&#39;elephant&#39;, &lt;KeywordWrapAlphabet.from_largest: 3&gt;, 0), -52.834575011...)]
224 &#34;&#34;&#34;
225 if wordlist is None:
226 wordlist = keywords
227
228 with multiprocessing.Pool() as pool:
229 helper_args = [(message, word, wrap, period, fitness)
230 for word in wordlist
231 for wrap in KeywordWrapAlphabet
232 for period in range(max_period+1)]
233 # Gotcha: the helper function here needs to be defined at the top level
234 # (limitation of Pool.starmap)
235 breaks = pool.starmap(bifid_break_worker, helper_args, chunksize)
236 if number_of_solutions == 1:
237 return max(breaks, key=lambda k: k[1])
238 else:
239 return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]</code></pre>
240 </details>
241 </dd>
242 <dt id="szyfrow.bifid.bifid_break_worker"><code class="name flex">
243 <span>def <span class="ident">bifid_break_worker</span></span>(<span>message, keyword, wrap_alphabet, period, fitness)</span>
244 </code></dt>
245 <dd>
246 <div class="desc"></div>
247 <details class="source">
248 <summary>
249 <span>Expand source code</span>
250 </summary>
251 <pre><code class="python">def bifid_break_worker(message, keyword, wrap_alphabet, period, fitness):
252 plaintext = bifid_decipher(message, keyword, wrap_alphabet,
253 period=period, fillvalue=&#39;e&#39;)
254 fit = fitness(plaintext)
255 return (keyword, wrap_alphabet, period), fit</code></pre>
256 </details>
257 </dd>
258 <dt id="szyfrow.bifid.bifid_decipher"><code class="name flex">
259 <span>def <span class="ident">bifid_decipher</span></span>(<span>message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a, letter_mapping=None, period=None, fillvalue=None)</span>
260 </code></dt>
261 <dd>
262 <div class="desc"><p>Decipher with bifid cipher</p>
263 <pre><code class="language-python-repl">&gt;&gt;&gt; bifid_decipher('ibidonhprm', 'iguana')
264 'indiaielly'
265 &gt;&gt;&gt; bifid_decipher(&quot;ibnhgaqltm&quot;, 'iguana', period=4)
266 'indiacurry'
267 &gt;&gt;&gt; bifid_decipher(&quot;ibnhgaqltzml&quot;, 'iguana', period=4)
268 'indiacurryxx'
269 </code></pre></div>
270 <details class="source">
271 <summary>
272 <span>Expand source code</span>
273 </summary>
274 <pre><code class="python">def bifid_decipher(message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a,
275 letter_mapping=None, period=None, fillvalue=None):
276 &#34;&#34;&#34;Decipher with bifid cipher
277
278 &gt;&gt;&gt; bifid_decipher(&#39;ibidonhprm&#39;, &#39;iguana&#39;)
279 &#39;indiaielly&#39;
280 &gt;&gt;&gt; bifid_decipher(&#34;ibnhgaqltm&#34;, &#39;iguana&#39;, period=4)
281 &#39;indiacurry&#39;
282 &gt;&gt;&gt; bifid_decipher(&#34;ibnhgaqltzml&#34;, &#39;iguana&#39;, period=4)
283 &#39;indiacurryxx&#39;
284 &#34;&#34;&#34;
285 if period:
286 if not fillvalue:
287 raise ValueError(&#34;fillvalue must be given if period is given&#34;)
288 else:
289 p_message = message + pad(len(message), period, fillvalue)
290 else:
291 p_message = message
292
293 translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)
294
295 t_message = message.translate(translation)
296 pairs0 = [f_grid[l] for l in sanitise(t_message)]
297 if period:
298 # chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
299 # if len(chunked_pairs[-1]) &lt; period and fillvalue:
300 # chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
301 chunked_pairs = chunks(pairs0, period, fillvalue=None)
302 else:
303 chunked_pairs = [pairs0]
304
305 pairs1 = []
306 for c in chunked_pairs:
307 items = [j for i in c for j in i]
308 gap = len(c)
309 p = [(items[i], items[i+gap]) for i in range(gap)]
310 pairs1 += p
311
312 return cat(r_grid[p] for p in pairs1) </code></pre>
313 </details>
314 </dd>
315 <dt id="szyfrow.bifid.bifid_encipher"><code class="name flex">
316 <span>def <span class="ident">bifid_encipher</span></span>(<span>message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a, letter_mapping=None, period=None, fillvalue=None)</span>
317 </code></dt>
318 <dd>
319 <div class="desc"><p>Bifid cipher</p>
320 <pre><code class="language-python-repl">&gt;&gt;&gt; bifid_encipher(&quot;indiajelly&quot;, 'iguana')
321 'ibidonhprm'
322 &gt;&gt;&gt; bifid_encipher(&quot;indiacurry&quot;, 'iguana', period=4)
323 'ibnhgaqltm'
324 &gt;&gt;&gt; bifid_encipher(&quot;indiacurry&quot;, 'iguana', period=4, fillvalue='x')
325 'ibnhgaqltzml'
326 </code></pre></div>
327 <details class="source">
328 <summary>
329 <span>Expand source code</span>
330 </summary>
331 <pre><code class="python">def bifid_encipher(message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a,
332 letter_mapping=None, period=None, fillvalue=None):
333 &#34;&#34;&#34;Bifid cipher
334
335 &gt;&gt;&gt; bifid_encipher(&#34;indiajelly&#34;, &#39;iguana&#39;)
336 &#39;ibidonhprm&#39;
337 &gt;&gt;&gt; bifid_encipher(&#34;indiacurry&#34;, &#39;iguana&#39;, period=4)
338 &#39;ibnhgaqltm&#39;
339 &gt;&gt;&gt; bifid_encipher(&#34;indiacurry&#34;, &#39;iguana&#39;, period=4, fillvalue=&#39;x&#39;)
340 &#39;ibnhgaqltzml&#39;
341 &#34;&#34;&#34;
342
343 if period:
344 if not fillvalue:
345 raise ValueError(&#34;fillvalue must be given if period is given&#34;)
346 else:
347 p_message = message + pad(len(message), period, fillvalue)
348 else:
349 p_message = message
350
351 translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)
352
353 t_message = p_message.translate(translation)
354 pairs0 = [f_grid[l] for l in sanitise(t_message)]
355 if period:
356 # chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
357 # if len(chunked_pairs[-1]) &lt; period and fillvalue:
358 # chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
359 chunked_pairs = chunks(pairs0, period, fillvalue=None)
360 else:
361 chunked_pairs = [pairs0]
362
363 pairs1 = []
364 for c in chunked_pairs:
365 items = sum(list(list(i) for i in zip(*c)), [])
366 p = [(items[i], items[i+1]) for i in range(0, len(items), 2)]
367 pairs1 += p
368
369 return cat(r_grid[p] for p in pairs1)</code></pre>
370 </details>
371 </dd>
372 <dt id="szyfrow.bifid.bifid_grid"><code class="name flex">
373 <span>def <span class="ident">bifid_grid</span></span>(<span>keyword, wrap_alphabet, letter_mapping)</span>
374 </code></dt>
375 <dd>
376 <div class="desc"><p>Create the grids for a Bifid cipher</p></div>
377 <details class="source">
378 <summary>
379 <span>Expand source code</span>
380 </summary>
381 <pre><code class="python">def bifid_grid(keyword, wrap_alphabet, letter_mapping):
382 &#34;&#34;&#34;Create the grids for a Bifid cipher
383 &#34;&#34;&#34;
384 cipher_alphabet = keyword_cipher_alphabet_of(keyword, wrap_alphabet)
385 if letter_mapping is None:
386 letter_mapping = {&#39;j&#39;: &#39;i&#39;}
387 translation = &#39;&#39;.maketrans(letter_mapping)
388 cipher_alphabet = cat(collections.OrderedDict.fromkeys(cipher_alphabet.translate(translation)))
389 f_grid = {k: ((i // 5) + 1, (i % 5) + 1)
390 for i, k in enumerate(cipher_alphabet)}
391 r_grid = {((i // 5) + 1, (i % 5) + 1): k
392 for i, k in enumerate(cipher_alphabet)}
393 return translation, f_grid, r_grid</code></pre>
394 </details>
395 </dd>
396 <dt id="szyfrow.bifid.cat"><code class="name flex">
397 <span>def <span class="ident">cat</span></span>(<span>iterable, /)</span>
398 </code></dt>
399 <dd>
400 <div class="desc"><p>Concatenate any number of strings.</p>
401 <p>The string whose method is called is inserted in between each given string.
402 The result is returned as a new string.</p>
403 <p>Example: '.'.join(['ab', 'pq', 'rs']) -&gt; 'ab.pq.rs'</p></div>
404 </dd>
405 <dt id="szyfrow.bifid.lcat"><code class="name flex">
406 <span>def <span class="ident">lcat</span></span>(<span>iterable, /)</span>
407 </code></dt>
408 <dd>
409 <div class="desc"><p>Concatenate any number of strings.</p>
410 <p>The string whose method is called is inserted in between each given string.
411 The result is returned as a new string.</p>
412 <p>Example: '.'.join(['ab', 'pq', 'rs']) -&gt; 'ab.pq.rs'</p></div>
413 </dd>
414 <dt id="szyfrow.bifid.wcat"><code class="name flex">
415 <span>def <span class="ident">wcat</span></span>(<span>iterable, /)</span>
416 </code></dt>
417 <dd>
418 <div class="desc"><p>Concatenate any number of strings.</p>
419 <p>The string whose method is called is inserted in between each given string.
420 The result is returned as a new string.</p>
421 <p>Example: '.'.join(['ab', 'pq', 'rs']) -&gt; 'ab.pq.rs'</p></div>
422 </dd>
423 </dl>
424 </section>
425 <section>
426 </section>
427 </article>
428 <nav id="sidebar">
429 <h1>Index</h1>
430 <div class="toc">
431 <ul></ul>
432 </div>
433 <ul id="index">
434 <li><h3>Super-module</h3>
435 <ul>
436 <li><code><a title="szyfrow" href="index.html">szyfrow</a></code></li>
437 </ul>
438 </li>
439 <li><h3><a href="#header-functions">Functions</a></h3>
440 <ul class="two-column">
441 <li><code><a title="szyfrow.bifid.bifid_break" href="#szyfrow.bifid.bifid_break">bifid_break</a></code></li>
442 <li><code><a title="szyfrow.bifid.bifid_break_worker" href="#szyfrow.bifid.bifid_break_worker">bifid_break_worker</a></code></li>
443 <li><code><a title="szyfrow.bifid.bifid_decipher" href="#szyfrow.bifid.bifid_decipher">bifid_decipher</a></code></li>
444 <li><code><a title="szyfrow.bifid.bifid_encipher" href="#szyfrow.bifid.bifid_encipher">bifid_encipher</a></code></li>
445 <li><code><a title="szyfrow.bifid.bifid_grid" href="#szyfrow.bifid.bifid_grid">bifid_grid</a></code></li>
446 <li><code><a title="szyfrow.bifid.cat" href="#szyfrow.bifid.cat">cat</a></code></li>
447 <li><code><a title="szyfrow.bifid.lcat" href="#szyfrow.bifid.lcat">lcat</a></code></li>
448 <li><code><a title="szyfrow.bifid.wcat" href="#szyfrow.bifid.wcat">wcat</a></code></li>
449 </ul>
450 </li>
451 </ul>
452 </nav>
453 </main>
454 <footer id="footer">
455 <p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.9.2</a>.</p>
456 </footer>
457 </body>
458 </html>