[2023][ruby][18.x]
change olmussmmyxyrysxlsuyvmyzuouwsukus
commit 5760b7d09c2c837285993915f4c4080e67b51007
author Alpha Chen <alpha@kejadlen.dev>
date
parent umnkymrv
diff --git a/2023/ruby/day_18.rb b/2023/ruby/day_18.rb
new file mode 100644
index 0000000..6351c65
--- /dev/null
+++ b/2023/ruby/day_18.rb
@@ -0,0 +1,93 @@
+require "matrix"
+
+# part one
+plan = ARGF.read.scan(/([UDLR])\s+(\d+)\s+\(#(\w+)\)/)
+  .map { [_1.to_sym, _2.to_i, _3] }
+
+# part two
+plan = plan.map { _3.chars }.map {|hex|
+  dist = hex[0..4].join.to_i(16)
+  dir = "RDLU".chars.fetch(hex.last.to_i).to_sym
+  [dir, dist]
+}
+
+deltas = { U: [-1,0], D: [1,0], L: [0,-1], R: [0,1] }
+
+points = plan.inject([[0,0]]) {|points, (dir, dist, _)|
+  delta = deltas.fetch(dir).map { _1*dist }
+  next_point = points.last.zip(delta).map { _1 + _2 }
+  points << next_point
+}
+
+p [
+  (0.5 * points.each_cons(2).sum { Matrix.columns(_1).determinant }.abs).to_i,
+  plan.select {|dir,_,_| %i[ D L ].include?(dir) }.sum { _2 },
+  1,
+].sum
+
+# trench = plan.inject([[0,0]]) {|trench, (dir, dist, _)|
+#   delta = deltas.fetch(dir)
+#   dist.times do
+#     trench << trench.last.zip(delta).map { _1 + _2 }
+#   end
+#   trench
+# }.uniq
+
+# y_range = Range.new(*trench.map(&:first).minmax)
+# x_range = Range.new(*trench.map(&:last).minmax)
+
+# y_range.each do |y|
+#   x_range.each do |x|
+#     print trench.include?([y,x]) ? ?# : ?.
+#   end
+#   puts
+# end
+
+# part one
+# lagoon = trench.to_set
+
+# seed = [1, x_range.find {|x| lagoon.include?([0,x]) } + 1]
+# frontier = [seed]
+# until frontier.empty?
+#   current = frontier.shift
+#   lagoon << current
+
+#   frontier.concat(
+#     [[-1,0],[1,0],[0,-1],[0,1]].map {|delta|
+#       current.zip(delta).map { _1 + _2 }
+#     }.reject { lagoon.include?(_1) || frontier.include?(_1) }
+#   )
+# end
+
+# p lagoon.size
+
+# row_counts = {}
+
+# count = trench.size
+# y_range.each do |y|
+#   inside = nil
+
+#   segments = trench.select {|y_,_| y_ == y }.map(&:last).sort.slice_when { _1+1 != _2 }
+#   if row_count = row_counts[segments]
+#     count += row_count
+#     next
+#   end
+
+#   row_count = 0
+#   segments.each do |segment|
+#     if [-1,1].all? {|dy| [[y+dy,segment[0]],[y+dy,segment[-1]]].any? { trench.include?(_1) }}
+#       if inside
+#         row_count += segment[0] - inside
+#         inside = nil
+#       else
+#         inside = segment[-1] + 1
+#       end
+#     elsif inside
+#       row_count += segment[0] - inside
+#       inside = segment[-1] + 1
+#     end
+#   end
+#   row_counts[segments] = row_count
+#   count += row_count
+# end
+# p count