-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday18.rb
86 lines (75 loc) · 1.64 KB
/
day18.rb
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
input = File.read('day18_input.txt')
#1 + 2 * 3 + 4 * 5 + 6
#(3 * 6) * 2 * 5 * 4 + (5 * 7 * 3 * 2 + 4 * (7 * 8 * 8 + 5 + 3)) + 4
#(9 + 7 + 3 * 9 * 7) + ((9 * 7 * 6 + 8) * 4 * 6 * 8)
test_input = <<EOT
1 + (2 * 3) + (4 * (5 + 6))
2 * 3 + (4 * 5)
5 + (8 * 3 + 9 + 3 * 4 * 3)
5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))
((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2
EOT
# part 1
def calculate(words)
operator = '+'
total = 0
stack = []
words.each do |word|
case word
when '+', '*'
if acc = stack.last
acc <<= word
else
operator = word
end
when '('
stack.push []
when ')'
result = calculate stack.pop
if acc = stack.last
acc <<= result
else
total = total.send operator, result
end
else # number
if acc = stack.last
acc <<= word
else
number = word.to_i
total = total.send(operator, number)
end
end
end
total
end
def parse(line)
line.split(/\b/)
.flat_map {|w| w.split(/\s/) }
.map(&:strip)
.reject {|w| w.size == 0}
.flat_map {|w| w =~ /[()]/ ? w.chars : w}
end
totals = input.strip.each_line.map do |line|
total = calculate parse(line)
puts "#{line} becomes #{total}"
total
end
puts totals.reduce :+
# part 2
Integer.class_eval do
alias_method :old_add, :+
alias_method :old_multiply, :*
def +(other)
old_multiply other
end
def *(other)
old_add other
end
end
totals = input.strip.each_line.map do |line|
new_line = line.gsub(/[+*]/) { |char| char == '+' ? '*' : '+' }
total = eval new_line
puts "#{line} becomes #{total}"
total
end
puts totals.reduce :old_add