[2020][ruby][24.x]
change pnssnwklotykwntklwyyznsknzqrtvkw
commit 4881af22c07462a261d8929bfd442a5e620ea02d
author Alpha Chen <alpha@kejadlen.dev>
date
parent xppmosrv
diff --git a/2020/ruby/day_24.rb b/2020/ruby/day_24.rb
new file mode 100644
index 0000000..ca10422
--- /dev/null
+++ b/2020/ruby/day_24.rb
@@ -0,0 +1,50 @@
+require "strscan"
+
+def parse(line)
+  deltas = []
+
+  ss = StringScanner.new(line)
+  until ss.eos?
+    deltas << case
+              when ss.scan(/e/)  then [ 1, -1,  0]
+              when ss.scan(/se/) then [ 0, -1,  1]
+              when ss.scan(/sw/) then [-1,  0,  1]
+              when ss.scan(/w/)  then [-1,  1,  0]
+              when ss.scan(/nw/) then [ 0,  1, -1]
+              when ss.scan(/ne/) then [ 1,  0, -1]
+              else fail
+              end
+  end
+
+  deltas.inject {|(x,y,z),(dx,dy,dz)| [x+dx, y+dy, z+dz] }
+end
+
+tiles = Hash.new(false)
+ARGF.read.split("\n").map {|line| parse(line) }
+  .each do |tile|
+    tiles[tile] = !tiles[tile]
+  end
+
+NEIGHBORS = %w[ e se sw w nw ne ].map {|dir| parse(dir) }
+def tick(tiles)
+  candidates = tiles.keys.flat_map {|coord|
+    [
+      coord,
+      *NEIGHBORS.map {|n| coord.zip(n).map {|c,d| c + d }},
+    ]
+  }
+  candidates.map {|coord|
+    live_neighbors = NEIGHBORS.map {|n| coord.zip(n).map {|c,d| c + d }}.count {|c| tiles[c] }
+    if tiles[coord]
+      [coord, (1..2).cover?(live_neighbors)]
+    else
+      [coord, live_neighbors == 2]
+    end
+  }.to_h.select {|_,v| v }
+end
+
+100.times do
+  tiles = tick(tiles)
+end
+
+p tiles.values.count(true)