From b7f9402e08c200bcf83867c88a34ab8bc841d9f2 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Wed, 12 Jul 2023 17:04:33 +0530 Subject: [PATCH 1/7] first round --- .../atbash-cipher/.approaches/config.json | 21 +++++++++ .../atbash-cipher/.approaches/introduction.md | 45 ++++++++++++++++++ .../.approaches/mono-functions/content.md | 46 ++++++++++++++++++ .../.approaches/mono-functions/snippet.txt | 8 ++++ .../.approaches/seperate-functions/content.md | 47 +++++++++++++++++++ .../seperate-functions/snippet.txt | 8 ++++ 6 files changed, 175 insertions(+) create mode 100644 exercises/practice/atbash-cipher/.approaches/config.json create mode 100644 exercises/practice/atbash-cipher/.approaches/introduction.md create mode 100644 exercises/practice/atbash-cipher/.approaches/mono-functions/content.md create mode 100644 exercises/practice/atbash-cipher/.approaches/mono-functions/snippet.txt create mode 100644 exercises/practice/atbash-cipher/.approaches/seperate-functions/content.md create mode 100644 exercises/practice/atbash-cipher/.approaches/seperate-functions/snippet.txt diff --git a/exercises/practice/atbash-cipher/.approaches/config.json b/exercises/practice/atbash-cipher/.approaches/config.json new file mode 100644 index 0000000000..3ebecc24a0 --- /dev/null +++ b/exercises/practice/atbash-cipher/.approaches/config.json @@ -0,0 +1,21 @@ +{ + "introduction": { + "authors": ["safwansamsudeen"] + }, + "approaches": [ + { + "uuid": "920e6d08-e8fa-4bef-b2f4-837006c476ae", + "slug": "mono-function", + "title": "Mono-function", + "blurb": "Use one function for both tasks", + "authors": ["safwansamsudeen"] + }, + { + "uuid": "9a7a17e0-4ad6-4d97-a8b9-c74d47f3e000", + "slug": "separate-functions", + "title": "Separate Functions", + "blurb": "Use seperate functions, and perhaps helper ones", + "authors": ["safwansamsudeen"] + } + ] +} diff --git a/exercises/practice/atbash-cipher/.approaches/introduction.md b/exercises/practice/atbash-cipher/.approaches/introduction.md new file mode 100644 index 0000000000..eb34f09c79 --- /dev/null +++ b/exercises/practice/atbash-cipher/.approaches/introduction.md @@ -0,0 +1,45 @@ +# Introduction +Atbash cipher in Python can be solved in many ways. + +## General guidance +The first thing is to have a "key" mapping - possibly in a `dict` or `str.maketrans`, otherwise the value would have be calculated on the fly. +Then, you have to "clean" up the string to be encoded by removing numbers/whitespace. +Finally, you break it up into chunks of five before returning it. + +For decoding, it's similar - clean up (which automatically joins the chunks) and translate using the _same_ key - the realization that the same key can be used is crucial in solving this in an idiomatic manner. + +## Approach: separate functions +We use `str.maketrans` to create the encoding. +In `encode`, we use a [generator expression][generator expression] in `str.join`. +```python +from string import ascii_lowercase +ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) + +def encode(text: str): + res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) + return " ".join(res[i:i+5] for i in range(0, len(res), 5)) +def decode(text: str): + return "".join(c.lower() for c in text if c.isalnum()).translate(ENCODING) +``` +Read more on this [approach here][approach-seperate-functions]. + +## Approach: mono-function +Notice that there the majority of the code is repetitive? +A fun way to solve this would be to keep it all inside the `encode` function, and merely chunk it if `decode` is False: +For variation, this approach shows a different way to translate the text. +```python +from string import ascii_lowercase as asc_low +ENCODING = {c: asc_low[i] for i, c in enumerate(asc_low[::-1])} + +def encode(text: str, decode: bool = False): + res = "".join(ENCODING.get(c, c) for c in text.lower() if c.isalnum()) + return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) + +def decode(text: str): + return encode(text, True) +``` +For more detail, [read here][approach-mono-function]. + +[approach-separate-functions]: https://exercism.org/tracks/python/exercises/atbash-cipher/approaches/separate-functions +[approach-mono-function]: https://exercism.org/tracks/python/exercises/atbash-cipher/approaches/mono-function +[generator expression]: https://www.programiz.com/python-programming/generator diff --git a/exercises/practice/atbash-cipher/.approaches/mono-functions/content.md b/exercises/practice/atbash-cipher/.approaches/mono-functions/content.md new file mode 100644 index 0000000000..5768686e35 --- /dev/null +++ b/exercises/practice/atbash-cipher/.approaches/mono-functions/content.md @@ -0,0 +1,46 @@ +## Approach: Mono-function +Notice that there the majority of the code is repetitive? +A fun way to solve this would be to keep it all inside the `encode` function, and merely chunk it if `decode` is False: +For variation, this approach shows a different way to translate the text. +```python +from string import ascii_lowercase as asc_low +ENCODING = {c: asc_low[i] for i, c in enumerate(asc_low[::-1])} + +def encode(text: str, decode: bool = False): + res = "".join(ENCODING.get(c, c) for c in text.lower() if c.isalnum()) + return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) + +def decode(text: str): + return encode(text, True) +``` +To explain the translation: we use a dict comprehension in which we reverse the ASCII lowercase digits, and enumerate through them - that is, `z` is 0, `y` is 1, and so on. +We access the character at that index and set it to the value of `c` - so `z` translates to `a`. + +In the calculation of the result, we try to obtain the value of the character using `dict.get`, which accepts a default parameter. +In this case, the character itself is the default - that is, numbers won't be found in the translation key, and thus should remain as numbers. + +We use a [ternary operator][ternary-operator] to check if we actually mean to decode the function, in which case we return the result as is. +If not, we chunk the result by joining every five characters with a space. + +Another possible way to solve this would be to use a function that returns a function that encodes or decodes based on the parameters: +```python +from string import punctuation, ascii_lowercase as alc + +lowercase = {c: alc[i] for i, c in enumerate(alc[::-1])} + +def code(decode=False): + def func(text): + line = "".join(lowercase.get(l, l) for l in text.lower() if l not in punctuation + ' ') + return line if decode else " ".join(line[i:i+5] for i in range(0, len(line), 5)) + return func + + +encode = code() +decode = code(True) +``` +The logic is the same - we've instead used one function that generates two _other_ functions based on the boolean value of its parameter. +`encode` is set to the function that's returned, and performs encoding. +`decode` is set a function that _decodes_ + +[ternary-operator]: https://www.tutorialspoint.com/ternary-operator-in-python +[decorator]: https://realpython.com/primer-on-python-decorators/ \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/mono-functions/snippet.txt b/exercises/practice/atbash-cipher/.approaches/mono-functions/snippet.txt new file mode 100644 index 0000000000..ed77151de2 --- /dev/null +++ b/exercises/practice/atbash-cipher/.approaches/mono-functions/snippet.txt @@ -0,0 +1,8 @@ +from string import ascii_lowercase +ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) + +def encode(text: str): + res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) + return " ".join(res[i:i+5] for i in range(0, len(res), 5)) +def decode(text: str): + return "".join(c.lower() for c in text if not c.isspace()).translate(ENCODING) \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/seperate-functions/content.md b/exercises/practice/atbash-cipher/.approaches/seperate-functions/content.md new file mode 100644 index 0000000000..e7de53dab9 --- /dev/null +++ b/exercises/practice/atbash-cipher/.approaches/seperate-functions/content.md @@ -0,0 +1,47 @@ +## Approach: Separate Functions +We use `str.maketrans` to create the encoding. +`.maketrans`/`.translate` is extremely fast compared to other methods of translation. + +In `encode`, we use a [generator expression][generator expression] in `str.join`, which is more efficient - and neater - than a list comprehension. +```python +from string import ascii_lowercase +ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) + +def encode(text: str): + res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) + return " ".join(res[i:i+5] for i in range(0, len(res), 5)) +def decode(text: str): + return "".join(c.lower() for c in text if not c.isspace()).translate(ENCODING) +``` +In `encode`, we first join together every character if the character is alphanumeric - as we use `text.lower()`, the characters are all lowercase as needed. +Then, we translate it and return a version joining every five characters with a space in between. + +`decode` does the exact same thing, except it doesn't return a chunked output. +Instead of cleaning the input by checking that it's alphanumeric, we check that it's not a whitespace character. + +It might be cleaner to use helper functions: +```python +from string import ascii_lowercase +ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) +def _clean(text): + return "".join([c.lower() for c in text if c.isalnum()]) +def _chunk(text): + return " ".join(text[i:i+5] for i in range(0, len(text), 5)) + +def encode(text): + return _chunk(_clean(text).translate(ENCODING)) +def decode(text): + return _clean(text).translate(ENCODING) +``` +Note that checking that `c` _is_ alphanumeric achieves the same result as checking that it's _not_ whitespace, although it's not as explicit. +As this is a helper function, this is acceptable enough. + +You can also make `_chunk` recursive: +```python +def _chunk(text): + if len(text) <= 5: + return text + return text[:5] + " " + _chunk(text[5:]) +``` + +[generator expression]: https://www.programiz.com/python-programming/generator \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/seperate-functions/snippet.txt b/exercises/practice/atbash-cipher/.approaches/seperate-functions/snippet.txt new file mode 100644 index 0000000000..ed77151de2 --- /dev/null +++ b/exercises/practice/atbash-cipher/.approaches/seperate-functions/snippet.txt @@ -0,0 +1,8 @@ +from string import ascii_lowercase +ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) + +def encode(text: str): + res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) + return " ".join(res[i:i+5] for i in range(0, len(res), 5)) +def decode(text: str): + return "".join(c.lower() for c in text if not c.isspace()).translate(ENCODING) \ No newline at end of file From 026475d33b594870dbe383cb7147cc45b101d53b Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Wed, 12 Jul 2023 17:23:58 +0530 Subject: [PATCH 2/7] correct typo --- .../{seperate-functions => separate-functions}/content.md | 0 .../{seperate-functions => separate-functions}/snippet.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename exercises/practice/atbash-cipher/.approaches/{seperate-functions => separate-functions}/content.md (100%) rename exercises/practice/atbash-cipher/.approaches/{seperate-functions => separate-functions}/snippet.txt (100%) diff --git a/exercises/practice/atbash-cipher/.approaches/seperate-functions/content.md b/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md similarity index 100% rename from exercises/practice/atbash-cipher/.approaches/seperate-functions/content.md rename to exercises/practice/atbash-cipher/.approaches/separate-functions/content.md diff --git a/exercises/practice/atbash-cipher/.approaches/seperate-functions/snippet.txt b/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt similarity index 100% rename from exercises/practice/atbash-cipher/.approaches/seperate-functions/snippet.txt rename to exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt From 24d4fada8446ed3eaaef8800a6b87c1a8fe3418f Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Wed, 12 Jul 2023 17:56:11 +0530 Subject: [PATCH 3/7] correct yet another typo --- .../.approaches/{mono-functions => mono-function}/content.md | 0 .../.approaches/{mono-functions => mono-function}/snippet.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename exercises/practice/atbash-cipher/.approaches/{mono-functions => mono-function}/content.md (100%) rename exercises/practice/atbash-cipher/.approaches/{mono-functions => mono-function}/snippet.txt (100%) diff --git a/exercises/practice/atbash-cipher/.approaches/mono-functions/content.md b/exercises/practice/atbash-cipher/.approaches/mono-function/content.md similarity index 100% rename from exercises/practice/atbash-cipher/.approaches/mono-functions/content.md rename to exercises/practice/atbash-cipher/.approaches/mono-function/content.md diff --git a/exercises/practice/atbash-cipher/.approaches/mono-functions/snippet.txt b/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt similarity index 100% rename from exercises/practice/atbash-cipher/.approaches/mono-functions/snippet.txt rename to exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt From a912ab39228614a20c16c80f77c7f96cb2adf7d3 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen <62411302+safwansamsudeen@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:54:11 +0530 Subject: [PATCH 4/7] Apply suggestions from code review Co-authored-by: BethanyG --- exercises/practice/atbash-cipher/.approaches/introduction.md | 2 +- .../practice/atbash-cipher/.approaches/mono-function/content.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/atbash-cipher/.approaches/introduction.md b/exercises/practice/atbash-cipher/.approaches/introduction.md index eb34f09c79..591f7f883f 100644 --- a/exercises/practice/atbash-cipher/.approaches/introduction.md +++ b/exercises/practice/atbash-cipher/.approaches/introduction.md @@ -2,7 +2,7 @@ Atbash cipher in Python can be solved in many ways. ## General guidance -The first thing is to have a "key" mapping - possibly in a `dict` or `str.maketrans`, otherwise the value would have be calculated on the fly. +The first thing is to have a "key" mapping - possibly in a `dict` or `str.maketrans`, otherwise the value would have to be calculated on the fly. Then, you have to "clean" up the string to be encoded by removing numbers/whitespace. Finally, you break it up into chunks of five before returning it. diff --git a/exercises/practice/atbash-cipher/.approaches/mono-function/content.md b/exercises/practice/atbash-cipher/.approaches/mono-function/content.md index 5768686e35..cb943c66a5 100644 --- a/exercises/practice/atbash-cipher/.approaches/mono-function/content.md +++ b/exercises/practice/atbash-cipher/.approaches/mono-function/content.md @@ -13,7 +13,7 @@ def encode(text: str, decode: bool = False): def decode(text: str): return encode(text, True) ``` -To explain the translation: we use a dict comprehension in which we reverse the ASCII lowercase digits, and enumerate through them - that is, `z` is 0, `y` is 1, and so on. +To explain the translation: we use a `dict` comprehension in which we reverse the ASCII lowercase digits, and enumerate through them - that is, `z` is 0, `y` is 1, and so on. We access the character at that index and set it to the value of `c` - so `z` translates to `a`. In the calculation of the result, we try to obtain the value of the character using `dict.get`, which accepts a default parameter. From e35a1bb7fd14042c034b62839a76fd15db194677 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Sat, 15 Jul 2023 16:06:07 +0530 Subject: [PATCH 5/7] replace most single variable names --- .../atbash-cipher/.approaches/config.json | 2 +- .../atbash-cipher/.approaches/introduction.md | 9 ++++---- .../.approaches/mono-function/content.md | 12 +++++----- .../.approaches/mono-function/snippet.txt | 12 +++++----- .../.approaches/separate-functions/content.md | 23 ++++++++++--------- .../separate-functions/snippet.txt | 4 ++-- 6 files changed, 32 insertions(+), 30 deletions(-) diff --git a/exercises/practice/atbash-cipher/.approaches/config.json b/exercises/practice/atbash-cipher/.approaches/config.json index 3ebecc24a0..ed1edeb506 100644 --- a/exercises/practice/atbash-cipher/.approaches/config.json +++ b/exercises/practice/atbash-cipher/.approaches/config.json @@ -14,7 +14,7 @@ "uuid": "9a7a17e0-4ad6-4d97-a8b9-c74d47f3e000", "slug": "separate-functions", "title": "Separate Functions", - "blurb": "Use seperate functions, and perhaps helper ones", + "blurb": "Use separate functions, and perhaps helper ones", "authors": ["safwansamsudeen"] } ] diff --git a/exercises/practice/atbash-cipher/.approaches/introduction.md b/exercises/practice/atbash-cipher/.approaches/introduction.md index eb34f09c79..46229dd794 100644 --- a/exercises/practice/atbash-cipher/.approaches/introduction.md +++ b/exercises/practice/atbash-cipher/.approaches/introduction.md @@ -16,10 +16,11 @@ from string import ascii_lowercase ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def encode(text: str): - res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) + res = "".join(chr for chr in text.lower() if chr.isalnum()).translate(ENCODING) return " ".join(res[i:i+5] for i in range(0, len(res), 5)) + def decode(text: str): - return "".join(c.lower() for c in text if c.isalnum()).translate(ENCODING) + return "".join(chr.lower() for chr in text if chr.isalnum()).translate(ENCODING) ``` Read more on this [approach here][approach-seperate-functions]. @@ -29,10 +30,10 @@ A fun way to solve this would be to keep it all inside the `encode` function, an For variation, this approach shows a different way to translate the text. ```python from string import ascii_lowercase as asc_low -ENCODING = {c: asc_low[i] for i, c in enumerate(asc_low[::-1])} +ENCODING = {chr: asc_low[id] for id, chr in enumerate(asc_low[::-1])} def encode(text: str, decode: bool = False): - res = "".join(ENCODING.get(c, c) for c in text.lower() if c.isalnum()) + res = "".join(ENCODING.get(chr, chr) for chr in text.lower() if chr.isalnum()) return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) def decode(text: str): diff --git a/exercises/practice/atbash-cipher/.approaches/mono-function/content.md b/exercises/practice/atbash-cipher/.approaches/mono-function/content.md index 5768686e35..061b6490a6 100644 --- a/exercises/practice/atbash-cipher/.approaches/mono-function/content.md +++ b/exercises/practice/atbash-cipher/.approaches/mono-function/content.md @@ -4,10 +4,10 @@ A fun way to solve this would be to keep it all inside the `encode` function, an For variation, this approach shows a different way to translate the text. ```python from string import ascii_lowercase as asc_low -ENCODING = {c: asc_low[i] for i, c in enumerate(asc_low[::-1])} +ENCODING = {chr: asc_low[id] for id, chr in enumerate(asc_low[::-1])} def encode(text: str, decode: bool = False): - res = "".join(ENCODING.get(c, c) for c in text.lower() if c.isalnum()) + res = "".join(ENCODING.get(chr, chr) for chr in text.lower() if chr.isalnum()) return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) def decode(text: str): @@ -24,13 +24,13 @@ If not, we chunk the result by joining every five characters with a space. Another possible way to solve this would be to use a function that returns a function that encodes or decodes based on the parameters: ```python -from string import punctuation, ascii_lowercase as alc +from string import ascii_lowercase as alc -lowercase = {c: alc[i] for i, c in enumerate(alc[::-1])} +lowercase = {chr: alc[id] for id, chr in enumerate(alc[::-1])} def code(decode=False): def func(text): - line = "".join(lowercase.get(l, l) for l in text.lower() if l not in punctuation + ' ') + line = "".join(lowercase.get(chr, chr) for chr in text.lower() if chr.isalnum()) return line if decode else " ".join(line[i:i+5] for i in range(0, len(line), 5)) return func @@ -40,7 +40,7 @@ decode = code(True) ``` The logic is the same - we've instead used one function that generates two _other_ functions based on the boolean value of its parameter. `encode` is set to the function that's returned, and performs encoding. -`decode` is set a function that _decodes_ +`decode` is set a function that _decodes_. [ternary-operator]: https://www.tutorialspoint.com/ternary-operator-in-python [decorator]: https://realpython.com/primer-on-python-decorators/ \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt b/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt index ed77151de2..832fef5b55 100644 --- a/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt +++ b/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt @@ -1,8 +1,8 @@ -from string import ascii_lowercase -ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) +from string import ascii_lowercase as asc_low +ENCODING = {chr: asc_low[id] for id, chr in enumerate(asc_low[::-1])} -def encode(text: str): - res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) - return " ".join(res[i:i+5] for i in range(0, len(res), 5)) +def encode(text: str, decode: bool = False): + res = "".join(ENCODING.get(chr, chr) for chr in text.lower() if chr.isalnum()) + return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) def decode(text: str): - return "".join(c.lower() for c in text if not c.isspace()).translate(ENCODING) \ No newline at end of file + return encode(text, True) \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md b/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md index e7de53dab9..b4bd580a57 100644 --- a/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md +++ b/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md @@ -8,10 +8,11 @@ from string import ascii_lowercase ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def encode(text: str): - res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) + res = "".join(chr for chr in text.lower() if chr.isalnum()).translate(ENCODING) return " ".join(res[i:i+5] for i in range(0, len(res), 5)) + def decode(text: str): - return "".join(c.lower() for c in text if not c.isspace()).translate(ENCODING) + return "".join(chr.lower() for chr in text if chr.isalnum()).translate(ENCODING) ``` In `encode`, we first join together every character if the character is alphanumeric - as we use `text.lower()`, the characters are all lowercase as needed. Then, we translate it and return a version joining every five characters with a space in between. @@ -23,25 +24,25 @@ It might be cleaner to use helper functions: ```python from string import ascii_lowercase ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) -def _clean(text): - return "".join([c.lower() for c in text if c.isalnum()]) -def _chunk(text): +def clean(text): + return "".join([chr.lower() for chr in text if chr.isalnum()]) +def chunk(text): return " ".join(text[i:i+5] for i in range(0, len(text), 5)) def encode(text): - return _chunk(_clean(text).translate(ENCODING)) + return chunk(clean(text).translate(ENCODING)) def decode(text): - return _clean(text).translate(ENCODING) + return clean(text).translate(ENCODING) ``` -Note that checking that `c` _is_ alphanumeric achieves the same result as checking that it's _not_ whitespace, although it's not as explicit. +Note that checking that `chr` _is_ alphanumeric achieves the same result as checking that it's _not_ whitespace, although it's not as explicit. As this is a helper function, this is acceptable enough. -You can also make `_chunk` recursive: +You can also make `chunk` recursive: ```python -def _chunk(text): +def chunk(text): if len(text) <= 5: return text - return text[:5] + " " + _chunk(text[5:]) + return text[:5] + " " + chunk(text[5:]) ``` [generator expression]: https://www.programiz.com/python-programming/generator \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt b/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt index ed77151de2..996a228fc9 100644 --- a/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt +++ b/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt @@ -2,7 +2,7 @@ from string import ascii_lowercase ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def encode(text: str): - res = "".join(c for c in text.lower() if c.isalnum()).translate(ENCODING) + res = "".join(chr for chr in text.lower() if chr.isalnum()).translate(ENCODING) return " ".join(res[i:i+5] for i in range(0, len(res), 5)) def decode(text: str): - return "".join(c.lower() for c in text if not c.isspace()).translate(ENCODING) \ No newline at end of file + return "".join(chr.lower() for chr in text if not chr.isspace()).translate(ENCODING) \ No newline at end of file From d0aa70a1971fe132844de12dbd2982e3cae76744 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Thu, 20 Jul 2023 06:26:44 +0530 Subject: [PATCH 6/7] replace i to index --- .../.approaches/mono-function/content.md | 4 ++-- .../.approaches/mono-function/snippet.txt | 2 +- .../.approaches/separate-functions/content.md | 11 +++++++---- .../.approaches/separate-functions/snippet.txt | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/exercises/practice/atbash-cipher/.approaches/mono-function/content.md b/exercises/practice/atbash-cipher/.approaches/mono-function/content.md index 078387f70a..879664ce20 100644 --- a/exercises/practice/atbash-cipher/.approaches/mono-function/content.md +++ b/exercises/practice/atbash-cipher/.approaches/mono-function/content.md @@ -8,7 +8,7 @@ ENCODING = {chr: asc_low[id] for id, chr in enumerate(asc_low[::-1])} def encode(text: str, decode: bool = False): res = "".join(ENCODING.get(chr, chr) for chr in text.lower() if chr.isalnum()) - return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) + return res if decode else " ".join(res[index:index+5] for index in range(0, len(res), 5)) def decode(text: str): return encode(text, True) @@ -31,7 +31,7 @@ lowercase = {chr: alc[id] for id, chr in enumerate(alc[::-1])} def code(decode=False): def func(text): line = "".join(lowercase.get(chr, chr) for chr in text.lower() if chr.isalnum()) - return line if decode else " ".join(line[i:i+5] for i in range(0, len(line), 5)) + return line if decode else " ".join(line[index:index+5] for index in range(0, len(line), 5)) return func diff --git a/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt b/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt index 832fef5b55..84e8b79300 100644 --- a/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt +++ b/exercises/practice/atbash-cipher/.approaches/mono-function/snippet.txt @@ -3,6 +3,6 @@ ENCODING = {chr: asc_low[id] for id, chr in enumerate(asc_low[::-1])} def encode(text: str, decode: bool = False): res = "".join(ENCODING.get(chr, chr) for chr in text.lower() if chr.isalnum()) - return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) + return res if decode else " ".join(res[index:index+5] for index in range(0, len(res), 5)) def decode(text: str): return encode(text, True) \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md b/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md index b4bd580a57..60e02a2205 100644 --- a/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md +++ b/exercises/practice/atbash-cipher/.approaches/separate-functions/content.md @@ -1,15 +1,16 @@ ## Approach: Separate Functions We use `str.maketrans` to create the encoding. `.maketrans`/`.translate` is extremely fast compared to other methods of translation. +If you're interested, [read more][str-maketrans] about it. -In `encode`, we use a [generator expression][generator expression] in `str.join`, which is more efficient - and neater - than a list comprehension. +In `encode`, we use a [generator expression][generator-expression] in `str.join`, which is more efficient - and neater - than a list comprehension. ```python from string import ascii_lowercase ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def encode(text: str): res = "".join(chr for chr in text.lower() if chr.isalnum()).translate(ENCODING) - return " ".join(res[i:i+5] for i in range(0, len(res), 5)) + return " ".join(res[index:index+5] for index in range(0, len(res), 5)) def decode(text: str): return "".join(chr.lower() for chr in text if chr.isalnum()).translate(ENCODING) @@ -27,10 +28,11 @@ ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def clean(text): return "".join([chr.lower() for chr in text if chr.isalnum()]) def chunk(text): - return " ".join(text[i:i+5] for i in range(0, len(text), 5)) + return " ".join(text[index:index+5] for index in range(0, len(text), 5)) def encode(text): return chunk(clean(text).translate(ENCODING)) + def decode(text): return clean(text).translate(ENCODING) ``` @@ -45,4 +47,5 @@ def chunk(text): return text[:5] + " " + chunk(text[5:]) ``` -[generator expression]: https://www.programiz.com/python-programming/generator \ No newline at end of file +[generator-expression]: https://www.programiz.com/python-programming/generator +[str-maketrans]: https://www.programiz.com/python-programming/methods/string/maketrans \ No newline at end of file diff --git a/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt b/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt index 996a228fc9..fbfe0b75fa 100644 --- a/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt +++ b/exercises/practice/atbash-cipher/.approaches/separate-functions/snippet.txt @@ -3,6 +3,6 @@ ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def encode(text: str): res = "".join(chr for chr in text.lower() if chr.isalnum()).translate(ENCODING) - return " ".join(res[i:i+5] for i in range(0, len(res), 5)) + return " ".join(res[index:index+5] for index in range(0, len(res), 5)) def decode(text: str): return "".join(chr.lower() for chr in text if not chr.isspace()).translate(ENCODING) \ No newline at end of file From 4895aa66e811dbd7cc580e07c8df63ea4c7703ee Mon Sep 17 00:00:00 2001 From: BethanyG Date: Mon, 31 Jul 2023 08:11:31 -0700 Subject: [PATCH 7/7] Apply suggestions from code review Committing suggestions so the PR can be merged. --- exercises/practice/atbash-cipher/.approaches/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/atbash-cipher/.approaches/introduction.md b/exercises/practice/atbash-cipher/.approaches/introduction.md index d9f5addb50..dff79f96c6 100644 --- a/exercises/practice/atbash-cipher/.approaches/introduction.md +++ b/exercises/practice/atbash-cipher/.approaches/introduction.md @@ -17,7 +17,7 @@ ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1]) def encode(text: str): res = "".join(chr for chr in text.lower() if chr.isalnum()).translate(ENCODING) - return " ".join(res[i:i+5] for i in range(0, len(res), 5)) + return " ".join(res[index:index+5] for index in range(0, len(res), 5)) def decode(text: str): return "".join(chr.lower() for chr in text if chr.isalnum()).translate(ENCODING) @@ -34,7 +34,7 @@ ENCODING = {chr: asc_low[id] for id, chr in enumerate(asc_low[::-1])} def encode(text: str, decode: bool = False): res = "".join(ENCODING.get(chr, chr) for chr in text.lower() if chr.isalnum()) - return res if decode else " ".join(res[i:i+5] for i in range(0, len(res), 5)) + return res if decode else " ".join(res[index:index+5] for index in range(0, len(res), 5)) def decode(text: str): return encode(text, True)