aboutsummaryrefslogtreecommitdiff
path: root/2020/eighteen.nim
blob: fe3b49c08bf06c40c64d5d6edf4df46e33929cae (plain) (blame)
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
# Day Eighteen: Operation Order
import std/[os, strutils]

let input = paramStr(1).readFile().strip().split("\n")

# cheese: add parenthesis and eval

func evaluate(a, b: int, op: char): int =
  if op == '+':
    return a + b
  elif op == '*':
    return a * b
  else:
    debugEcho "this should never happen."
    return -1

var sum = 0
for line in input:
  var stack: seq[tuple[val: int, op: char]] = @[(0, '+')]
  for c in line:
    let last = stack.len - 1
    if c == ' ':
      discard
    elif c == '+' or c == '*':
      stack[last].op = c
    elif c == '(':
      stack.add((0, '+'))
    elif c == ')':
      stack[last-1] = (evaluate(stack[last-1].val, stack.pop.val, stack[last-1].op), '+')
    else:
      stack[last] = (evaluate(stack[last].val, parseInt($c), stack[last].op), ' ')
  sum += stack[stack.len - 1].val
echo sum

func shunting(expression: string): string =
  var stack: seq[char]
  for t in expression:
    if t == ' ':
      discard
    elif t == '+':
      while stack.len > 0 and stack[stack.len-1] == '+':
        result.add(stack.pop)
      stack.add(t)
    elif t == '*':
      while stack.len > 0 and (stack[stack.len-1] == '+' or stack[stack.len-1] == '*'):
        result.add(stack.pop)
      stack.add(t)
    elif t == '(':
      stack.add(t)
    elif t == ')':
      while stack.len > 0 and stack[stack.len - 1] != '(':
        result.add(stack.pop)
      assert stack.pop == '('
    else:
      result.add(t)
  while stack.len != 0:
    result.add(stack.pop)

func evaluate(expression: string): int =
  var stack: seq[int]
  for s in expression:
    if s == ' ':
      discard
    elif s == '+':
      stack.add(stack.pop + stack.pop)
    elif s == '*':
      stack.add(stack.pop * stack.pop)
    else:
      stack.add(parseInt($s))
  assert stack.len == 1
  return stack[0]

sum = 0
for line in input:
  sum += evaluate(line.shunting())
echo sum