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 +