You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
advent-of-code/2023/ruby/day_16.rb

48 lines
1.7 KiB

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