-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhelping_nobita.py
120 lines (91 loc) · 2.83 KB
/
helping_nobita.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import re
import itertools as it
from collections import Counter
from typing import Tuple, List
KANJI_CHAR_TO_INT = {
'一': 1,
'二': 2,
'三': 3,
'四': 4,
'五': 5,
'六': 6,
'七': 7,
'八': 8,
'九': 9,
'十': 10,
'百': 100,
'千': 1000,
'万': 10000,
}
KANJI_INT_TO_CHAR = {v: k for k, v in KANJI_CHAR_TO_INT.items()}
QUANTIFIERS = [10, 100, 1000, 10000]
class EquationException(Exception):
pass
def process_message(message: str) -> Tuple[str, str, str]:
matched = re.match(r'(?P<a>.+) OPERATOR (?P<b>.+) = (?P<c>.+)', message)
a, b, c = matched.group('a', 'b', 'c')
return a, b, c
def build_generator(digits: List[int], kanji: str):
mapping = it.permutations(digits)
mapping = map(lambda x: int(''.join(map(str, x))), mapping)
kanji_counter = Counter(kanji)
mapping = filter(lambda x: Counter(compose_kanji(x)) == kanji_counter, mapping)
return mapping
def compose_kanji(number: int) -> str:
kanji = str()
for base, digit in enumerate(reversed(str(number))):
digit = int(digit)
quantifier = 10 ** base
if digit == 0:
continue
if quantifier > 1:
kanji += KANJI_INT_TO_CHAR[quantifier]
if quantifier == 1 or digit != 1 or quantifier == 10000:
kanji += KANJI_INT_TO_CHAR[digit]
kanji = ''.join(reversed(kanji))
return kanji
def from_kanji(kanji: str):
numbers = list(map(lambda c: KANJI_CHAR_TO_INT[c], kanji))
quantifiers = list(filter(lambda x: x in QUANTIFIERS, numbers))
digits = filter(lambda x: x not in QUANTIFIERS, numbers)
digits = list(digits)
if quantifiers:
n_digits = len(str(max(*quantifiers, 1)))
while len(digits) < n_digits:
digits.append(0)
yield from build_generator(digits, kanji)
for _ in quantifiers:
if 0 not in digits:
break
digits.remove(0)
digits.append(1)
yield from build_generator(digits, kanji)
def obtain_op(a: int, b: int, c: int) -> chr:
if a + b == c:
return '+'
elif a - b == c:
return '-'
elif a * b == c:
return '*'
else:
raise EquationException
def solve_case() -> str:
message = input().strip()
a_kanji, b_kanji, c_kanji = process_message(message)
a_digits = from_kanji(a_kanji)
b_digits = from_kanji(b_kanji)
c_digits = from_kanji(c_kanji)
for a, b, c in it.product(a_digits, b_digits, c_digits):
try:
op = obtain_op(a, b, c)
return f'{a} {op} {b} = {c}'
except EquationException:
pass
raise Exception
def main() -> None:
n = int(input())
mapping = map(lambda idx: (idx + 1, solve_case()), range(n))
for i, solution in mapping:
print(f'Case #{i}: {solution}')
if __name__ == '__main__':
main()