From b98b09c3b8576d1ec702733b7b3e887fce924ad2 Mon Sep 17 00:00:00 2001 From: Samuel Shuert Date: Fri, 3 Oct 2025 15:17:48 +0000 Subject: [PATCH] feat: oct 3 level 2 --- python/oct3/level2/isNearlySorted.py | 40 ++++++++++++++++++ python/oct3/level2/repeatingPattern.py | 40 ++++++++++++++++++ python/oct3/level2/sortEvens.py | 37 +++++++++++++++++ python/oct3/level2/subCipher.py | 57 ++++++++++++++++++++++++++ 4 files changed, 174 insertions(+) create mode 100644 python/oct3/level2/isNearlySorted.py create mode 100644 python/oct3/level2/repeatingPattern.py create mode 100644 python/oct3/level2/sortEvens.py create mode 100644 python/oct3/level2/subCipher.py diff --git a/python/oct3/level2/isNearlySorted.py b/python/oct3/level2/isNearlySorted.py new file mode 100644 index 0000000..c44e382 --- /dev/null +++ b/python/oct3/level2/isNearlySorted.py @@ -0,0 +1,40 @@ +from typing import Sequence, Literal, Set, Tuple +from copy import deepcopy + + +def isNearlySorted(L: Sequence[float]) -> Literal[False] | Sequence[float]: + """Returns a tuple of indices that need to be swapped to sort the list, or False if it cannot be sorted with a single swap.""" + if not len(L): + return False + sortPath: Set[Tuple[int, int]] = set() + sortedList = list(deepcopy(L)) + for i in range(len(L) - 1): + for j in range(len(L) - 1, i, -1): + a = sortedList[i] + b = sortedList[j] + if a > b: + sortedList[i], sortedList[j] = b, a + sortPath.add((i, j)) + if len(sortPath) > 1: + return False + if len(sortPath) == 1: + return list(sortPath.pop()) + return False + + +print("Testing isNearlySorted()...", end="") +assert isNearlySorted([2, 7, 5, 4]) == [1, 3] +assert isNearlySorted([2, 3, 1]) == False +assert isNearlySorted([1, 2, 3]) == False +assert isNearlySorted([-1, 1, 0, 5]) == [1, 2] +assert isNearlySorted([5, 6, 9, 8, 8]) == [2, 4] +assert isNearlySorted([2, 1]) == [0, 1] +assert isNearlySorted([3, 3]) == False +assert isNearlySorted([2]) == False +assert isNearlySorted([]) == False + +# Verify that the function is non-mutating +L = [2, 7, 5, 4] +isNearlySorted(L) +assert L == [2, 7, 5, 4] +print("Passed!") diff --git a/python/oct3/level2/repeatingPattern.py b/python/oct3/level2/repeatingPattern.py new file mode 100644 index 0000000..e15b9f9 --- /dev/null +++ b/python/oct3/level2/repeatingPattern.py @@ -0,0 +1,40 @@ +from typing import List, Optional, TypeVar + + +T = TypeVar("T") + + +def repeatingPattern(L: List[T]) -> Optional[List[T]]: + """Returns the smallest repeating pattern of a list or None if no pattern exists.""" + if len(L) < 2: + return None + repeat_options = list( + reversed([i for i in range(2, max(len(L) // 2 + 1, 3)) if len(L) % i == 0]) + ) + M = [L[0]] + for repeat in repeat_options: + M = L[: len(L) // repeat] + if M * repeat == L: + return M + if len(M) > len(L): + return None + return None + + +print("Testing repeatingPattern()...", end="") +assert repeatingPattern([1, 2, 1, 2]) == [1, 2] +assert repeatingPattern([1, 2, 1, 2, 1, 2, 1, 2]) == [1, 2] +assert repeatingPattern([1, 2, 3, 1, 2, 3]) == [1, 2, 3] +assert repeatingPattern([1, 1]) == [1] +assert repeatingPattern([]) == None +assert repeatingPattern([42]) == None +assert repeatingPattern([1, 2, 3, 1, 2]) == None +assert repeatingPattern([121, 212, 12]) == None +L = [1, 2, 3, 4] +assert repeatingPattern(L * 20) == L + +# Finally, verify that the function is non-mutating +L = [1, 2, 1, 2] +repeatingPattern(L) +assert L == [1, 2, 1, 2] +print("Passed!") diff --git a/python/oct3/level2/sortEvens.py b/python/oct3/level2/sortEvens.py new file mode 100644 index 0000000..27fca9c --- /dev/null +++ b/python/oct3/level2/sortEvens.py @@ -0,0 +1,37 @@ +from typing import List + + +def sortEvens(L: List[int]): + """Sorts the even elements of a list in ascending order.""" + modifiable_indecies = [i for i, x in enumerate(L) if x % 2 == 0] + sorted_evens = sorted([L[i] for i in modifiable_indecies]) + + for i, x in enumerate(sorted_evens): + L[modifiable_indecies[i]] = x + + +print("Testing sortEvens()...", end="") +L = [1, 8, 4, 9, -2, 7] +assert sortEvens(L) == None +assert L == [1, -2, 4, 9, 8, 7] + +L = [1, 4, 3, 2, 5] +assert sortEvens(L) == None +assert L == [1, 2, 3, 4, 5] + +L = [1, 3, 2, 5] +assert sortEvens(L) == None +assert L == [1, 3, 2, 5] + +L = [3, 6, 4, -2, 8, 4, 0, 5] +assert sortEvens(L) == None +assert L == [3, -2, 0, 4, 4, 6, 8, 5] + +L = [1, 3, 5] +assert sortEvens(L) == None +assert L == [1, 3, 5] + +L = [] +assert sortEvens(L) == None +assert L == [] +print("Passed!") diff --git a/python/oct3/level2/subCipher.py b/python/oct3/level2/subCipher.py new file mode 100644 index 0000000..71bf022 --- /dev/null +++ b/python/oct3/level2/subCipher.py @@ -0,0 +1,57 @@ +from string import ascii_lowercase, ascii_uppercase + + +def encodeSubstitutionCipher(msg: str, key: str) -> str: + """Encode a message using a substitution cipher.""" + unique = set(msg) + for c in unique: + if c.isalpha(): + if c.isupper(): + encoded = key[ord(c) - ord("A")] + else: + encoded = key[ord(c) - ord("a")] + encoded = encoded.lower() + msg = msg.replace(c, encoded) + return msg + + +def decodeSubstitutionCipher(encodedMsg: str, key: str) -> str: + """Decode a message using a substitution cipher.""" + unique = set(encodedMsg) + for c in unique: + if c.isalpha(): + if c.isupper(): + decoded = ascii_uppercase[key.index(c.upper())] + else: + decoded = ascii_lowercase[key.index(c.upper())] + encodedMsg = encodedMsg.replace(c, decoded) + return encodedMsg + + +print("Testing encodeSubstitutionCipher()...", end="") +assert encodeSubstitutionCipher("CAB", "SQGYFEZXLANKJIMPURDCWTHVOB") == "GSQ" +assert encodeSubstitutionCipher("Cab Z?", "SQGYFEZXLANKJIMPURDCWTHVOB") == "Gsq B?" +assert ( + encodeSubstitutionCipher("Hello, World!", "ABCDEFGHIJKLMNOPQRSTUVWXYZ") + == "Hello, World!" +) +assert ( + encodeSubstitutionCipher("42 - 0 = 42", "XHNSBMTOPQWGZDCEAVLKJYIURF") + == "42 - 0 = 42" +) +assert encodeSubstitutionCipher("", "XHNSBMTOPQWGZDCEAVLKJYIURF") == "" + + +print("Testing decodeSubstitutionCipher()...", end="") +assert decodeSubstitutionCipher("GSQ", "SQGYFEZXLANKJIMPURDCWTHVOB") == "CAB" +assert decodeSubstitutionCipher("Gsq B?", "SQGYFEZXLANKJIMPURDCWTHVOB") == "Cab Z?" +assert ( + decodeSubstitutionCipher("Hello, World!", "ABCDEFGHIJKLMNOPQRSTUVWXYZ") + == "Hello, World!" +) +assert ( + decodeSubstitutionCipher("42 - 0 = 42", "XHNSBMTOPQWGZDCEAVLKJYIURF") + == "42 - 0 = 42" +) +assert decodeSubstitutionCipher("", "XHNSBMTOPQWGZDCEAVLKJYIURF") == "" +print("Passed!") -- 2.51.2