diff --git a/2023/ruby/day_16.rb b/2023/ruby/day_16.rb new file mode 100644 index 0000000..e5bb867 --- /dev/null +++ b/2023/ruby/day_16.rb @@ -0,0 +1,47 @@ +input = ARGF.readlines(chomp: true) + .flat_map.with_index {|row, y| + row.chars.map.with_index {|elem, x| [[y,x], elem] } + }.to_h + +current = [[[0,0], [0,1]]] +seen = Set.new + +until current.empty? + coord, delta = current.shift + seen << [coord, delta] + + case [elem = input[coord], delta] + in [nil, _] + # the beam has escaped the contraption + in [?., _] | [?|, [_,0]] | [?-, [0,_]] # keep going + current << [coord.zip(delta).map { _1 + _2 }, delta] + in [?|, [0,_]] # split up and down + current << [coord.zip([-1,0]).map { _1 + _2 }, [-1,0]] + current << [coord.zip([1,0]).map { _1 + _2 }, [1,0]] + in [?-, [_,0]] # split left and right + current << [coord.zip([0,-1]).map { _1 + _2 }, [0,-1]] + current << [coord.zip([0,1]).map { _1 + _2 }, [0,1]] + in [?/, [0,1]] # going right, goes up + current << [coord.zip([-1,0]).map { _1 + _2 }, [-1,0]] + in [?/, [0,-1]] # going left, goes down + current << [coord.zip([1,0]).map { _1 + _2 }, [1,0]] + in [?/, [1,0]] # going down, goes left + current << [coord.zip([0,-1]).map { _1 + _2 }, [0,-1]] + in [?/, [-1,0]] # going up, goes right + current << [coord.zip([0,1]).map { _1 + _2 }, [0,1]] + in [?\\, [0,1]] # going right, goes down + current << [coord.zip([1,0]).map { _1 + _2 }, [1,0]] + in [?\\, [0,-1]] # going left, goes up + current << [coord.zip([-1,0]).map { _1 + _2 }, [-1,0]] + in [?\\, [1,0]] # going down, goes right + current << [coord.zip([0,1]).map { _1 + _2 }, [0,1]] + in [?\\, [-1,0]] # going up, goes left + current << [coord.zip([0,-1]).map { _1 + _2 }, [0,-1]] + else + fail "unexpected element: #{elem.inspect}" + end + + current = current.reject { seen.include?(_1) } +end + +p seen.map(&:first).select { input.has_key?(_1) }.uniq.size