From 3c6d997ab30c7b1307dd9e4a391985c2bb7b2670 Mon Sep 17 00:00:00 2001 From: Renad Hamood Salim Busaidi <71909@omantel.om> Date: Tue, 23 Jun 2026 16:04:12 +0400 Subject: [PATCH 1/3] Save codingbat.py before switching branch --- Renad/codingbat.py | 182 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 Renad/codingbat.py diff --git a/Renad/codingbat.py b/Renad/codingbat.py new file mode 100644 index 0000000..7dccc34 --- /dev/null +++ b/Renad/codingbat.py @@ -0,0 +1,182 @@ +#Warmup-1 > sleep_in +def sleep_in(weekday, vacation): + if not weekday or vacation: + return True + + else: + return False + +#Warmup-1 > monkey_trouble +def monkey_trouble(a_smile, b_smile): + if a_smile and b_smile: + return True + elif not a_smile and not b_smile: + return True + elif not a_smile or not b_smile: + return False + else: + return False + +#Warmup-1 > sum_double +def sum_double(a, b): + if a != b: + return a + b + else: + return (a+b)*2 + +#Warmup-1 > diff21 +def diff21(n): + if n > 21: + return 2 * abs(21 - n) + else: + return 21 - n + +#Warmup-1 > parrot_trouble +def parrot_trouble(talking, hour): + if talking == True and (hour < 7 or hour > 20): + return True + else: + return False + +#Warmup-1 > makes10 +def makes10(a, b): + if a == 10 or b == 10: + return True + elif (a + b) == 10: + return True + else: + return False + +#Warmup-1 > near_hundred +def near_hundred(n): + return ((abs(100 - n) <= 10) or (abs(200 - n) <= 10)) + +#Warmup-1 > pos_neg +def pos_neg(a, b, negative): + if negative: + return (a < 0 and b < 0) + else: + return ((a < 0 and b > 0) or (a > 0 and b < 0)) + +#Warmup-1 > not_string +def not_string(str): + if len(str) >= 3 and str[:3] == "not": + return str + return "not " + str + +#Warmup-1 > missing_char +def missing_char(str, n): + front = str[:n] + back = str[n+1:] + return front + back + +#Warmup-1 > front_back +def front_back(str): + if len(str) <= 1: + return str + + mid = str[1:len(str)-1] # can be written as str[1:-1] + + # last + mid + first + return str[len(str)-1] + mid + str[0] + +#Warmup-1 > front3 +def front3(str): + # Figure the end of the front + front_end = 3 + if len(str) < front_end: + front_end = len(str) + front = str[:front_end] + return front + front + front + +#------------------------------------------------------------------------------------------------------------ + +#Warmup-2 > string_times +def string_times(str, n): + if n == 1 : + return str + else: + return str * n + +#Warmup-2 > front_times +def front_times(str, n): + if len(str) < 3 or len(str) >= 3: + return str[:3] * n + + +#Warmup-2 > string_bits +def string_bits(str): + result = "" + for i in range(len(str)): + if i % 2 == 0: + result = result + str[i] + return result + +#Warmup-2 > string_splosion +def string_splosion(str): + result = "" + for i in range(len(str)): + result = result + str[:i+1] + return result + +#Warmup-2 > last2 +def last2(str): + # Screen out too-short string case. + if len(str) < 2: + return 0 + + # last 2 chars, can be written as str[-2:] + last2 = str[len(str)-2:] + count = 0 + + # Check each substring length 2 starting at i + for i in range(len(str)-2): + sub = str[i:i+2] + if sub == last2: + count = count + 1 + + return count + +#Warmup-2 > array_count9 +def array_count9(nums): + count = 0 + for i in nums: + if i == 9: + count = count + 1 + return count + +#Warmup-2 > array_front9 +def array_front9(nums): + # First figure the end for the loop + end = len(nums) + if end > 4: + end = 4 + + for i in range(end): # loop over index [0, 1, 2, 3] + if nums[i] == 9: + return True + return False + +#Warmup-2 > array123 +def array123(nums): + # Note: iterate with length-2, so can use i+1 and i+2 in the loop + for i in range(len(nums)-2): + if nums[i]==1 and nums[i+1]==2 and nums[i+2]==3: + return True + return False + +#Warmup-2 > string_match +def string_match(a, b): + # Figure which string is shorter. + shorter = min(len(a), len(b)) + count = 0 + + # Loop i over every substring starting spot. + # Use length-1 here, so can use char str[i+1] in the loop + for i in range(shorter-1): + a_sub = a[i:i+2] + b_sub = b[i:i+2] + if a_sub == b_sub: + count = count + 1 + + return count# CodingBat solutions module From 7077d8a8ecdfb7a8ae36d2937c2589b904c7de64 Mon Sep 17 00:00:00 2001 From: Renad Hamood Salim Busaidi <71909@omantel.om> Date: Thu, 25 Jun 2026 11:13:40 +0400 Subject: [PATCH 2/3] Add assumptions.md and clarifications.md, rename decoding_utils.py to decoder.py --- assumptions.md | 86 +++++++++++++++++++ clarifications.md | 76 ++++++++++++++++ .../{decoding_utils.py => decoder.py} | 0 3 files changed, 162 insertions(+) create mode 100644 assumptions.md create mode 100644 clarifications.md rename project_enigma/{decoding_utils.py => decoder.py} (100%) diff --git a/assumptions.md b/assumptions.md new file mode 100644 index 0000000..ae9ed07 --- /dev/null +++ b/assumptions.md @@ -0,0 +1,86 @@ +# The Detective's Log — assumptions.md +## Project Enigma: Hidden Rules Reverse-Engineered + +--- + +## Rule 1: The COUNT uses z-encoding + +The client's note says numbers higher than 26 use "multiple characters that are added together, terminated by the first non-z character." + +I discovered this applies to the COUNT field at the start of each package: +- Read all `z` characters, each adding 26 to the running total. +- Stop at the first non-`z` letter, add its value, and that is the final count. + +**Examples discovered from test cases:** +- `d` = 4 +- `zd` = 26 + 4 = 30 (confirmed by `zdaaaaaaaabaaaaaaaabaaaaaaaabbaa` → [34] with 30 values) +- `zza` = 26 + 26 + 1 = 53 + +--- + +## Rule 2: The VALUES also use z-encoding (not stated in the client's note) + +The client's note only describes z-encoding for "numbers." I found through the test cases that individual measured values inside a package are also z-encoded — not flat single letters. + +**Evidence:** `dz_a_aazzaaa` → [28, 53, 1] +- Count = `d` = 4 +- Value 1: `z_` = 26 + 0 = 26 (z followed by `_` as terminator) +- Value 2: `a` = 1 +- Value 3: `_` = 0 +- Value 4: `a` = 1 +- Sum = 28 ✓ + +And later in the same string: `azzaaa` → count `a`=1, one value `zza` = 26+26+1 = 53 ✓ + +--- + +## Rule 3: Underscore `_` means zero in all positions + +The client's note does not mention `_` at all. I reverse-engineered its meaning: +- As a standalone value: `_` = 0 +- As the terminator of a z-encoded value: adds 0 (e.g. `z_` = 26 + 0 = 26) +- At the start of a package: signals an empty package with sum = 0 + +--- + +## Rule 4: A package starting with `_` discards the rest of its space-separated group + +This was the trickiest hidden rule. The test cases revealed a contradiction that required careful analysis: + +| Input | Expected | Observation | +|-------|----------|-------------| +| `_ad` | `[0]` | `ad` is discarded after `_` | +| `_zzzb` | `[0]` | `zzzb` is discarded after `_` | +| `__` | `[0]` | second `_` is discarded | +| `_ _` | `[0, 0]` | space separates into two valid packages | +| `aab___` | `[1, 0, 0]` | `b__` = count 2, two `_` values = 0+0=0 — NOT the discard rule | + +**Conclusion:** The discard rule only applies when `_` is the very first character in a space-separated group. When `_` appears as a value inside a normal package (e.g. after `b` in `aab___`), it is treated normally as a zero value. + +**Implementation decision:** Split the full string by spaces first, then apply the discard rule per token. + +--- + +## Rule 5: Spaces separate independent packages + +Spaces are not part of any encoding — they are delimiters between separate package groups. This is what allows `_ _` to produce two packages instead of one. + +--- + +## Summary of Encoding Structure + +``` +[PACKAGE] [PACKAGE] [PACKAGE] ... + ^space-separated^ + +Each PACKAGE: + COUNT (z-encoded) + COUNT × VALUE (each z-encoded) + + OR + + _ (zero package — rest of this space-group is discarded) + +z-encoding for a number N: + floor(N/26) × 'z' + letter_for(N mod 26) [where a=1...y=25, and z=26 via the next z] + underscore '_' counts as 0 in any terminator position +``` diff --git a/clarifications.md b/clarifications.md new file mode 100644 index 0000000..0afe8fd --- /dev/null +++ b/clarifications.md @@ -0,0 +1,76 @@ +# The Interrogation — clarifications.md +## Clarification Questions for the Client (Acme Metrics Corp) + +Hello, + +Welcome back! While you were away, I built the decoder and got all 17 test cases passing. However, I had to make several assumptions to fill in the gaps in the specification. I'd like to confirm these with you before we move to production. + +--- + +### Question 1: Does z-encoding apply to VALUES as well as counts? + +Your note only mentions that "numbers higher than 26 are encoded with multiple characters." It is clear this applies to the COUNT field. However, the test cases show it also applies to individual measured values inside a package. + +**Example:** `dz_a_aazzaaa` → [28, 53, 1] +The value `53` can only be decoded if `zza` (inside the values section) is treated as a z-encoded number = 26+26+1 = 53. + +**My assumption:** Yes, values use z-encoding too. +**Please confirm:** Is this always the case, or can values ever be plain single characters only? + +--- + +### Question 2: What does the underscore `_` mean — and is it an official part of the format? + +The client's note makes no mention of `_` at all, yet it appears in many test cases. I reverse-engineered the following rules: + +- `_` as a standalone value = 0 +- `_` as a z-encoding terminator (e.g. `z_`) = adds 0 to the sum (so `z_` = 26) +- `_` at the start of a package = empty package (sum = 0) + +**Please confirm:** Is `_` an officially supported character in the encoding format, or is it a "corrupt/missing" data marker? Should it always mean 0? + +--- + +### Question 3: The behavior of `_` at the start of a package seems inconsistent — can you clarify? + +This is the most confusing part of the test cases. Consider: + +| Input | Expected Output | Observation | +|-------|----------------|-------------| +| `__` | `[0]` | Only ONE zero returned, second `_` is ignored | +| `_ _` | `[0, 0]` | TWO zeros returned when separated by a space | +| `_ad` | `[0]` | `ad` after the `_` is completely discarded | +| `aab___` | `[1, 0, 0]` | Here `__` produces TWO zeros (they are values inside a `b=2` count package) | + +**The contradiction:** `__` alone produces `[0]`, but `__` after `aab` produces `[0, 0]`. The meaning of `__` changes depending on context. + +**My assumption:** When `_` starts a package, it signals "empty package = 0" AND discards all remaining characters until the next space. This is why `__` = `[0]` (second `_` discarded) but `_ _` = `[0, 0]` (space saves the second one). + +**My proposed production rule:** A leading `_` in a space-separated token = one zero package, rest of token discarded. Is this correct, or should `__` always mean `[0, 0]`? + +--- + +### Question 4: What should happen with completely unknown/invalid characters? + +The test cases only show letters `a–z`, underscores `_`, and spaces. What should the function do if it encounters something else (e.g. numbers, punctuation, uppercase letters)? + +**My proposed production rule:** Ignore/skip unknown characters. Please confirm. + +--- + +### Question 5: Is there a maximum package count or value size? + +The current test cases go up to values like 53. In production, could counts or values be extremely large (e.g. thousands of z's)? The current implementation handles any size, but confirming this helps with performance planning. + +--- + +### Question 6: Can a package have count = 0 explicitly (not via `_`)? + +For example, if the input is just `a` with no values following — count = 1 but no value characters exist. My current implementation returns `0` for this (the loop breaks early). Is that the intended behavior? + +--- + +Thank you for your time. Once these are confirmed, I can update the specification document and finalize the production-ready version. + +Best regards, +Renad diff --git a/project_enigma/decoding_utils.py b/project_enigma/decoder.py similarity index 100% rename from project_enigma/decoding_utils.py rename to project_enigma/decoder.py From 56c96ea45c6e2fa3465b720dff5cc8baef86d30b Mon Sep 17 00:00:00 2001 From: Renad Hamood Salim Busaidi <71909@omantel.om> Date: Thu, 25 Jun 2026 11:17:40 +0400 Subject: [PATCH 3/3] Renad decoder code --- project_enigma/decoder.py | 57 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/project_enigma/decoder.py b/project_enigma/decoder.py index 775b218..9e2c882 100644 --- a/project_enigma/decoder.py +++ b/project_enigma/decoder.py @@ -1,5 +1,5 @@ def decode_measurements(encoded_string: str) -> list[int]: - """This function decodes an encoded string into a list of integers. + """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. @@ -8,10 +8,54 @@ def decode_measurements(encoded_string: str) -> list[int]: 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. + """ + results = [] + + variables = encoded_string.split(' ') + + for variable in variables: + i = 0 + n = len(variable) + + while i < n: + if variable[i] == '_': + results.append(0) + break + + count = 0 + while i < n and variable[i] == 'z': + count = count + 26 + i = i + 1 + + if i < n and variable[i] != '_' and 'a' <= variable[i] <= 'z': + count = count + ord(variable[i]) - ord('a') + 1 + i = i + 1 + + total = 0 + for _ in range(count): + if i >= n: + break + + value = 0 + + while i < n and variable[i] == 'z': + value = value + 26 + i = i + 1 + + if i < n: + terminator = variable[i] + if terminator == '_': + value = value + 0 + else: + value = value+ ord(terminator) - ord('a') + 1 + i = i + 1 + + total = total + value + + results.append(total) + + return results if __name__ == "__main__": test_cases = [ @@ -34,7 +78,12 @@ def decode_measurements(encoded_string: str) -> list[int]: ("aab___", [1, 0, 0]), ] + passed = 0 for encoded, expected in test_cases: result = decode_measurements(encoded) status = "PASS" if result == expected else "FAIL" + if status == "PASS": + passed += 1 print(f"{status}: decode_measurements({encoded!r}) = {result} (expected {expected})") + + print(f"\nResult: {passed}/{len(test_cases)} passed") \ No newline at end of file