From 4913069afa748ba9e07302ef22a27e0318b452d8 Mon Sep 17 00:00:00 2001 From: Tahani Majid Abdullah Al Hasani <71933@omantel.om> Date: Thu, 25 Jun 2026 11:27:00 +0400 Subject: [PATCH] feat: add decoder.py, assumptions.md, clarifications.md --- project_enigma/assumption.md | 0 project_enigma/clarifications.md | 0 project_enigma/decoder.py | 73 ++++++++++++++++++++++++++++++++ project_enigma/decoding_utils.py | 54 ++++++++++++++++++----- 4 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 project_enigma/assumption.md create mode 100644 project_enigma/clarifications.md create mode 100644 project_enigma/decoder.py diff --git a/project_enigma/assumption.md b/project_enigma/assumption.md new file mode 100644 index 0000000..e69de29 diff --git a/project_enigma/clarifications.md b/project_enigma/clarifications.md new file mode 100644 index 0000000..e69de29 diff --git a/project_enigma/decoder.py b/project_enigma/decoder.py new file mode 100644 index 0000000..6c9b993 --- /dev/null +++ b/project_enigma/decoder.py @@ -0,0 +1,73 @@ +def decode_measurements(encoded_string: str) -> list[int]: + results: list[int] = [] + for segment in encoded_string.split(" "): + _decode_segment(segment, results) + return results + + +def _char_value(ch: str) -> int: + if ch == '_': + return 0 + if 'a' <= ch <= 'z': + return ord(ch) - ord('a') + 1 + return 0 + + +def _read_encoded_number(s: str, pos: int) -> tuple[int, int]: + if pos >= len(s): + return 0, pos + if s[pos] != 'z': + return _char_value(s[pos]), pos + 1 + total = 0 + while pos < len(s) and s[pos] == 'z': + total += 26 + pos += 1 + if pos < len(s): + total += _char_value(s[pos]) + pos += 1 + return total, pos + + +def _decode_segment(s: str, results: list[int]) -> None: + pos = 0 + length = len(s) + while pos < length: + if s[pos] == '_': + results.append(0) + return + count, pos = _read_encoded_number(s, pos) + cycle_sum = 0 + for _ in range(count): + if pos >= length: + break + value, pos = _read_encoded_number(s, pos) + cycle_sum += value + results.append(cycle_sum) + + +if __name__ == "__main__": + test_cases = [ + ("aa", [1]), + ("abbcc", [2, 6]), + ("dz_a_aazzaaa", [28, 53, 1]), + ("a_", [0]), + ("abcdabcdab", [2, 7, 7]), + ("abcdabcdab_", [2, 7, 7, 0]), + ("zdaaaaaaaabaaaaaaaabaaaaaaaabbaa", [34]), + ("zza_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_", [26]), + ("za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa", [40, 1]), + ("_", [0]), + ("_ad", [0]), + ("a_", [0]), + ("_zzzb", [0]), + ("__", [0]), + ("", []), + ("_ _", [0, 0]), + ("aab___", [1, 0, 0]), + ] + + for encoded, expected in test_cases: + result = decode_measurements(encoded) + status = "PASS" if result == expected else "FAIL" + print(f"{status}: decode_measurements({encoded!r}) = {result} (expected {expected})") + \ No newline at end of file diff --git a/project_enigma/decoding_utils.py b/project_enigma/decoding_utils.py index 775b218..6d99b4a 100644 --- a/project_enigma/decoding_utils.py +++ b/project_enigma/decoding_utils.py @@ -1,16 +1,48 @@ def decode_measurements(encoded_string: str) -> list[int]: - """This function decodes an encoded string into a list of integers. - RULE 1: A generic logic should be implemented without handling edge cases using if statements for specific inputs. - RULE 2: The generic logic should handle all inputs and generate the expected outputs. + results: list[int] = [] + for segment in encoded_string.split(" "): + _decode_segment(segment, results) + return results - Args: - encoded_string (str): The encoded string to decode. - Returns: - list[int]: The list of decoded integers. - """ - pass # Remove this pass and place your logic here to decode the string into a list of integers based on the specified encoding rules. - return [] # Placeholder return statement; replace with actual decoding logic. +def _char_value(ch: str) -> int: + if ch == '_': + return 0 + if 'a' <= ch <= 'z': + return ord(ch) - ord('a') + 1 + return 0 + + +def _read_encoded_number(s: str, pos: int) -> tuple[int, int]: + if pos >= len(s): + return 0, pos + if s[pos] != 'z': + return _char_value(s[pos]), pos + 1 + total = 0 + while pos < len(s) and s[pos] == 'z': + total += 26 + pos += 1 + if pos < len(s): + total += _char_value(s[pos]) + pos += 1 + return total, pos + + +def _decode_segment(s: str, results: list[int]) -> None: + pos = 0 + length = len(s) + while pos < length: + if s[pos] == '_': + results.append(0) + return + count, pos = _read_encoded_number(s, pos) + cycle_sum = 0 + for _ in range(count): + if pos >= length: + break + value, pos = _read_encoded_number(s, pos) + cycle_sum += value + results.append(cycle_sum) if __name__ == "__main__": @@ -37,4 +69,4 @@ def decode_measurements(encoded_string: str) -> list[int]: for encoded, expected in test_cases: result = decode_measurements(encoded) status = "PASS" if result == expected else "FAIL" - print(f"{status}: decode_measurements({encoded!r}) = {result} (expected {expected})") + print(f"{status}: decode_measurements({encoded!r}) = {result} (expected {expected})") \ No newline at end of file