X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;ds=inline;f=docs%2Fszyfrow%2Fsupport%2Futilities.html;fp=docs%2Fszyfrow%2Fsupport%2Futilities.html;h=00365f96f1330d5dc68f6e6b4351254bbc1aad40;hb=b535d9d75e69cc395e8de28c99e38564655e5ac9;hp=0000000000000000000000000000000000000000;hpb=f19a021eabb3222709b9d513839a14c01cfdfd38;p=szyfrow.git diff --git a/docs/szyfrow/support/utilities.html b/docs/szyfrow/support/utilities.html new file mode 100644 index 0000000..00365f9 --- /dev/null +++ b/docs/szyfrow/support/utilities.html @@ -0,0 +1,764 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.9.2" /> +<title>szyfrow.support.utilities API documentation</title> +<meta name="description" content="A mish-mash of utility functions" /> +<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> +<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> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<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> +<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> +<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> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>szyfrow.support.utilities</code></h1> +</header> +<section id="section-intro"> +<p>A mish-mash of utility functions</p> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">"""A mish-mash of utility functions""" + +import string +import collections +import unicodedata +from itertools import zip_longest + +cat = ''.join +"""join a a list of letters into a string.""" + +wcat = ' '.join +"""join a list of words into a string, separated by spaces""" + +lcat = '\n'.join +"""join a list of lines, separated by newline""" + +def pos(letter): + """Return the position of a letter in the alphabet (0-25)""" + if letter in string.ascii_lowercase: + return ord(letter) - ord('a') + elif letter in string.ascii_uppercase: + return ord(letter) - ord('A') + else: + raise ValueError('pos requires input of {} to be an ascii letter'.format(letter)) + +def unpos(number): + """Return the letter in the given position in the alphabet (mod 26)""" + return chr(number % 26 + ord('a')) + +def pad(message_len, group_len, fillvalue): + """Return the padding needed to extend a message to a multiple of group_len + in length. + + fillvalue can be a function or a literal value. If a function, it is called + once for each padded character. Use this with fillvalue=random_english_letter + to pad a message with random letters. + """ + padding_length = group_len - message_len % group_len + if padding_length == group_len: padding_length = 0 + padding = '' + if callable(fillvalue): + for i in range(padding_length): + padding += fillvalue() + else: + padding += fillvalue * padding_length + return padding + +def every_nth(text, n, fillvalue=''): + """Returns n strings, each of which consists of every nth character, + starting with the 0th, 1st, 2nd, ... (n-1)th character + + >>> every_nth(string.ascii_lowercase, 5) + ['afkpuz', 'bglqv', 'chmrw', 'dinsx', 'ejoty'] + >>> every_nth(string.ascii_lowercase, 1) + ['abcdefghijklmnopqrstuvwxyz'] + >>> every_nth(string.ascii_lowercase, 26) # doctest: +NORMALIZE_WHITESPACE + ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] + >>> every_nth(string.ascii_lowercase, 5, fillvalue='!') + ['afkpuz', 'bglqv!', 'chmrw!', 'dinsx!', 'ejoty!'] + """ + split_text = chunks(text, n, fillvalue) + return [cat(l) for l in zip_longest(*split_text, fillvalue=fillvalue)] + +def combine_every_nth(split_text): + """Reforms a text split into every_nth strings + + >>> combine_every_nth(every_nth(string.ascii_lowercase, 5)) + 'abcdefghijklmnopqrstuvwxyz' + >>> combine_every_nth(every_nth(string.ascii_lowercase, 1)) + 'abcdefghijklmnopqrstuvwxyz' + >>> combine_every_nth(every_nth(string.ascii_lowercase, 26)) + 'abcdefghijklmnopqrstuvwxyz' + """ + return cat([cat(l) + for l in zip_longest(*split_text, fillvalue='')]) + +def chunks(text, n, fillvalue=None): + """Split a text into chunks of n characters + + >>> chunks('abcdefghi', 3) + ['abc', 'def', 'ghi'] + >>> chunks('abcdefghi', 4) + ['abcd', 'efgh', 'i'] + >>> chunks('abcdefghi', 4, fillvalue='!') + ['abcd', 'efgh', 'i!!!'] + """ + if fillvalue: + # padding = fillvalue[0] * (n - len(text) % n) + padding = pad(len(text), n, fillvalue) + padded_text = text + padding + else: + padded_text = text + return [(padded_text)[i:i+n] for i in range(0, len(text), n)] + +def transpose(items, transposition): + """Moves items around according to the given transposition + + >>> transpose(['a', 'b', 'c', 'd'], (0,1,2,3)) + ['a', 'b', 'c', 'd'] + >>> transpose(['a', 'b', 'c', 'd'], (3,1,2,0)) + ['d', 'b', 'c', 'a'] + >>> transpose([10,11,12,13,14,15], (3,2,4,1,5,0)) + [13, 12, 14, 11, 15, 10] + """ + transposed = [''] * len(transposition) + for p, t in enumerate(transposition): + transposed[p] = items[t] + return transposed + +def untranspose(items, transposition): + """Undoes a transpose + + >>> untranspose(['a', 'b', 'c', 'd'], [0,1,2,3]) + ['a', 'b', 'c', 'd'] + >>> untranspose(['d', 'b', 'c', 'a'], [3,1,2,0]) + ['a', 'b', 'c', 'd'] + >>> untranspose([13, 12, 14, 11, 15, 10], [3,2,4,1,5,0]) + [10, 11, 12, 13, 14, 15] + """ + transposed = [''] * len(transposition) + for p, t in enumerate(transposition): + transposed[t] = items[p] + return transposed + +def deduplicate(text): + """Return the input string, but with second (and subsequent) occurrences + of a character removed. + """ + return list(collections.OrderedDict.fromkeys(text)) + + +def letters(text): + """Remove all non-alphabetic characters from a text + >>> letters('The Quick') + 'TheQuick' + >>> letters('The Quick BROWN fox jumped! over... the (9lazy) DOG') + 'TheQuickBROWNfoxjumpedoverthelazyDOG' + """ + return ''.join([c for c in text if c in string.ascii_letters]) + +# Special characters for conversion, such as smart quotes. +unaccent_specials = ''.maketrans({"â": "'", 'â': '"', 'â': '"'}) + +def unaccent(text): + """Remove all accents from letters. + It does this by converting the unicode string to decomposed compatability + form, dropping all the combining accents, then re-encoding the bytes. + + >>> unaccent('hello') + 'hello' + >>> unaccent('HELLO') + 'HELLO' + >>> unaccent('héllo') + 'hello' + >>> unaccent('héllö') + 'hello' + >>> unaccent('HÃLLÃ') + 'HELLO' + """ + translated_text = text.translate(unaccent_specials) + return unicodedata.normalize('NFKD', translated_text).\ + encode('ascii', 'ignore').\ + decode('utf-8') + +def sanitise(text): + """Remove all non-alphabetic characters and convert the text to lowercase + + >>> sanitise('The Quick') + 'thequick' + >>> sanitise('The Quick BROWN fox jumped! over... the (9lazy) DOG') + 'thequickbrownfoxjumpedoverthelazydog' + >>> sanitise('HÃLLÃ') + 'hello' + """ + return letters(unaccent(text)).lower() + + +def index_of_coincidence(text): + """Index of coincidence of a string. This is low for random text, + higher for natural langauge. + """ + stext = sanitise(text) + counts = collections.Counter(stext) + denom = len(stext) * (len(text) - 1) / 26 + return ( + sum(max(counts[l] * counts[l] - 1, 0) for l in string.ascii_lowercase) + / + denom + ) + + +def frequencies(text): + """Count the number of occurrences of each character in text + + >>> sorted(frequencies('abcdefabc').items()) + [('a', 2), ('b', 2), ('c', 2), ('d', 1), ('e', 1), ('f', 1)] + >>> sorted(frequencies('the quick brown fox jumped over the lazy ' \ + 'dog').items()) # doctest: +NORMALIZE_WHITESPACE + [(' ', 8), ('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), + ('g', 1), ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), + ('n', 1), ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), + ('v', 1), ('w', 1), ('x', 1), ('y', 1), ('z', 1)] + >>> sorted(frequencies('The Quick BROWN fox jumped! over... the ' \ + '(9lazy) DOG').items()) # doctest: +NORMALIZE_WHITESPACE + [(' ', 8), ('!', 1), ('(', 1), (')', 1), ('.', 3), ('9', 1), ('B', 1), + ('D', 1), ('G', 1), ('N', 1), ('O', 2), ('Q', 1), ('R', 1), ('T', 1), + ('W', 1), ('a', 1), ('c', 1), ('d', 1), ('e', 4), ('f', 1), ('h', 2), + ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('o', 2), ('p', 1), + ('r', 1), ('t', 1), ('u', 2), ('v', 1), ('x', 1), ('y', 1), ('z', 1)] + >>> sorted(frequencies(sanitise('The Quick BROWN fox jumped! over... '\ + 'the (9lazy) DOG')).items()) # doctest: +NORMALIZE_WHITESPACE + [('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), ('g', 1), + ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('n', 1), + ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), ('v', 1), + ('w', 1), ('x', 1), ('y', 1), ('z', 1)] + >>> frequencies('abcdefabcdef')['x'] + 0 + """ + return collections.Counter(c for c in text) + +if __name__ == "__main__": + import doctest + doctest.testmod()</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="szyfrow.support.utilities.cat"><code class="name flex"> +<span>def <span class="ident">cat</span></span>(<span>iterable, /)</span> +</code></dt> +<dd> +<div class="desc"><p>Concatenate any number of strings.</p> +<p>The string whose method is called is inserted in between each given string. +The result is returned as a new string.</p> +<p>Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'</p></div> +</dd> +<dt id="szyfrow.support.utilities.chunks"><code class="name flex"> +<span>def <span class="ident">chunks</span></span>(<span>text, n, fillvalue=None)</span> +</code></dt> +<dd> +<div class="desc"><p>Split a text into chunks of n characters</p> +<pre><code class="language-python-repl">>>> chunks('abcdefghi', 3) +['abc', 'def', 'ghi'] +>>> chunks('abcdefghi', 4) +['abcd', 'efgh', 'i'] +>>> chunks('abcdefghi', 4, fillvalue='!') +['abcd', 'efgh', 'i!!!'] +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def chunks(text, n, fillvalue=None): + """Split a text into chunks of n characters + + >>> chunks('abcdefghi', 3) + ['abc', 'def', 'ghi'] + >>> chunks('abcdefghi', 4) + ['abcd', 'efgh', 'i'] + >>> chunks('abcdefghi', 4, fillvalue='!') + ['abcd', 'efgh', 'i!!!'] + """ + if fillvalue: + # padding = fillvalue[0] * (n - len(text) % n) + padding = pad(len(text), n, fillvalue) + padded_text = text + padding + else: + padded_text = text + return [(padded_text)[i:i+n] for i in range(0, len(text), n)]</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.combine_every_nth"><code class="name flex"> +<span>def <span class="ident">combine_every_nth</span></span>(<span>split_text)</span> +</code></dt> +<dd> +<div class="desc"><p>Reforms a text split into every_nth strings</p> +<pre><code class="language-python-repl">>>> combine_every_nth(every_nth(string.ascii_lowercase, 5)) +'abcdefghijklmnopqrstuvwxyz' +>>> combine_every_nth(every_nth(string.ascii_lowercase, 1)) +'abcdefghijklmnopqrstuvwxyz' +>>> combine_every_nth(every_nth(string.ascii_lowercase, 26)) +'abcdefghijklmnopqrstuvwxyz' +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def combine_every_nth(split_text): + """Reforms a text split into every_nth strings + + >>> combine_every_nth(every_nth(string.ascii_lowercase, 5)) + 'abcdefghijklmnopqrstuvwxyz' + >>> combine_every_nth(every_nth(string.ascii_lowercase, 1)) + 'abcdefghijklmnopqrstuvwxyz' + >>> combine_every_nth(every_nth(string.ascii_lowercase, 26)) + 'abcdefghijklmnopqrstuvwxyz' + """ + return cat([cat(l) + for l in zip_longest(*split_text, fillvalue='')])</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.deduplicate"><code class="name flex"> +<span>def <span class="ident">deduplicate</span></span>(<span>text)</span> +</code></dt> +<dd> +<div class="desc"><p>Return the input string, but with second (and subsequent) occurrences +of a character removed.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def deduplicate(text): + """Return the input string, but with second (and subsequent) occurrences + of a character removed. + """ + return list(collections.OrderedDict.fromkeys(text))</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.every_nth"><code class="name flex"> +<span>def <span class="ident">every_nth</span></span>(<span>text, n, fillvalue='')</span> +</code></dt> +<dd> +<div class="desc"><p>Returns n strings, each of which consists of every nth character, +starting with the 0th, 1st, 2nd, … (n-1)th character</p> +<pre><code class="language-python-repl">>>> every_nth(string.ascii_lowercase, 5) +['afkpuz', 'bglqv', 'chmrw', 'dinsx', 'ejoty'] +>>> every_nth(string.ascii_lowercase, 1) +['abcdefghijklmnopqrstuvwxyz'] +>>> every_nth(string.ascii_lowercase, 26) # doctest: +NORMALIZE_WHITESPACE +['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] +>>> every_nth(string.ascii_lowercase, 5, fillvalue='!') +['afkpuz', 'bglqv!', 'chmrw!', 'dinsx!', 'ejoty!'] +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def every_nth(text, n, fillvalue=''): + """Returns n strings, each of which consists of every nth character, + starting with the 0th, 1st, 2nd, ... (n-1)th character + + >>> every_nth(string.ascii_lowercase, 5) + ['afkpuz', 'bglqv', 'chmrw', 'dinsx', 'ejoty'] + >>> every_nth(string.ascii_lowercase, 1) + ['abcdefghijklmnopqrstuvwxyz'] + >>> every_nth(string.ascii_lowercase, 26) # doctest: +NORMALIZE_WHITESPACE + ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] + >>> every_nth(string.ascii_lowercase, 5, fillvalue='!') + ['afkpuz', 'bglqv!', 'chmrw!', 'dinsx!', 'ejoty!'] + """ + split_text = chunks(text, n, fillvalue) + return [cat(l) for l in zip_longest(*split_text, fillvalue=fillvalue)]</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.frequencies"><code class="name flex"> +<span>def <span class="ident">frequencies</span></span>(<span>text)</span> +</code></dt> +<dd> +<div class="desc"><p>Count the number of occurrences of each character in text</p> +<pre><code class="language-python-repl">>>> sorted(frequencies('abcdefabc').items()) +[('a', 2), ('b', 2), ('c', 2), ('d', 1), ('e', 1), ('f', 1)] +>>> sorted(frequencies('the quick brown fox jumped over the lazy ' 'dog').items()) # doctest: +NORMALIZE_WHITESPACE +[(' ', 8), ('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), + ('g', 1), ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), + ('n', 1), ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), + ('v', 1), ('w', 1), ('x', 1), ('y', 1), ('z', 1)] +>>> sorted(frequencies('The Quick BROWN fox jumped! over... the ' '(9lazy) DOG').items()) # doctest: +NORMALIZE_WHITESPACE +[(' ', 8), ('!', 1), ('(', 1), (')', 1), ('.', 3), ('9', 1), ('B', 1), + ('D', 1), ('G', 1), ('N', 1), ('O', 2), ('Q', 1), ('R', 1), ('T', 1), + ('W', 1), ('a', 1), ('c', 1), ('d', 1), ('e', 4), ('f', 1), ('h', 2), + ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('o', 2), ('p', 1), + ('r', 1), ('t', 1), ('u', 2), ('v', 1), ('x', 1), ('y', 1), ('z', 1)] +>>> sorted(frequencies(sanitise('The Quick BROWN fox jumped! over... ' 'the (9lazy) DOG')).items()) # doctest: +NORMALIZE_WHITESPACE +[('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), ('g', 1), + ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('n', 1), + ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), ('v', 1), + ('w', 1), ('x', 1), ('y', 1), ('z', 1)] +>>> frequencies('abcdefabcdef')['x'] +0 +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def frequencies(text): + """Count the number of occurrences of each character in text + + >>> sorted(frequencies('abcdefabc').items()) + [('a', 2), ('b', 2), ('c', 2), ('d', 1), ('e', 1), ('f', 1)] + >>> sorted(frequencies('the quick brown fox jumped over the lazy ' \ + 'dog').items()) # doctest: +NORMALIZE_WHITESPACE + [(' ', 8), ('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), + ('g', 1), ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), + ('n', 1), ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), + ('v', 1), ('w', 1), ('x', 1), ('y', 1), ('z', 1)] + >>> sorted(frequencies('The Quick BROWN fox jumped! over... the ' \ + '(9lazy) DOG').items()) # doctest: +NORMALIZE_WHITESPACE + [(' ', 8), ('!', 1), ('(', 1), (')', 1), ('.', 3), ('9', 1), ('B', 1), + ('D', 1), ('G', 1), ('N', 1), ('O', 2), ('Q', 1), ('R', 1), ('T', 1), + ('W', 1), ('a', 1), ('c', 1), ('d', 1), ('e', 4), ('f', 1), ('h', 2), + ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('o', 2), ('p', 1), + ('r', 1), ('t', 1), ('u', 2), ('v', 1), ('x', 1), ('y', 1), ('z', 1)] + >>> sorted(frequencies(sanitise('The Quick BROWN fox jumped! over... '\ + 'the (9lazy) DOG')).items()) # doctest: +NORMALIZE_WHITESPACE + [('a', 1), ('b', 1), ('c', 1), ('d', 2), ('e', 4), ('f', 1), ('g', 1), + ('h', 2), ('i', 1), ('j', 1), ('k', 1), ('l', 1), ('m', 1), ('n', 1), + ('o', 4), ('p', 1), ('q', 1), ('r', 2), ('t', 2), ('u', 2), ('v', 1), + ('w', 1), ('x', 1), ('y', 1), ('z', 1)] + >>> frequencies('abcdefabcdef')['x'] + 0 + """ + return collections.Counter(c for c in text)</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.index_of_coincidence"><code class="name flex"> +<span>def <span class="ident">index_of_coincidence</span></span>(<span>text)</span> +</code></dt> +<dd> +<div class="desc"><p>Index of coincidence of a string. This is low for random text, +higher for natural langauge.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def index_of_coincidence(text): + """Index of coincidence of a string. This is low for random text, + higher for natural langauge. + """ + stext = sanitise(text) + counts = collections.Counter(stext) + denom = len(stext) * (len(text) - 1) / 26 + return ( + sum(max(counts[l] * counts[l] - 1, 0) for l in string.ascii_lowercase) + / + denom + )</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.lcat"><code class="name flex"> +<span>def <span class="ident">lcat</span></span>(<span>iterable, /)</span> +</code></dt> +<dd> +<div class="desc"><p>Concatenate any number of strings.</p> +<p>The string whose method is called is inserted in between each given string. +The result is returned as a new string.</p> +<p>Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'</p></div> +</dd> +<dt id="szyfrow.support.utilities.letters"><code class="name flex"> +<span>def <span class="ident">letters</span></span>(<span>text)</span> +</code></dt> +<dd> +<div class="desc"><p>Remove all non-alphabetic characters from a text</p> +<pre><code class="language-python-repl">>>> letters('The Quick') +'TheQuick' +>>> letters('The Quick BROWN fox jumped! over... the (9lazy) DOG') +'TheQuickBROWNfoxjumpedoverthelazyDOG' +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def letters(text): + """Remove all non-alphabetic characters from a text + >>> letters('The Quick') + 'TheQuick' + >>> letters('The Quick BROWN fox jumped! over... the (9lazy) DOG') + 'TheQuickBROWNfoxjumpedoverthelazyDOG' + """ + return ''.join([c for c in text if c in string.ascii_letters])</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.pad"><code class="name flex"> +<span>def <span class="ident">pad</span></span>(<span>message_len, group_len, fillvalue)</span> +</code></dt> +<dd> +<div class="desc"><p>Return the padding needed to extend a message to a multiple of group_len +in length.</p> +<p>fillvalue can be a function or a literal value. If a function, it is called +once for each padded character. Use this with fillvalue=random_english_letter +to pad a message with random letters.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def pad(message_len, group_len, fillvalue): + """Return the padding needed to extend a message to a multiple of group_len + in length. + + fillvalue can be a function or a literal value. If a function, it is called + once for each padded character. Use this with fillvalue=random_english_letter + to pad a message with random letters. + """ + padding_length = group_len - message_len % group_len + if padding_length == group_len: padding_length = 0 + padding = '' + if callable(fillvalue): + for i in range(padding_length): + padding += fillvalue() + else: + padding += fillvalue * padding_length + return padding</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.pos"><code class="name flex"> +<span>def <span class="ident">pos</span></span>(<span>letter)</span> +</code></dt> +<dd> +<div class="desc"><p>Return the position of a letter in the alphabet (0-25)</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def pos(letter): + """Return the position of a letter in the alphabet (0-25)""" + if letter in string.ascii_lowercase: + return ord(letter) - ord('a') + elif letter in string.ascii_uppercase: + return ord(letter) - ord('A') + else: + raise ValueError('pos requires input of {} to be an ascii letter'.format(letter))</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.sanitise"><code class="name flex"> +<span>def <span class="ident">sanitise</span></span>(<span>text)</span> +</code></dt> +<dd> +<div class="desc"><p>Remove all non-alphabetic characters and convert the text to lowercase</p> +<pre><code class="language-python-repl">>>> sanitise('The Quick') +'thequick' +>>> sanitise('The Quick BROWN fox jumped! over... the (9lazy) DOG') +'thequickbrownfoxjumpedoverthelazydog' +>>> sanitise('HÃLLÃ') +'hello' +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def sanitise(text): + """Remove all non-alphabetic characters and convert the text to lowercase + + >>> sanitise('The Quick') + 'thequick' + >>> sanitise('The Quick BROWN fox jumped! over... the (9lazy) DOG') + 'thequickbrownfoxjumpedoverthelazydog' + >>> sanitise('HÃLLÃ') + 'hello' + """ + return letters(unaccent(text)).lower()</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.transpose"><code class="name flex"> +<span>def <span class="ident">transpose</span></span>(<span>items, transposition)</span> +</code></dt> +<dd> +<div class="desc"><p>Moves items around according to the given transposition</p> +<pre><code class="language-python-repl">>>> transpose(['a', 'b', 'c', 'd'], (0,1,2,3)) +['a', 'b', 'c', 'd'] +>>> transpose(['a', 'b', 'c', 'd'], (3,1,2,0)) +['d', 'b', 'c', 'a'] +>>> transpose([10,11,12,13,14,15], (3,2,4,1,5,0)) +[13, 12, 14, 11, 15, 10] +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def transpose(items, transposition): + """Moves items around according to the given transposition + + >>> transpose(['a', 'b', 'c', 'd'], (0,1,2,3)) + ['a', 'b', 'c', 'd'] + >>> transpose(['a', 'b', 'c', 'd'], (3,1,2,0)) + ['d', 'b', 'c', 'a'] + >>> transpose([10,11,12,13,14,15], (3,2,4,1,5,0)) + [13, 12, 14, 11, 15, 10] + """ + transposed = [''] * len(transposition) + for p, t in enumerate(transposition): + transposed[p] = items[t] + return transposed</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.unaccent"><code class="name flex"> +<span>def <span class="ident">unaccent</span></span>(<span>text)</span> +</code></dt> +<dd> +<div class="desc"><p>Remove all accents from letters. +It does this by converting the unicode string to decomposed compatability +form, dropping all the combining accents, then re-encoding the bytes.</p> +<pre><code class="language-python-repl">>>> unaccent('hello') +'hello' +>>> unaccent('HELLO') +'HELLO' +>>> unaccent('héllo') +'hello' +>>> unaccent('héllö') +'hello' +>>> unaccent('HÃLLÃ') +'HELLO' +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def unaccent(text): + """Remove all accents from letters. + It does this by converting the unicode string to decomposed compatability + form, dropping all the combining accents, then re-encoding the bytes. + + >>> unaccent('hello') + 'hello' + >>> unaccent('HELLO') + 'HELLO' + >>> unaccent('héllo') + 'hello' + >>> unaccent('héllö') + 'hello' + >>> unaccent('HÃLLÃ') + 'HELLO' + """ + translated_text = text.translate(unaccent_specials) + return unicodedata.normalize('NFKD', translated_text).\ + encode('ascii', 'ignore').\ + decode('utf-8')</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.unpos"><code class="name flex"> +<span>def <span class="ident">unpos</span></span>(<span>number)</span> +</code></dt> +<dd> +<div class="desc"><p>Return the letter in the given position in the alphabet (mod 26)</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def unpos(number): + """Return the letter in the given position in the alphabet (mod 26)""" + return chr(number % 26 + ord('a'))</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.untranspose"><code class="name flex"> +<span>def <span class="ident">untranspose</span></span>(<span>items, transposition)</span> +</code></dt> +<dd> +<div class="desc"><p>Undoes a transpose</p> +<pre><code class="language-python-repl">>>> untranspose(['a', 'b', 'c', 'd'], [0,1,2,3]) +['a', 'b', 'c', 'd'] +>>> untranspose(['d', 'b', 'c', 'a'], [3,1,2,0]) +['a', 'b', 'c', 'd'] +>>> untranspose([13, 12, 14, 11, 15, 10], [3,2,4,1,5,0]) +[10, 11, 12, 13, 14, 15] +</code></pre></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def untranspose(items, transposition): + """Undoes a transpose + + >>> untranspose(['a', 'b', 'c', 'd'], [0,1,2,3]) + ['a', 'b', 'c', 'd'] + >>> untranspose(['d', 'b', 'c', 'a'], [3,1,2,0]) + ['a', 'b', 'c', 'd'] + >>> untranspose([13, 12, 14, 11, 15, 10], [3,2,4,1,5,0]) + [10, 11, 12, 13, 14, 15] + """ + transposed = [''] * len(transposition) + for p, t in enumerate(transposition): + transposed[t] = items[p] + return transposed</code></pre> +</details> +</dd> +<dt id="szyfrow.support.utilities.wcat"><code class="name flex"> +<span>def <span class="ident">wcat</span></span>(<span>iterable, /)</span> +</code></dt> +<dd> +<div class="desc"><p>Concatenate any number of strings.</p> +<p>The string whose method is called is inserted in between each given string. +The result is returned as a new string.</p> +<p>Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'</p></div> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="szyfrow.support" href="index.html">szyfrow.support</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="szyfrow.support.utilities.cat" href="#szyfrow.support.utilities.cat">cat</a></code></li> +<li><code><a title="szyfrow.support.utilities.chunks" href="#szyfrow.support.utilities.chunks">chunks</a></code></li> +<li><code><a title="szyfrow.support.utilities.combine_every_nth" href="#szyfrow.support.utilities.combine_every_nth">combine_every_nth</a></code></li> +<li><code><a title="szyfrow.support.utilities.deduplicate" href="#szyfrow.support.utilities.deduplicate">deduplicate</a></code></li> +<li><code><a title="szyfrow.support.utilities.every_nth" href="#szyfrow.support.utilities.every_nth">every_nth</a></code></li> +<li><code><a title="szyfrow.support.utilities.frequencies" href="#szyfrow.support.utilities.frequencies">frequencies</a></code></li> +<li><code><a title="szyfrow.support.utilities.index_of_coincidence" href="#szyfrow.support.utilities.index_of_coincidence">index_of_coincidence</a></code></li> +<li><code><a title="szyfrow.support.utilities.lcat" href="#szyfrow.support.utilities.lcat">lcat</a></code></li> +<li><code><a title="szyfrow.support.utilities.letters" href="#szyfrow.support.utilities.letters">letters</a></code></li> +<li><code><a title="szyfrow.support.utilities.pad" href="#szyfrow.support.utilities.pad">pad</a></code></li> +<li><code><a title="szyfrow.support.utilities.pos" href="#szyfrow.support.utilities.pos">pos</a></code></li> +<li><code><a title="szyfrow.support.utilities.sanitise" href="#szyfrow.support.utilities.sanitise">sanitise</a></code></li> +<li><code><a title="szyfrow.support.utilities.transpose" href="#szyfrow.support.utilities.transpose">transpose</a></code></li> +<li><code><a title="szyfrow.support.utilities.unaccent" href="#szyfrow.support.utilities.unaccent">unaccent</a></code></li> +<li><code><a title="szyfrow.support.utilities.unpos" href="#szyfrow.support.utilities.unpos">unpos</a></code></li> +<li><code><a title="szyfrow.support.utilities.untranspose" href="#szyfrow.support.utilities.untranspose">untranspose</a></code></li> +<li><code><a title="szyfrow.support.utilities.wcat" href="#szyfrow.support.utilities.wcat">wcat</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.9.2</a>.</p> +</footer> +</body> +</html> \ No newline at end of file