Skip to content

Commit 79f15a4

Browse files
authored
Merge pull request #176 from ikostan/exercism-sync/d62a8d8fd012d080
[Sync Iteration] python/wordy/2
2 parents 7a543d5 + 9b56cbc commit 79f15a4

1 file changed

Lines changed: 118 additions & 0 deletions

File tree

solutions/python/wordy/2/wordy.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""
2+
Parse and evaluate simple math word problems
3+
returning the answer as an integer.
4+
5+
Handle a set of operations, in sequence.
6+
7+
Since these are verbal word problems, evaluate
8+
the expression from left-to-right, ignoring the
9+
typical order of operations.
10+
"""
11+
12+
import string
13+
14+
STR_TO_OPERATOR: dict = {
15+
"plus": "+",
16+
"minus": "-",
17+
"multiplied": "*",
18+
"divided": "/",
19+
}
20+
21+
WRONG_OPERATORS: list[str] = [
22+
"plus?",
23+
"minus?",
24+
"multiplied?",
25+
"divided?",
26+
"plus plus",
27+
"plus multiplied",
28+
"minus multiplied",
29+
"minus minus",
30+
"multiplied multiplied",
31+
"divided divided",
32+
"What is?",
33+
]
34+
35+
36+
def answer(question: str) -> int:
37+
_validate_errors(question)
38+
result: int = 0
39+
new_question: list[str] = _reformat(question)
40+
41+
if len(new_question) <= 3:
42+
try:
43+
_validate_evaluation_pattern(new_question)
44+
eval_str: str = "".join(new_question)
45+
result = eval(eval_str)
46+
return result
47+
except Exception:
48+
raise ValueError("syntax error")
49+
50+
while len(new_question) >= 3:
51+
try:
52+
_validate_evaluation_pattern(new_question[:3])
53+
eval_str: str = "".join(new_question[:3])
54+
val: int = eval(eval_str)
55+
result = val
56+
new_question = [str(result)] + new_question[3:]
57+
if len(new_question) < 3:
58+
_validate_evaluation_pattern(new_question)
59+
return eval("".join(new_question))
60+
except Exception:
61+
raise ValueError("syntax error")
62+
return result
63+
64+
65+
def _validate_evaluation_pattern(val: list) -> None:
66+
if len(val) == 3 and not val[1] in STR_TO_OPERATOR.values():
67+
raise ValueError("syntax error")
68+
69+
if len(val) == 2 and not val[0] in STR_TO_OPERATOR.values():
70+
raise ValueError("syntax error")
71+
72+
73+
def _reformat(question: str) -> list:
74+
# 1: Remove '?' mark
75+
question = question.replace("?", "")
76+
# 2: Convert all operators writen in word into proper math sign
77+
question_list: list[str] = question.split()
78+
formated_question_list: list[str] = []
79+
for i, item in enumerate(question_list):
80+
if not (
81+
item.isdigit()
82+
or item in STR_TO_OPERATOR.keys()
83+
or item in STR_TO_OPERATOR.values()
84+
or any(val in item for val in STR_TO_OPERATOR.values())
85+
):
86+
continue
87+
elif item in STR_TO_OPERATOR.keys():
88+
formated_question_list.append(STR_TO_OPERATOR[item])
89+
elif item.isdigit():
90+
formated_question_list.append(item)
91+
elif item in STR_TO_OPERATOR.values():
92+
formated_question_list.append(item)
93+
elif any(val in item for val in STR_TO_OPERATOR.values()):
94+
formated_question_list.append(item)
95+
96+
return formated_question_list
97+
98+
99+
def _validate_errors(question: str) -> None:
100+
if "cubed" in question:
101+
raise ValueError("unknown operation")
102+
103+
for item in WRONG_OPERATORS:
104+
if item in question:
105+
raise ValueError("syntax error")
106+
107+
digits: list[bool] = []
108+
for char in question:
109+
if char.isdigit():
110+
digits.append(True)
111+
112+
operators: list[bool] = []
113+
for key, val in STR_TO_OPERATOR.items():
114+
if key in question or val in question:
115+
operators.append(True)
116+
117+
if not any(digits + operators):
118+
raise ValueError("unknown operation")

0 commit comments

Comments
 (0)