[2023][ruby][14.2]
change wwurxorunnozyyxupknsrnwsxmrtrknr
commit f3211f034b0c85005bf8d1b2d01cb2166d67309b
author Alpha Chen <alpha@kejadlen.dev>
date
parent vovptrul
diff --git a/2023/ruby/day_14.rb b/2023/ruby/day_14.rb
index be5d668..b83d4cb 100644
--- a/2023/ruby/day_14.rb
+++ b/2023/ruby/day_14.rb
@@ -1,5 +1,6 @@
 input = ARGF.readlines(chomp: true).map(&:chars)
 
+# part one
 p input.transpose
   .map {|col| col.chunk_while { [_1, _2].tally.fetch(?#, 0).even? }}
   .map {|col| col.flat_map { _1.sort.reverse }}
@@ -7,3 +8,49 @@ p input.transpose
   .reverse
   .each.with_index
   .sum {|row, i| row.count(?O) * (i+1) }
+
+# always tilts left
+def tilt(platform)
+  platform
+    .map {|row| row.chunk_while { [_1, _2].tally.fetch(?#, 0).even? }}
+    .map {|row| row.flat_map { _1.sort.reverse }}
+end
+
+def spin_cycle(platform)
+  return enum_for(__method__, platform) unless block_given?
+
+  loop do
+    # north
+    platform = tilt(platform.transpose).transpose
+
+    # west
+    platform = tilt(platform)
+
+    # south
+    platform = tilt(platform.reverse.transpose).transpose.reverse
+
+    # east
+    platform = tilt(platform.map(&:reverse)).map(&:reverse)
+
+    yield platform
+  end
+end
+
+# part two
+spin = spin_cycle(input)
+seen = {}
+(1_000_000_000).times do |i|
+  platform = spin.next
+  if seen.has_key?(platform.hash)
+    start, _ = seen.fetch(platform.hash)
+    i = (1_000_000_000 - start) % (i+1 - start) + start
+    p seen.find {|_,(j,_)| j == i }.fetch(1).fetch(1)
+    exit
+  end
+
+  load = platform.reverse
+    .each.with_index
+    .sum {|row, i| row.count(?O) * (i+1) }
+  seen[platform.hash] = [i+1, load]
+end
+