[2023][ruby][16.1] shameless green
change ulxxntpntpvzorsrptzvprkqnqtmwppy
commit ab5f7ece1622f464e4e71b6b052bb3fc7c87d5f0
author Alpha Chen <alpha@kejadlen.dev>
date
parent mznzvrxq
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