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
instructions = ARGF.read.lines(chomp: true)
def exec(instructions)
return enum_for(__method__, instructions) unless block_given?
x = 1
instructions.each do |instruction|
case instruction
when /noop/
yield x
when /addx (-?\d+)/
yield x
yield x
x += $1.to_i
else
fail "invalid instruction: #{instruction}"
end
end
yield x
end
x_hist = exec(instructions).to_a
# part one
p 20.step(by: 40, to: 220).sum { x_hist[_1-1] * _1 }
# part two
puts x_hist.each_slice(40).map {|row|
row.each.with_index.map {|x, cycle|
(-1..1).cover?(cycle - x) ? ?# : ?.
}.join
}.join("\n")
# a functional version of part two, but I think
# the imperative version feels closer to the domain
#
# x_hist.each_slice(40) do |row|
# row.each.with_index do |x, cycle|
# putc (-1..1).cover?(cycle - x) ? ?# : ?.
# end
# puts
# end