From aacbb431282cd61e2697e4318c8522bce35a4444 Mon Sep 17 00:00:00 2001 From: Job van der Wal Date: Wed, 17 Nov 2021 13:48:23 +0100 Subject: [PATCH 01/12] First three fixed files --- .../practice/affine-cipher/.meta/example.py | 26 ++++++++++--------- .../practice/all-your-base/.meta/example.py | 2 +- .../practice/alphametics/.meta/example.py | 17 ++++++------ 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/exercises/practice/affine-cipher/.meta/example.py b/exercises/practice/affine-cipher/.meta/example.py index c655c4546a..46b555e364 100644 --- a/exercises/practice/affine-cipher/.meta/example.py +++ b/exercises/practice/affine-cipher/.meta/example.py @@ -1,17 +1,17 @@ BLKSZ = 5 -ALPHSZ = 26 +ALPHABET = 26 -def modInverse(a, ALPHSZ): - a = a % ALPHSZ - for x in range(1, ALPHSZ): - if ((a * x) % ALPHSZ == 1): - return x +def mod_inverse(a, alphabet): + a = a % alphabet + for idx in range(1, alphabet): + if (a * idx) % alphabet == 1: + return idx return 1 def translate(text, a, b, mode): - inv = modInverse(a, ALPHSZ) + inv = mod_inverse(a, ALPHABET) if inv == 1: raise ValueError("a and m must be coprime.") @@ -23,19 +23,21 @@ def translate(text, a, b, mode): chars.append(c) continue if mode == 0: - new = (a * orig + b) % ALPHSZ + new = (a * orig + b) % ALPHABET elif mode == 1: - new = (inv * (orig - b)) % ALPHSZ + new = (inv * (orig - b)) % ALPHABET chars.append(chr(new + 97)) - return ''.join(chars) + return "".join(chars) def encode(plain, a, b): cipher = translate(plain, a, b, 0) - return " ".join([cipher[i:i + BLKSZ] - for i in range(0, len(cipher), BLKSZ)]) + return " ".join([cipher[idx:idx + BLKSZ] + for idx in range(0, len(cipher), BLKSZ)]) def decode(ciphered, a, b): return translate(ciphered, a, b, 1) + +print(mod_inverse(5, ALPHABET)) diff --git a/exercises/practice/all-your-base/.meta/example.py b/exercises/practice/all-your-base/.meta/example.py index bce92f831b..cba65c0667 100644 --- a/exercises/practice/all-your-base/.meta/example.py +++ b/exercises/practice/all-your-base/.meta/example.py @@ -1,5 +1,5 @@ def from_digits(digits, base): - return sum(n * base ** i for i, n in enumerate(reversed(digits))) + return sum(n * base ** idx for idx, n in enumerate(reversed(digits))) def to_digits(number, base_to): diff --git a/exercises/practice/alphametics/.meta/example.py b/exercises/practice/alphametics/.meta/example.py index d72610822e..4d16a676c3 100644 --- a/exercises/practice/alphametics/.meta/example.py +++ b/exercises/practice/alphametics/.meta/example.py @@ -1,4 +1,3 @@ -from itertools import permutations, chain, product """ This solution will first parse the alphametic expression grouping and counting letters buy digit ranks @@ -10,8 +9,10 @@ to reduce the number of permutations """ +from itertools import permutations, chain, product + -def digPerms(digset, nzcharset, okzcharset): +def dig_perms(digset, nzcharset, okzcharset): """This function creates permutations given the set of digits, letters not alllowed to be 0, and letters allowed to be 0 """ @@ -48,7 +49,7 @@ def digPerms(digset, nzcharset, okzcharset): poslst))) -def check_rec(eqparams, tracecombo=(dict(), 0, set(range(10))), p=0): +def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), p=0): """This function recursively traces a parsed expression from lowest digits to highest, generating additional digits when necessary checking the digit sum is divisible by 10, carrying the multiple of 10 @@ -75,7 +76,7 @@ def check_rec(eqparams, tracecombo=(dict(), 0, set(range(10))), p=0): else: # Otherwise the solution in this branch is not found # return empty - return dict() + return {} diglets = uchars[p] # all new unique letters from the current level partsum = cover # Carry over from lower level remexp = [] # TBD letters @@ -88,7 +89,7 @@ def check_rec(eqparams, tracecombo=(dict(), 0, set(range(10))), p=0): remexp.append((c, v)) # Generate permutations for the remaining digits and currecnt level # non-zero letters and zero-allowed letters - for newdigs in digPerms(remdigs, unzchars[p], uokzchars[p]): + for newdigs in dig_perms(remdigs, unzchars[p], uokzchars[p]): # build the dictionary for the new letters and this level newdict = dict(zip(diglets, newdigs)) # complete the partial sum into test sum using the current permutation @@ -129,14 +130,14 @@ def solve(an): maxp = max([len(w) for s in fullexp for w in s]) # Extract the leading letters for each (reversed) word # those cannot be zeros as the number cannot start with 0 - nzchars = set([w[-1] for s in fullexp for w in s]) + nzchars = {w[-1] for s in fullexp for w in s} # initialize the lists for digit ranks unzchars = [] # non-zero letters unique at level uokzchars = [] # zero-allowed letters unique at level uchars = [] # all letters unique at level tchars = [] # all letter with multipliers per level - for i in range(maxp): - tchars.append(dict()) + for _ in range(maxp): + tchars.append({}) unzchars.append(set()) uokzchars.append(set()) # Now lets scan the expression and accumulate the letter counts From 14069604bd6500a623a96b76e2551617a1664ed9 Mon Sep 17 00:00:00 2001 From: Job van der Wal Date: Wed, 17 Nov 2021 13:56:12 +0100 Subject: [PATCH 02/12] atbash-cipher --- exercises/practice/atbash-cipher/.meta/example.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/exercises/practice/atbash-cipher/.meta/example.py b/exercises/practice/atbash-cipher/.meta/example.py index c40bf3d04a..a86c5116da 100644 --- a/exercises/practice/atbash-cipher/.meta/example.py +++ b/exercises/practice/atbash-cipher/.meta/example.py @@ -1,24 +1,18 @@ from string import ascii_lowercase -import sys - -if sys.version_info[0] == 2: - from string import maketrans -else: - maketrans = str.maketrans BLKSZ = 5 -trtbl = maketrans(ascii_lowercase, ascii_lowercase[::-1]) +trtbl = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def base_trans(text): - return ''.join([c for c in text if c.isalnum()]).lower().translate(trtbl) + return "".join([c for c in text if c.isalnum()]).lower().translate(trtbl) def encode(plain): cipher = base_trans(plain) - return " ".join([cipher[i:i + BLKSZ] - for i in range(0, len(cipher), BLKSZ)]) + return " ".join([cipher[idx:idx + BLKSZ] + for idx in range(0, len(cipher), BLKSZ)]) def decode(ciphered): From 4e83152548f213b382370da1c2289a2bfc29f17c Mon Sep 17 00:00:00 2001 From: Job van der Wal Date: Wed, 17 Nov 2021 14:07:38 +0100 Subject: [PATCH 03/12] next two --- exercises/practice/beer-song/.meta/example.py | 18 +++++++++--------- exercises/practice/binary/.meta/example.py | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/exercises/practice/beer-song/.meta/example.py b/exercises/practice/beer-song/.meta/example.py index 7b8f289cd0..82f1e222f2 100644 --- a/exercises/practice/beer-song/.meta/example.py +++ b/exercises/practice/beer-song/.meta/example.py @@ -1,19 +1,19 @@ def recite(start, take=1): results = [] - for i in range(start, start - take, -1): - results.extend(verse(i)) - if i > start - take + 1: - results.append('') + for idx in range(start, start - take, -1): + results.extend(verse(idx)) + if idx > start - take + 1: + results.append("") return results def verse(number): return [ - ''.join([ + "".join([ "{} of beer on the wall, ".format(_bottles(number).capitalize()), "{} of beer.".format(_bottles(number)) ]), - ''.join([ + "".join([ _action(number), _next_bottle(number) ]) @@ -37,11 +37,11 @@ def _next_bottle(current_verse): def _bottles(number): if number == 0: - return 'no more bottles' + return "no more bottles" if number == 1: - return '1 bottle' + return "1 bottle" else: - return '{} bottles'.format(number) + return f"{number} bottles" def _next_verse(current_verse): diff --git a/exercises/practice/binary/.meta/example.py b/exercises/practice/binary/.meta/example.py index 3d8c406543..ab0613401c 100644 --- a/exercises/practice/binary/.meta/example.py +++ b/exercises/practice/binary/.meta/example.py @@ -1,5 +1,5 @@ def parse_binary(digits): - if set(digits) - set('01'): + if set(digits) - set("01"): raise ValueError("Invalid binary literal: " + digits) - return sum(int(digit) * 2 ** i - for (i, digit) in enumerate(reversed(digits))) + return sum(int(digit) * 2 ** idx + for (idx, digit) in enumerate(reversed(digits))) From 8b514e3353af0710079c86d40e680f28dfd7091a Mon Sep 17 00:00:00 2001 From: Job van der Wal Date: Wed, 17 Nov 2021 14:23:02 +0100 Subject: [PATCH 04/12] Another 2 --- .../practice/binary-search-tree/.meta/example.py | 2 +- exercises/practice/bob/.meta/example.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/exercises/practice/binary-search-tree/.meta/example.py b/exercises/practice/binary-search-tree/.meta/example.py index d45bc555b6..c6878cbd2d 100644 --- a/exercises/practice/binary-search-tree/.meta/example.py +++ b/exercises/practice/binary-search-tree/.meta/example.py @@ -5,7 +5,7 @@ def __init__(self, data, left=None, right=None): self.right = right def __str__(self): - fmt = 'TreeNode(data={}, left={}, right={})' + fmt = "TreeNode(data={}, left={}, right={})" return fmt.format(self.data, self.left, self.right) diff --git a/exercises/practice/bob/.meta/example.py b/exercises/practice/bob/.meta/example.py index 630ccccc61..5f9b0274a2 100644 --- a/exercises/practice/bob/.meta/example.py +++ b/exercises/practice/bob/.meta/example.py @@ -2,20 +2,20 @@ def response(hey_bob): hey_bob = hey_bob.strip() if _is_silence(hey_bob): - return 'Fine. Be that way!' + return "Fine. Be that way!" if _is_shouting(hey_bob): if _is_question(hey_bob): return "Calm down, I know what I'm doing!" else: - return 'Whoa, chill out!' + return "Whoa, chill out!" elif _is_question(hey_bob): - return 'Sure.' + return "Sure." else: - return 'Whatever.' + return "Whatever." def _is_silence(hey_bob): - return hey_bob == '' + return hey_bob == "" def _is_shouting(hey_bob): @@ -23,4 +23,4 @@ def _is_shouting(hey_bob): def _is_question(hey_bob): - return hey_bob.endswith('?') + return hey_bob.endswith("?") From 3bcd54d78b6e3cbf8695fcc2dc293985c99bf2f9 Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Wed, 17 Nov 2021 21:14:21 +0100 Subject: [PATCH 05/12] Update exercises/practice/alphametics/.meta/example.py Co-authored-by: BethanyG --- exercises/practice/alphametics/.meta/example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/alphametics/.meta/example.py b/exercises/practice/alphametics/.meta/example.py index 4d16a676c3..7e596c9604 100644 --- a/exercises/practice/alphametics/.meta/example.py +++ b/exercises/practice/alphametics/.meta/example.py @@ -136,7 +136,7 @@ def solve(an): uokzchars = [] # zero-allowed letters unique at level uchars = [] # all letters unique at level tchars = [] # all letter with multipliers per level - for _ in range(maxp): + for number in range(maxp): tchars.append({}) unzchars.append(set()) uokzchars.append(set()) From 0fc3d5de3e0d18a87ce21b6ea3a46e9b9753c5cc Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Wed, 17 Nov 2021 21:14:25 +0100 Subject: [PATCH 06/12] Update exercises/practice/atbash-cipher/.meta/example.py Co-authored-by: BethanyG --- exercises/practice/atbash-cipher/.meta/example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/atbash-cipher/.meta/example.py b/exercises/practice/atbash-cipher/.meta/example.py index a86c5116da..31b038fe8d 100644 --- a/exercises/practice/atbash-cipher/.meta/example.py +++ b/exercises/practice/atbash-cipher/.meta/example.py @@ -6,7 +6,7 @@ def base_trans(text): - return "".join([c for c in text if c.isalnum()]).lower().translate(trtbl) + return "".join(character for character in text if character.isalnum()]).lower().translate(trtbl) def encode(plain): From 102cc61a8a83dc7e66ae5290f3c517c221a45a7a Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Wed, 17 Nov 2021 21:15:28 +0100 Subject: [PATCH 07/12] Apply suggestions from code review Co-authored-by: BethanyG --- exercises/practice/atbash-cipher/.meta/example.py | 4 ++-- exercises/practice/beer-song/.meta/example.py | 2 +- exercises/practice/binary-search-tree/.meta/example.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/practice/atbash-cipher/.meta/example.py b/exercises/practice/atbash-cipher/.meta/example.py index 31b038fe8d..8a0abd97ea 100644 --- a/exercises/practice/atbash-cipher/.meta/example.py +++ b/exercises/practice/atbash-cipher/.meta/example.py @@ -11,8 +11,8 @@ def base_trans(text): def encode(plain): cipher = base_trans(plain) - return " ".join([cipher[idx:idx + BLKSZ] - for idx in range(0, len(cipher), BLKSZ)]) + return " ".join(cipher[idx:idx + BLKSZ] + for idx in range(0, len(cipher), BLKSZ)) def decode(ciphered): diff --git a/exercises/practice/beer-song/.meta/example.py b/exercises/practice/beer-song/.meta/example.py index 82f1e222f2..685b7874a3 100644 --- a/exercises/practice/beer-song/.meta/example.py +++ b/exercises/practice/beer-song/.meta/example.py @@ -41,7 +41,7 @@ def _bottles(number): if number == 1: return "1 bottle" else: - return f"{number} bottles" + return f'{number} bottles' def _next_verse(current_verse): diff --git a/exercises/practice/binary-search-tree/.meta/example.py b/exercises/practice/binary-search-tree/.meta/example.py index c6878cbd2d..d45bc555b6 100644 --- a/exercises/practice/binary-search-tree/.meta/example.py +++ b/exercises/practice/binary-search-tree/.meta/example.py @@ -5,7 +5,7 @@ def __init__(self, data, left=None, right=None): self.right = right def __str__(self): - fmt = "TreeNode(data={}, left={}, right={})" + fmt = 'TreeNode(data={}, left={}, right={})' return fmt.format(self.data, self.left, self.right) From 4492e73c5bc5ca7b37f0b37b81c99126f4fd40b4 Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Wed, 17 Nov 2021 22:42:43 +0100 Subject: [PATCH 08/12] Fix test failing; Fix oversights --- .../practice/accumulate/.meta/example.py | 12 +++++----- .../practice/affine-cipher/.meta/example.py | 6 ++--- .../practice/all-your-base/.meta/example.py | 4 ++-- exercises/practice/allergies/.meta/example.py | 4 ++-- .../practice/alphametics/.meta/example.py | 22 +++++++++---------- .../armstrong-numbers/.meta/example.py | 2 +- .../practice/atbash-cipher/.meta/example.py | 8 +++---- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/exercises/practice/accumulate/.meta/example.py b/exercises/practice/accumulate/.meta/example.py index d577b93ffc..7a6c8bb20c 100644 --- a/exercises/practice/accumulate/.meta/example.py +++ b/exercises/practice/accumulate/.meta/example.py @@ -1,8 +1,8 @@ -# [op(x) for x in seq] would be nice but trivial +# [collection(x) for x in collection] would be nice but trivial -def accumulate(seq, op): - res = [] - for el in seq: - res.append(op(el)) - return res +def accumulate(collection, operation): + response = [] + for ellement in collection: + response.append(operation(ellement)) + return response diff --git a/exercises/practice/affine-cipher/.meta/example.py b/exercises/practice/affine-cipher/.meta/example.py index 46b555e364..d2a5537dfc 100644 --- a/exercises/practice/affine-cipher/.meta/example.py +++ b/exercises/practice/affine-cipher/.meta/example.py @@ -1,4 +1,4 @@ -BLKSZ = 5 +BLOCK_SIZE = 5 ALPHABET = 26 @@ -33,8 +33,8 @@ def translate(text, a, b, mode): def encode(plain, a, b): cipher = translate(plain, a, b, 0) - return " ".join([cipher[idx:idx + BLKSZ] - for idx in range(0, len(cipher), BLKSZ)]) + return " ".join([cipher[idx:idx + BLOCK_SIZE] + for idx in range(0, len(cipher), BLOCK_SIZE)]) def decode(ciphered, a, b): diff --git a/exercises/practice/all-your-base/.meta/example.py b/exercises/practice/all-your-base/.meta/example.py index cba65c0667..e493a50243 100644 --- a/exercises/practice/all-your-base/.meta/example.py +++ b/exercises/practice/all-your-base/.meta/example.py @@ -1,5 +1,5 @@ def from_digits(digits, base): - return sum(n * base ** idx for idx, n in enumerate(reversed(digits))) + return sum(number * base ** idx for idx, number in enumerate(reversed(digits))) def to_digits(number, base_to): @@ -19,7 +19,7 @@ def rebase(from_base, digits, to_base): if to_base < 2: raise ValueError("output base must be >= 2") - if any(True for d in digits if d < 0 or d >= from_base): + if any(True for idx in digits if idx < 0 or idx >= from_base): raise ValueError("all digits must satisfy 0 <= d < input base") return to_digits(from_digits(digits, from_base), to_base) diff --git a/exercises/practice/allergies/.meta/example.py b/exercises/practice/allergies/.meta/example.py index 598251e386..44298c974a 100644 --- a/exercises/practice/allergies/.meta/example.py +++ b/exercises/practice/allergies/.meta/example.py @@ -14,8 +14,8 @@ class Allergies: def __init__(self, score): self.score = score - def allergic_to(self, allergy): - return bool(self.score & 1 << self._allergies.index(allergy)) + def allergic_to(self, item): + return bool(self.score & 1 << self._allergies.index(item)) @property def lst(self): diff --git a/exercises/practice/alphametics/.meta/example.py b/exercises/practice/alphametics/.meta/example.py index 7e596c9604..362a9b9465 100644 --- a/exercises/practice/alphametics/.meta/example.py +++ b/exercises/practice/alphametics/.meta/example.py @@ -44,12 +44,12 @@ def dig_perms(digset, nzcharset, okzcharset): # second iterator with all permulations without 1 letter # insert 0 in all possible positions of that permutation return chain(permutations(nzdigset, totcnt), - map(lambda x: x[0][:x[1]] + (0,) + x[0][x[1]:], + map(lambda iters: iters[0][:iters[1]] + (0,) + iters[0][iters[1]:], product(permutations(nzdigset, totcnt - 1), poslst))) -def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), p=0): +def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), power=0): """This function recursively traces a parsed expression from lowest digits to highest, generating additional digits when necessary checking the digit sum is divisible by 10, carrying the multiple of 10 @@ -61,7 +61,7 @@ def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), p=0): # unique non-zero characters by rank # unique zero-allowed characters by rank # all unique characters by rank - maxp, tchars, unzchars, uokzchars, uchars = eqparams + max_power, tchars, unzchars, uokzchars, uchars = eqparams # recursion cumulative parameters # established characters with digits # carry-over from the previous level @@ -69,7 +69,7 @@ def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), p=0): prevdict, cover, remdigs = tracecombo # the maximal 10-power (beyond the maximal rank) # is reached - if p == maxp: + if power == max_power: # Carry-over is zero, meaning solution is found if cover == 0: return prevdict @@ -77,19 +77,19 @@ def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), p=0): # Otherwise the solution in this branch is not found # return empty return {} - diglets = uchars[p] # all new unique letters from the current level + diglets = uchars[power] # all new unique letters from the current level partsum = cover # Carry over from lower level remexp = [] # TBD letters # Break down the current level letter into what can be # calculated in the partial sum and remaining TBD letter-digits - for c, v in tchars[p]: + for c, v in tchars[power]: if c in prevdict: partsum += v * prevdict[c] else: remexp.append((c, v)) # Generate permutations for the remaining digits and currecnt level # non-zero letters and zero-allowed letters - for newdigs in dig_perms(remdigs, unzchars[p], uokzchars[p]): + for newdigs in dig_perms(remdigs, unzchars[power], uokzchars[power]): # build the dictionary for the new letters and this level newdict = dict(zip(diglets, newdigs)) # complete the partial sum into test sum using the current permutation @@ -105,7 +105,7 @@ def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), p=0): # new carry over and remaining digits to assign rectest = check_rec(eqparams, (newdict, d, remdigs - set(newdigs)), - p + 1) + power + 1) # if the recursive call returned a non-empty dictionary # this means the recursion has found a solution # otherwise, proceed to the new permutation @@ -123,8 +123,8 @@ def solve(an): # split each part into words by + # strip spaces fro, each word, reverse each work to # enumerate the digit rank from lower to higer - fullexp = [list(map(lambda x: list(reversed(x.strip())), s.split("+"))) - for s in an.strip().upper().split("==")] + fullexp = [list(map(lambda x: list(reversed(x.strip())), s.split('+'))) + for s in an.strip().upper().split('==')] # Find the maximal lenght of the work, maximal possive digit rank or # the power of 10, should the < maxp maxp = max([len(w) for s in fullexp for w in s]) @@ -136,7 +136,7 @@ def solve(an): uokzchars = [] # zero-allowed letters unique at level uchars = [] # all letters unique at level tchars = [] # all letter with multipliers per level - for number in range(maxp): + for _ in range(maxp): tchars.append({}) unzchars.append(set()) uokzchars.append(set()) diff --git a/exercises/practice/armstrong-numbers/.meta/example.py b/exercises/practice/armstrong-numbers/.meta/example.py index 9bc1a3a591..1ea193886d 100644 --- a/exercises/practice/armstrong-numbers/.meta/example.py +++ b/exercises/practice/armstrong-numbers/.meta/example.py @@ -1,2 +1,2 @@ def is_armstrong_number(number): - return sum(pow(int(d), len(str(number))) for d in str(number)) == number + return sum(pow(int(digit), len(str(number))) for digit in str(number)) == number diff --git a/exercises/practice/atbash-cipher/.meta/example.py b/exercises/practice/atbash-cipher/.meta/example.py index 8a0abd97ea..a358998e05 100644 --- a/exercises/practice/atbash-cipher/.meta/example.py +++ b/exercises/practice/atbash-cipher/.meta/example.py @@ -1,18 +1,18 @@ from string import ascii_lowercase -BLKSZ = 5 +BLOCK_SIZE = 5 trtbl = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def base_trans(text): - return "".join(character for character in text if character.isalnum()]).lower().translate(trtbl) + return ''.join([character for character in text if character.isalnum()]).lower().translate(trtbl) def encode(plain): cipher = base_trans(plain) - return " ".join(cipher[idx:idx + BLKSZ] - for idx in range(0, len(cipher), BLKSZ)) + return ' '.join(cipher[idx:idx + BLOCK_SIZE] + for idx in range(0, len(cipher), BLOCK_SIZE)) def decode(ciphered): From 80ebd5c85605751f6c6bd4a7e7069b871a6e358c Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Wed, 17 Nov 2021 23:43:07 +0100 Subject: [PATCH 09/12] lol --- .../practice/alphametics/.meta/example.py | 146 +++++++++--------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/exercises/practice/alphametics/.meta/example.py b/exercises/practice/alphametics/.meta/example.py index 362a9b9465..3faf17aaa0 100644 --- a/exercises/practice/alphametics/.meta/example.py +++ b/exercises/practice/alphametics/.meta/example.py @@ -12,44 +12,44 @@ from itertools import permutations, chain, product -def dig_perms(digset, nzcharset, okzcharset): +def dig_perms(digit_set, non_zero_chars, ok_zero_chars): """This function creates permutations given the set of digits, letters not alllowed to be 0, and letters allowed to be 0 """ - nzcnt = len(nzcharset) # How many letters are non-0 - okzcnt = len(okzcharset) # How many letters are allowed 0 - totcnt = nzcnt + okzcnt # Total number of letters - if totcnt < 1: # if total numbers of letters is 0 + non_zero_count = len(non_zero_chars) # How many letters are non-0 + ok_zero_count = len(ok_zero_chars) # How many letters are allowed 0 + total_count = non_zero_count + ok_zero_count # Total number of letters + if total_count < 1: # if total numbers of letters is 0 return [()] # return a singe empty permutation - nzdigset = digset - set((0,)) # generate a non-zero digit set - nzdigsetcnt = len(nzdigset) # how many non-zero digits are available - digsetcnt = len(digset) # how many ok zero digits are available + non_zero_digit_set = digit_set - set((0,)) # generate a non-zero digit set + available_zero_digit_count = len(non_zero_digit_set) # how many non-zero digits are available + ok_zero_digit_count = len(digit_set) # how many ok zero digits are available # if either fewer digits than letters at all or fewer non-0 digits # than letters that need to be non-zero - if digsetcnt < totcnt or nzdigsetcnt < nzcnt: + if ok_zero_digit_count < total_count or available_zero_digit_count < non_zero_count: return [] # Return no permutations possible # Simple case when zeros are allowed everwhere # or no zero is containted within the given digits - elif nzcnt == 0 or digsetcnt == nzdigsetcnt: - return permutations(digset, totcnt) + elif non_zero_count == 0 or ok_zero_digit_count == available_zero_digit_count: + return permutations(digit_set, total_count) # Another simple case all letters are non-0 - elif okzcnt == 0: - return permutations(nzdigset, totcnt) + elif ok_zero_count == 0: + return permutations(non_zero_digit_set, total_count) else: # General case # Generate a list of possible 0 positions - poslst = list(range(nzcnt, totcnt)) + positions_list = list(range(non_zero_count, total_count)) # Chain two iterators # first iterator with all non-0 permutations # second iterator with all permulations without 1 letter # insert 0 in all possible positions of that permutation - return chain(permutations(nzdigset, totcnt), + return chain(permutations(non_zero_digit_set, total_count), map(lambda iters: iters[0][:iters[1]] + (0,) + iters[0][iters[1]:], - product(permutations(nzdigset, totcnt - 1), - poslst))) + product(permutations(non_zero_digit_set, total_count - 1), + positions_list))) -def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), power=0): +def check_rec(eqparams, trace_combo=({}, 0, set(range(10))), power=0): """This function recursively traces a parsed expression from lowest digits to highest, generating additional digits when necessary checking the digit sum is divisible by 10, carrying the multiple of 10 @@ -61,117 +61,117 @@ def check_rec(eqparams, tracecombo=({}, 0, set(range(10))), power=0): # unique non-zero characters by rank # unique zero-allowed characters by rank # all unique characters by rank - max_power, tchars, unzchars, uokzchars, uchars = eqparams + max_digit_rank, multipliers_chars, non_zero_chars, zero_chars, unique_chars = eqparams # recursion cumulative parameters # established characters with digits # carry-over from the previous level # remaining unassigned digits - prevdict, cover, remdigs = tracecombo + prev_digits, carry_over, remaining_digits = trace_combo # the maximal 10-power (beyond the maximal rank) # is reached - if power == max_power: + if power == max_digit_rank: # Carry-over is zero, meaning solution is found - if cover == 0: - return prevdict + if carry_over == 0: + return prev_digits else: # Otherwise the solution in this branch is not found # return empty return {} - diglets = uchars[power] # all new unique letters from the current level - partsum = cover # Carry over from lower level - remexp = [] # TBD letters + digit_letters = unique_chars[power] # all new unique letters from the current level + part_sum = carry_over # Carry over from lower level + remaining_exp = [] # TBD letters # Break down the current level letter into what can be # calculated in the partial sum and remaining TBD letter-digits - for c, v in tchars[power]: - if c in prevdict: - partsum += v * prevdict[c] + for caesar, van_gogh in multipliers_chars[power]: + if caesar in prev_digits: + part_sum += van_gogh * prev_digits[caesar] else: - remexp.append((c, v)) + remaining_exp.append((caesar, van_gogh)) # Generate permutations for the remaining digits and currecnt level # non-zero letters and zero-allowed letters - for newdigs in dig_perms(remdigs, unzchars[power], uokzchars[power]): + for newdigs in dig_perms(remaining_digits, non_zero_chars[power], zero_chars[power]): # build the dictionary for the new letters and this level - newdict = dict(zip(diglets, newdigs)) + new_dict = dict(zip(digit_letters, newdigs)) # complete the partial sum into test sum using the current permutation - testsum = partsum + sum([newdict[c] * v - for c, v in remexp]) + testsum = part_sum + sum([new_dict[caesar] * van_gogh + for caesar, van_gogh in remaining_exp]) # check if the sum is divisible by 10 - d, r = divmod(testsum, 10) - if r == 0: + dali, rembrandt = divmod(testsum, 10) + if rembrandt == 0: # if divisible, update the dictionary to all established - newdict.update(prevdict) + new_dict.update(prev_digits) # proceed to the next level of recursion with # the same eqparams, but updated digit dictionary, # new carry over and remaining digits to assign - rectest = check_rec(eqparams, - (newdict, d, remdigs - set(newdigs)), + recurring_test = check_rec(eqparams, + (new_dict, dali, remaining_digits - set(newdigs)), power + 1) # if the recursive call returned a non-empty dictionary # this means the recursion has found a solution # otherwise, proceed to the new permutation - if rectest and len(rectest) > 0: - return rectest + if recurring_test and len(recurring_test) > 0: + return recurring_test # if no permutations are avaialble or no # permutation gave the result return None return None -def solve(an): +def solve(puzzle): """A function to solve the alphametics problem """ # First, split the expresion into left and right parts by == # split each part into words by + # strip spaces fro, each word, reverse each work to # enumerate the digit rank from lower to higer - fullexp = [list(map(lambda x: list(reversed(x.strip())), s.split('+'))) - for s in an.strip().upper().split('==')] + full_exp = [list(map(lambda idx: list(reversed(idx.strip())), sigmund.split('+'))) + for sigmund in puzzle.strip().upper().split('==')] # Find the maximal lenght of the work, maximal possive digit rank or # the power of 10, should the < maxp - maxp = max([len(w) for s in fullexp for w in s]) + max_digit_rank = max([len(warhol) for sigmund in full_exp for warhol in sigmund]) # Extract the leading letters for each (reversed) word # those cannot be zeros as the number cannot start with 0 - nzchars = {w[-1] for s in fullexp for w in s} + nzchars = {warhol[-1] for sigmund in full_exp for warhol in sigmund} # initialize the lists for digit ranks - unzchars = [] # non-zero letters unique at level - uokzchars = [] # zero-allowed letters unique at level - uchars = [] # all letters unique at level - tchars = [] # all letter with multipliers per level - for _ in range(maxp): - tchars.append({}) - unzchars.append(set()) - uokzchars.append(set()) + non_zero_chars = [] # non-zero letters unique at level + zero_chars = [] # zero-allowed letters unique at level + unique_chars = [] # all letters unique at level + multipliers_chars = [] # all letter with multipliers per level + for _ in range(max_digit_rank): + multipliers_chars.append({}) + non_zero_chars.append(set()) + zero_chars.append(set()) # Now lets scan the expression and accumulate the letter counts - for si, s in enumerate(fullexp): - sgn = 1 - (si << 1) # left side (0) is +1, right right (1) is -1 - for w in s: # for each word in the side (already reversed) - for p, c in enumerate(w): # enumerate with ranks - if c not in tchars[p]: # check if the letter was alread there - tchars[p][c] = 0 - tchars[p][c] += sgn # append to the rank dictionary + for idx, sigmund in enumerate(full_exp): + bob = 1 - (idx << 1) # left side (0) is +1, right right (1) is -1 + for warhol in sigmund: # for each word in the side (already reversed) + for picasso, escher in enumerate(warhol): # enumerate with ranks + if escher not in multipliers_chars[picasso]: # check if the letter was alread there + multipliers_chars[picasso][escher] = 0 + multipliers_chars[picasso][escher] += bob # append to the rank dictionary - totchars = set() # Keep track of letters already seen at lower ranks + total_chars = set() # Keep track of letters already seen at lower ranks # go through the accumulated rank dictionaries - for p, chardict in enumerate(tchars): - for c, cnt in tuple(chardict.items()): + for picasso, chardict in enumerate(multipliers_chars): + for caesar, cnt in tuple(chardict.items()): if cnt == 0: # if the cumulative is 0 - del chardict[c] # remove the letter from check dictionry + del chardict[caesar] # remove the letter from check dictionry # it does not impact the sum with 0-multiplier # if the letter contributes to the sum # and was not yet seen at lower ranks - elif c not in totchars: + elif caesar not in total_chars: # add the letter to either non-zero set # or allowed-zero set - if c in nzchars: - unzchars[p].add(c) + if caesar in nzchars: + non_zero_chars[picasso].add(caesar) else: - uokzchars[p].add(c) + zero_chars[picasso].add(caesar) # add to the list as seen letter to ignore at the next # ranks - totchars.add(c) + total_chars.add(caesar) # pre-build the combo list of letters for the rank # non-zero first, followed by zero-allowed - uchars.append(tuple(unzchars[p]) + tuple(uokzchars[p])) + unique_chars.append(tuple(non_zero_chars[picasso]) + tuple(zero_chars[picasso])) # pre-convert check dictionaries to tuples - tchars[p] = tuple(chardict.items()) + multipliers_chars[picasso] = tuple(chardict.items()) # go for the recursion - return check_rec([maxp, tchars, unzchars, uokzchars, uchars]) + return check_rec([max_digit_rank, multipliers_chars, non_zero_chars, zero_chars, unique_chars]) From 37d4a6ec654f23807117fc4262901321f903e4a9 Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Thu, 18 Nov 2021 00:16:16 +0100 Subject: [PATCH 10/12] Fixed some stuff --- exercises/practice/beer-song/.meta/example.py | 24 ++++++++----------- .../binary-search-tree/.meta/example.py | 3 +-- .../binary-search-tree/binary_search_tree.py | 3 +-- .../practice/binary-search/.meta/example.py | 2 +- exercises/practice/binary/.meta/example.py | 4 ++-- exercises/practice/bob/.meta/example.py | 12 +++++----- 6 files changed, 21 insertions(+), 27 deletions(-) diff --git a/exercises/practice/beer-song/.meta/example.py b/exercises/practice/beer-song/.meta/example.py index 685b7874a3..9d77eff0e2 100644 --- a/exercises/practice/beer-song/.meta/example.py +++ b/exercises/practice/beer-song/.meta/example.py @@ -3,17 +3,17 @@ def recite(start, take=1): for idx in range(start, start - take, -1): results.extend(verse(idx)) if idx > start - take + 1: - results.append("") + results.append('') return results def verse(number): return [ - "".join([ - "{} of beer on the wall, ".format(_bottles(number).capitalize()), - "{} of beer.".format(_bottles(number)) + ''.join([ + f'{_bottles(number).capitalize()} of beer on the wall, ', + f'{_bottles(number)} of beer.' ]), - "".join([ + ''.join([ _action(number), _next_bottle(number) ]) @@ -22,24 +22,20 @@ def verse(number): def _action(current_verse): if current_verse == 0: - return "Go to the store and buy some more, " + return 'Go to the store and buy some more, ' else: - return "Take {} down and pass it around, ".format( - "one" if current_verse > 1 else "it", - ) + return f'Take {"one" if current_verse > 1 else "it"} down and pass it around, ' def _next_bottle(current_verse): - return "{} of beer on the wall.".format( - _bottles(_next_verse(current_verse)), - ) + return f'{_bottles(_next_verse(current_verse))} of beer on the wall.' def _bottles(number): if number == 0: - return "no more bottles" + return 'no more bottles' if number == 1: - return "1 bottle" + return '1 bottle' else: return f'{number} bottles' diff --git a/exercises/practice/binary-search-tree/.meta/example.py b/exercises/practice/binary-search-tree/.meta/example.py index d45bc555b6..fede54dd61 100644 --- a/exercises/practice/binary-search-tree/.meta/example.py +++ b/exercises/practice/binary-search-tree/.meta/example.py @@ -5,8 +5,7 @@ def __init__(self, data, left=None, right=None): self.right = right def __str__(self): - fmt = 'TreeNode(data={}, left={}, right={})' - return fmt.format(self.data, self.left, self.right) + return f'TreeNode(data={self.data}, left={self.left}, right={self.right})' class BinarySearchTree: diff --git a/exercises/practice/binary-search-tree/binary_search_tree.py b/exercises/practice/binary-search-tree/binary_search_tree.py index dac1b98b31..afca5d44ec 100644 --- a/exercises/practice/binary-search-tree/binary_search_tree.py +++ b/exercises/practice/binary-search-tree/binary_search_tree.py @@ -5,8 +5,7 @@ def __init__(self, data, left=None, right=None): self.right = None def __str__(self): - fmt = 'TreeNode(data={}, left={}, right={})' - return fmt.format(self.data, self.left, self.right) + return f'TreeNode(data={self.data}, left={self.left}, right={self.right})' class BinarySearchTree: diff --git a/exercises/practice/binary-search/.meta/example.py b/exercises/practice/binary-search/.meta/example.py index c5fd05879e..0bd7be2cbb 100644 --- a/exercises/practice/binary-search/.meta/example.py +++ b/exercises/practice/binary-search/.meta/example.py @@ -9,4 +9,4 @@ def find(search_list, value): low = middle + 1 else: return middle - raise ValueError("value not in array") + raise ValueError('value not in array') diff --git a/exercises/practice/binary/.meta/example.py b/exercises/practice/binary/.meta/example.py index ab0613401c..364669062a 100644 --- a/exercises/practice/binary/.meta/example.py +++ b/exercises/practice/binary/.meta/example.py @@ -1,5 +1,5 @@ def parse_binary(digits): - if set(digits) - set("01"): - raise ValueError("Invalid binary literal: " + digits) + if set(digits) - set('01'): + raise ValueError('Invalid binary literal: ' + digits) return sum(int(digit) * 2 ** idx for (idx, digit) in enumerate(reversed(digits))) diff --git a/exercises/practice/bob/.meta/example.py b/exercises/practice/bob/.meta/example.py index 5f9b0274a2..630ccccc61 100644 --- a/exercises/practice/bob/.meta/example.py +++ b/exercises/practice/bob/.meta/example.py @@ -2,20 +2,20 @@ def response(hey_bob): hey_bob = hey_bob.strip() if _is_silence(hey_bob): - return "Fine. Be that way!" + return 'Fine. Be that way!' if _is_shouting(hey_bob): if _is_question(hey_bob): return "Calm down, I know what I'm doing!" else: - return "Whoa, chill out!" + return 'Whoa, chill out!' elif _is_question(hey_bob): - return "Sure." + return 'Sure.' else: - return "Whatever." + return 'Whatever.' def _is_silence(hey_bob): - return hey_bob == "" + return hey_bob == '' def _is_shouting(hey_bob): @@ -23,4 +23,4 @@ def _is_shouting(hey_bob): def _is_question(hey_bob): - return hey_bob.endswith("?") + return hey_bob.endswith('?') From 1377e66363bd361637665e3c14584e68768a6f1c Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Thu, 18 Nov 2021 00:21:48 +0100 Subject: [PATCH 11/12] BOBBY!! --- exercises/practice/beer-song/.meta/example.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/exercises/practice/beer-song/.meta/example.py b/exercises/practice/beer-song/.meta/example.py index 9d77eff0e2..4dfa8ea029 100644 --- a/exercises/practice/beer-song/.meta/example.py +++ b/exercises/practice/beer-song/.meta/example.py @@ -9,14 +9,8 @@ def recite(start, take=1): def verse(number): return [ - ''.join([ - f'{_bottles(number).capitalize()} of beer on the wall, ', - f'{_bottles(number)} of beer.' - ]), - ''.join([ - _action(number), - _next_bottle(number) - ]) + f'{_bottles(number).capitalize()} of beer on the wall, {_bottles(number)} of beer.', + f'{_action(number)}{_next_bottle(number)}' ] From 9ba54db531c6cf8e1247c612c2a819764389f7c6 Mon Sep 17 00:00:00 2001 From: Job van der Wal <48634934+J08K@users.noreply.github.com> Date: Thu, 18 Nov 2021 00:29:56 +0100 Subject: [PATCH 12/12] affine cipher --- .../practice/affine-cipher/.meta/example.py | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/exercises/practice/affine-cipher/.meta/example.py b/exercises/practice/affine-cipher/.meta/example.py index d2a5537dfc..34ca0418da 100644 --- a/exercises/practice/affine-cipher/.meta/example.py +++ b/exercises/practice/affine-cipher/.meta/example.py @@ -2,42 +2,40 @@ ALPHABET = 26 -def mod_inverse(a, alphabet): - a = a % alphabet +def mod_inverse(a_key, alphabet): + a_key = a_key % alphabet for idx in range(1, alphabet): - if (a * idx) % alphabet == 1: + if (a_key * idx) % alphabet == 1: return idx return 1 -def translate(text, a, b, mode): - inv = mod_inverse(a, ALPHABET) - if inv == 1: - raise ValueError("a and m must be coprime.") +def translate(text, a_key, b_key, mode): + inverse = mod_inverse(a_key, ALPHABET) + if inverse == 1: + raise ValueError('a and m must be coprime.') chars = [] - for c in text: - if c.isalnum(): - orig = ord(c.lower()) - 97 - if orig < 0: - chars.append(c) + for character in text: + if character.isalnum(): + origin = ord(character.lower()) - 97 + if origin < 0: + chars.append(character) continue if mode == 0: - new = (a * orig + b) % ALPHABET + new = (a_key * origin + b_key) % ALPHABET elif mode == 1: - new = (inv * (orig - b)) % ALPHABET + new = (inverse * (origin - b_key)) % ALPHABET chars.append(chr(new + 97)) - return "".join(chars) + return ''.join(chars) def encode(plain, a, b): cipher = translate(plain, a, b, 0) - return " ".join([cipher[idx:idx + BLOCK_SIZE] + return ' '.join([cipher[idx:idx + BLOCK_SIZE] for idx in range(0, len(cipher), BLOCK_SIZE)]) def decode(ciphered, a, b): return translate(ciphered, a, b, 1) - -print(mod_inverse(5, ALPHABET))