# HG changeset patch # User IBBoard # Date 1702759142 0 # Node ID 19481b06146177513b19e0f970a9742a00482c56 # Parent f34254b67082abcb9c6fd1683025498366d9652f Implement tilting and cycling for Day 14 part 2 Lots of false starts trying to iterate. Eventually looked for "back in same position" to spot a loop. Then took longer to spot that "same position" isn't necessarily "start position" and loop can be offset! diff -r f34254b67082 -r 19481b061461 day14b.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day14b.rb Sat Dec 16 20:39:02 2023 +0000 @@ -0,0 +1,82 @@ +#! /usr/bin/env ruby + +require 'set' + +if ARGV.length != 1 + abort("Incorrect arguments - needs input file") +elsif not File.exist? (ARGV[0]) + abort("File #{ARGV[0]} did not exist") +end + +file = ARGV[0] + +platform = File.open(file, "r").each_line(chomp: true).map {|row| row.each_char.to_a}.to_a.transpose() + +COL_SIZE = platform[0].length +puts "Column size: #{COL_SIZE}" + +def cycle(platform) + [:north, :west, :south, :east].reduce(platform) do |platform, iter| +# puts "Push #{iter}" + result = platform.map {|col| col.chunk_while {|i, j| i != "#"}.to_a}.map do |col| + col.flat_map do |chunk| + num_movable_objects = chunk.count("O") + new_chunk = Array.new(num_movable_objects, "O") + new_chunk.concat(Array.new(chunk.length - num_movable_objects, ".")) + new_chunk[-1] = "#" if chunk[-1] == "#" + new_chunk + end + end + case iter + when :north + # Pushed it North, now we need to go West +# puts "#{result.transpose.map{|col| col.join('')}.join("\n")}\n\n" + result.transpose + when :west + # Pushed it West, now we need to go South +# puts "#{result.map{|col| col.join('')}.join("\n")}\n\n" + result.transpose.map(&:reverse) + when :south + # Pushed it South, now we need to go East +# puts "#{result.map(&:reverse).transpose.map{|col| col.join('')}.join("\n")}\n\n" + result.transpose.map(&:reverse) + when :east + # Pushed it East, now we need to get back to North alignment +# puts "#{result.map(&:reverse).transpose.map(&:reverse).transpose.map{|col| col.join('')}.join("\n")}\n\n" + result.map(&:reverse).transpose.map(&:reverse) + end + end +end + +previous_states = [] +max_cycle_length = 1000000000 +cycle_start = nil +cycle_length = max_cycle_length +(1..max_cycle_length).each do |iter| +# puts "Cycle #{iter}" + platform = cycle(platform) + if iter % 1000 == 0 + puts iter + end + cycle_start = previous_states.index platform + if !cycle_start.nil? + cycle_start += 1 # Compensate for zero-indexing in array + cycle_length = iter - cycle_start +# puts "#{iter} - #{cycle_start} + 1 = #{cycle_length}" + break + end + previous_states << platform + puts "\n\n" +end +# Already did the first cycle of the loop, so skip it +#puts "#{(max_cycle_length - cycle_start)} % #{cycle_length} = #{((max_cycle_length - cycle_start) % cycle_length)} extras" +((max_cycle_length - cycle_start) % cycle_length).times {|n| platform = cycle(platform)} +total_load = platform.reduce(0) do |weight, col| + col_weight = col.each_with_index.reduce(0) do |accum, cell| + cell_contents, cell_pos = cell + accum + (cell_contents == "O" ? (COL_SIZE - cell_pos) : 0) + end +# puts "#{col} = #{col_weight}" + weight + col_weight +end +puts total_load