diff --git a/2022/ruby/day_10.rb b/2022/ruby/day_10.rb index 1fafd2f..64020c1 100644 --- a/2022/ruby/day_10.rb +++ b/2022/ruby/day_10.rb @@ -1,25 +1,42 @@ instructions = ARGF.read.lines(chomp: true) -adds = {} -cycle = 1 -instructions.each do |instruction| - cycle += case instruction - when /noop/ - 1 - when /addx (-?\d+)/ - adds[cycle+1] = $1.to_i - 2 - else fail instruction - end +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 -xs = (0..adds.keys.max).inject([1]) { _1 << _1.last + adds.fetch(_2, 0) } -p 20.step(by: 40, to: 220).map { [_1, xs[_1]] }.sum { _1 * _2 } +x_hist = exec(instructions).to_a + +# part one +p 20.step(by: 40, to: 220).sum { x_hist[_1-1] * _1 } -puts 6.times.map {|y| - 40.times.map {|x| - cycle = 40*y + x + 1 - xx = xs.fetch(cycle, xs.last) - (-1..1).cover?(x - xx) ? ?# : ?. +# 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 diff --git a/2022/ruby/test_day_10.rb b/2022/ruby/test_day_10.rb new file mode 100644 index 0000000..5310d5a --- /dev/null +++ b/2022/ruby/test_day_10.rb @@ -0,0 +1,30 @@ +require "minitest/autorun" + +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 + +class TestDay10 < Minitest::Test + def test_example + assert_equal [1, 1, 1, 4, 4, -1], exec(<<~PROG.lines(chomp: true)).to_a + noop + addx 3 + addx -5 + PROG + end +end