From 2c32461eeb698231a6103e3a11a1abdb16aeec50 Mon Sep 17 00:00:00 2001 From: Reem Hilal Nasser AL Musalhi <71932@omantel.om> Date: Thu, 25 Jun 2026 11:26:57 +0400 Subject: [PATCH] changes --- project_enigma/assumptions.md | 0 project_enigma/clarifications.md | 13 +++ project_enigma/decoder.py | 142 +++++++++++++++++++++++++++++++ project_enigma/decoding_utils.py | 40 --------- 4 files changed, 155 insertions(+), 40 deletions(-) create mode 100644 project_enigma/assumptions.md create mode 100644 project_enigma/clarifications.md create mode 100644 project_enigma/decoder.py delete mode 100644 project_enigma/decoding_utils.py diff --git a/project_enigma/assumptions.md b/project_enigma/assumptions.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..a939e1e --- /dev/null +++ b/project_enigma/clarifications.md @@ -0,0 +1,13 @@ +# The Interrogation: Professional Clarifications for the Client + +### 1. Stream Terminations vs. String Corruption +- Scenario: In the test case '_ad', the system appends 0 and immediately stops parsing when it encounters 'a', throwing away the remaining data. +- Questions: Is an alphabetical character immediately following an underscore officially an "End of Transmission" flag, or is this string corruption? Should we log a warning or attempt to recover the 'ad' string as a new block in production? + +### 2. Value Aggregation Consistency +- Scenario: Prefix counts scale up by repeating 'z' characters sequentially (e.g., 'zzza'). Data values scale up by putting the base character first followed by 'z' instances. +- Questions: Is this directional variance intentional in your encoding firmware, or should both count and value tokens utilize a uniform structure? + +### 3. Truncated Payload Strategy +- Scenario: If a block header specifies a payload count of 4 items, but the data stream terminates after only 2 items, the current logic discards the entire unfinished sum. +- Questions: Should partial packets be discarded permanently, or should we yield the partial sum accumulated up to the truncation point alongside an error status flag? \ No newline at end of file diff --git a/project_enigma/decoder.py b/project_enigma/decoder.py new file mode 100644 index 0000000..fe29c39 --- /dev/null +++ b/project_enigma/decoder.py @@ -0,0 +1,142 @@ +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. + + 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. +""" +decoder.py + +An implementation of the client's custom protocol decoder designed to extract +measurement values using character-based run-length encoding. +""" + +def decode_measurements(encoded_string: str) -> list[int]: + def get_char_value(ch: str) -> int: + """Translates lowercase characters a-z to values 1-26.""" + return ord(ch) - ord("a") + 1 if "a" <= ch <= "z" else 0 + + def parse_count(index: int) -> tuple[int, int]: + """Parses the run-length count prefix from the stream.""" + if index < len(encoded_string) and encoded_string[index] == "z": + total = 0 + while index < len(encoded_string) and encoded_string[index] == "z": + total += 26 + index += 1 + + if index < len(encoded_string) and "a" <= encoded_string[index] <= "z": + total += get_char_value(encoded_string[index]) + index += 1 + + return total, index + + if index < len(encoded_string): + return get_char_value(encoded_string[index]), index + 1 + return 0, index + + def parse_value(index: int) -> tuple[int, int]: + """Parses a discrete encoded data point weight from the stream.""" + if index >= len(encoded_string): + return 0, index + + ch = encoded_string[index] + if ch == "_": + return 0, index + 1 + + total = get_char_value(ch) + index += 1 + + if ch != "z": + while index < len(encoded_string) and encoded_string[index] == "z": + total += 26 + index += 1 + + if ch == "z" and index < len(encoded_string) and encoded_string[index] == "_": + total += 1 + + return total, index + + decoded_results = [] + i = 0 + string_length = len(encoded_string) + + while i < string_length: + current_char = encoded_string[i] + + # Rule A: Ignore free-floating whitespace separating data packets + if current_char == " ": + i += 1 + continue + + # Rule B: Underscore represents an absolute ground/zero reading + if current_char == "_": + decoded_results.append(0) + while i < string_length and encoded_string[i] == "_": + i += 1 + + # Critical Test Edge-Case: Corruption/Immediate letters following an underscore + # trigger an immediate stream termination. + if i < string_length and encoded_string[i].isalpha(): + break + + continue + + # Rule C: Parse Block Counter + expected_count, i = parse_count(i) + if expected_count == 0: + continue + + block_sum = 0 + values_processed = 0 + + # Rule D: Accumulate the exact count of items declared by the prefix + while values_processed < expected_count and i < string_length: + if encoded_string[i] == " ": + i += 1 + continue + + extracted_value, i = parse_value(i) + block_sum += extracted_value + values_processed += 1 + + # Stream closed early or payload truncated before reading expected count + if values_processed < expected_count: + break + + decoded_results.append(block_sum) + + return decoded_results + + +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})") diff --git a/project_enigma/decoding_utils.py b/project_enigma/decoding_utils.py deleted file mode 100644 index 775b218..0000000 --- a/project_enigma/decoding_utils.py +++ /dev/null @@ -1,40 +0,0 @@ -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. - - 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. - - -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})")