-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolution.nim
74 lines (59 loc) · 1.89 KB
/
solution.nim
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
import ../../lib/imports
iterator tokens(s: string): char =
for ch in s:
if ch != ' ': yield ch
proc eval(s: string, prec = ""): int =
var nums = newSeq[int]()
var ops = newSeq[char]()
proc resolve(): int =
let b = nums.pop
let a = nums.pop
let op = ops.pop
case op
of '+': a + b
of '*': a * b
else: raise newException(ValueError, "unknown op: " & op)
for t in s.tokens:
if t.isDigit:
nums.add t.ord - '0'.ord
elif t == '(':
ops.add t
elif t == ')':
while ops[^1] != '(':
nums.add resolve()
discard ops.pop
else:
while ops.len > 0 and ops[^1] != '(' and (prec.len == 0 or prec.find(ops[^1]) >= prec.find(t)):
nums.add resolve()
ops.add t
while ops.len > 0:
nums.add resolve()
nums[0]
when defined(test):
block:
doAssert eval("1 + 2 * 3 + 4 * 5 + 6") == 71
doAssert eval("1 + (2 * 3) + (4 * (5 + 6))") == 51
doAssert eval("2 * 3 + (4 * 5)") == 26
doAssert eval("5 + (8 * 3 + 9 + 3 * 4 * 3)") == 437
doAssert eval("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))") == 12240
doAssert eval("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2") == 13632
proc part1(input: string): int =
for line in input.split("\n"):
result += eval(line)
proc eval2(s: string): int =
eval(s, "*+")
when defined(test):
block:
doAssert eval2("1 + 2 * 3 + 4 * 5 + 6") == 231
doAssert eval2("1 + (2 * 3) + (4 * (5 + 6))") == 51
doAssert eval2("2 * 3 + (4 * 5)") == 46
doAssert eval2("5 + (8 * 3 + 9 + 3 * 4 * 3)") == 1445
doAssert eval2("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))") == 669060
doAssert eval2("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2") == 23340
proc part2(input: string): int =
for line in input.split("\n"):
result += eval2(line)
when isMainModule and not defined(test):
let input = readFile("input").strip
echo part1(input)
echo part2(input)