Skip to content
Merged
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
57 changes: 35 additions & 22 deletions wordy/wordy.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@ def answer(question: str) -> int:
if word not in REPLACEABLE
]
# Reduce iteratively:
# evaluate the first three-token slice and fold the result left-to-right.
# evaluate the first two-token slice and fold the result left-to-right.
try:
result, new_question = int(new_question[0]), new_question[1:]
while new_question:
result, new_question = _math_operation(result, new_question)
_err_check(new_question)
result, new_question = (
_math_operation(result, new_question),
new_question[2:],
)
except ValueError as exc:
if exc.args[0] == "unknown operation":
raise exc
Expand All @@ -50,7 +54,7 @@ def answer(question: str) -> int:
return result


def _math_operation(result: int, question: list[str]) -> tuple[int, list[str]]:
def _math_operation(result: int, question: list[str]) -> int:
"""
Compute a single binary arithmetic step for the current operator.

Expand All @@ -64,11 +68,34 @@ def _math_operation(result: int, question: list[str]) -> tuple[int, list[str]]:
:param question: Remaining tokens starting with the operator then rhs
integer, e.g. ``['plus', '4', ...]``.
:type question: list[str]
:returns: A tuple of the new accumulated result and the remaining tokens
after consuming the operator and rhs.
:rtype: tuple[int, list[str]]
:raises ValueError: If the operator is unknown or the token sequence is
malformed.
:returns: Accumulated result after consuming the operator and rhs.
:rtype: int
"""
math_operator: str = question[0]
operand: int = int(question[1])

match STR_TO_OPERATOR[math_operator]:
case "+":
result += operand
case "-":
result -= operand
case "/":
result //= operand
case "*":
result *= operand

return result


def _err_check(question: list[str]) -> None:
"""
Validate the upcoming operator/operand tokens and raise appropriate errors.

:param question: Remaining tokens starting at the operator; used to detect
malformed sequences (e.g., missing rhs integer).
:type question: list[str]
:raises ValueError: If an unknown operation is encountered or the token
sequence is syntactically invalid.
"""
math_operator: str = question[0]
# if the question contains an unknown operation.
Expand All @@ -80,17 +107,3 @@ def _math_operation(result: int, question: list[str]) -> tuple[int, list[str]]:
# if the question is malformed or invalid.
if math_operator in STR_TO_OPERATOR and len(question) == 1:
raise ValueError("syntax error")

if STR_TO_OPERATOR[math_operator] == "+":
result += int(question[1])

if STR_TO_OPERATOR[math_operator] == "-":
result -= int(question[1])

if STR_TO_OPERATOR[math_operator] == "/":
result //= int(question[1])

if STR_TO_OPERATOR[math_operator] == "*":
result *= int(question[1])

return result, question[2:]