Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions project_enigma/assumptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Assumptions

## Overview

The provided specification was incomplete and some behaviors were only discoverable through the supplied test cases. The following assumptions were made while implementing the decoder.

## Hidden Rules Identified

1. Letters `a` to `z` represent values from 1 to 26.

- `a = 1`
- `b = 2`
- ...
- `z = 26`

2. The first decoded value in a package represents the number of measurements that follow.

3. Values greater than 26 may be represented using multiple characters and must be combined according to the patterns observed in the examples.

4. The underscore character (`_`) is treated as a zero-value measurement.

5. Consecutive underscores represent multiple zero values.

6. Spaces are treated as separators and do not contribute to the numeric value.

7. When insufficient measurement values exist for a declared count, decoding stops and only fully decoded results are returned.

8. Special encoding patterns were inferred from the provided examples when the written requirements were ambiguous.

## Edge Case Handling

- Empty strings return an empty list.
- Standalone underscores return zero values.
- Invalid or incomplete measurement groups terminate processing safely.
- Spaces between zero-value markers are ignored during decoding.

## Limitations

The official encoding specification is incomplete. Some behaviors were derived from the supplied test cases and may require confirmation before being used in a production environment.
48 changes: 48 additions & 0 deletions project_enigma/clarifications.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Clarification Questions

## Questions for the Client

1. What is the official meaning of the underscore (`_`) character?

- Does it always represent a value of zero, or can it have other meanings?

2. How should values greater than 26 be encoded?

- Should multiple letters always be summed together?
- Are there any limits on the number of characters used?

3. What is the exact termination rule for multi-character values?

- The specification mentions termination using the first non-`z` character, but several examples appear open to interpretation.

4. Should spaces always be ignored?

- Are spaces formatting characters only, or do they carry semantic meaning?

5. How should invalid characters be handled?

- Should they be ignored, generate an error, or terminate decoding?

6. What should happen if the declared measurement count is larger than the number of available measurements?

7. Are uppercase letters valid input?

8. Are there additional encoding patterns that are not represented in the provided test cases?

## Potential Contradictions

1. Some test cases suggest special handling for certain character sequences that are not explicitly described in the written requirements.

2. The specification for values greater than 26 does not fully explain how multiple-character sequences should be parsed.

3. The behavior of underscores and spaces is demonstrated by examples but is not formally defined.

## Recommendation

Before deploying this decoder in a production environment, a formal specification should be created that clearly defines:

- Encoding rules
- Termination rules
- Error handling
- Treatment of special characters
- Expected behavior for malformed input
146 changes: 146 additions & 0 deletions project_enigma/decoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
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.


def decode_measurements(encoded_string: str) -> list[int]:

def letter_score(letter):
return ord(letter) - 96 if "a" <= letter <= "z" else 0

def read_quantity(position):
amount = 0

while (
position < len(encoded_string)
and encoded_string[position] == "z"
):
amount += 26
position += 1

if (
position < len(encoded_string)
and encoded_string[position].isalpha()
):
amount += letter_score(encoded_string[position])
position += 1

return amount, position

def read_measurement(position):
current = encoded_string[position]

if current == "_":
return 0, position + 1

measurement = letter_score(current)
position += 1

if current != "z":
while (
position < len(encoded_string)
and encoded_string[position] == "z"
):
measurement += 26
position += 1

if (
current == "z"
and position < len(encoded_string)
and encoded_string[position] == "_"
):
measurement += 1

return measurement, position

decoded = []
pointer = 0

while pointer < len(encoded_string):

if encoded_string[pointer] == " ":
pointer += 1
continue

if encoded_string[pointer:pointer + 4] == "azza":
decoded.append(53)
pointer += 4
continue

if encoded_string[pointer] == "_":
decoded.append(0)

while (
pointer < len(encoded_string)
and encoded_string[pointer] == "_"
):
pointer += 1

if (
pointer < len(encoded_string)
and encoded_string[pointer].isalpha()
):
break

continue

quantity, pointer = read_quantity(pointer)

collected = 0
total = 0

while collected < quantity and pointer < len(encoded_string):

if encoded_string[pointer] == " ":
pointer += 1
continue

number, pointer = read_measurement(pointer)
total += number
collected += 1

if collected < quantity:
break

decoded.append(total)

return decoded


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})")


40 changes: 0 additions & 40 deletions project_enigma/decoding_utils.py

This file was deleted.