Mercurial > repos > other > adventofcode2023
comparison day14b.rb @ 24:19481b061461
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!
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sat, 16 Dec 2023 20:39:02 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
23:f34254b67082 | 24:19481b061461 |
---|---|
1 #! /usr/bin/env ruby | |
2 | |
3 require 'set' | |
4 | |
5 if ARGV.length != 1 | |
6 abort("Incorrect arguments - needs input file") | |
7 elsif not File.exist? (ARGV[0]) | |
8 abort("File #{ARGV[0]} did not exist") | |
9 end | |
10 | |
11 file = ARGV[0] | |
12 | |
13 platform = File.open(file, "r").each_line(chomp: true).map {|row| row.each_char.to_a}.to_a.transpose() | |
14 | |
15 COL_SIZE = platform[0].length | |
16 puts "Column size: #{COL_SIZE}" | |
17 | |
18 def cycle(platform) | |
19 [:north, :west, :south, :east].reduce(platform) do |platform, iter| | |
20 # puts "Push #{iter}" | |
21 result = platform.map {|col| col.chunk_while {|i, j| i != "#"}.to_a}.map do |col| | |
22 col.flat_map do |chunk| | |
23 num_movable_objects = chunk.count("O") | |
24 new_chunk = Array.new(num_movable_objects, "O") | |
25 new_chunk.concat(Array.new(chunk.length - num_movable_objects, ".")) | |
26 new_chunk[-1] = "#" if chunk[-1] == "#" | |
27 new_chunk | |
28 end | |
29 end | |
30 case iter | |
31 when :north | |
32 # Pushed it North, now we need to go West | |
33 # puts "#{result.transpose.map{|col| col.join('')}.join("\n")}\n\n" | |
34 result.transpose | |
35 when :west | |
36 # Pushed it West, now we need to go South | |
37 # puts "#{result.map{|col| col.join('')}.join("\n")}\n\n" | |
38 result.transpose.map(&:reverse) | |
39 when :south | |
40 # Pushed it South, now we need to go East | |
41 # puts "#{result.map(&:reverse).transpose.map{|col| col.join('')}.join("\n")}\n\n" | |
42 result.transpose.map(&:reverse) | |
43 when :east | |
44 # Pushed it East, now we need to get back to North alignment | |
45 # puts "#{result.map(&:reverse).transpose.map(&:reverse).transpose.map{|col| col.join('')}.join("\n")}\n\n" | |
46 result.map(&:reverse).transpose.map(&:reverse) | |
47 end | |
48 end | |
49 end | |
50 | |
51 previous_states = [] | |
52 max_cycle_length = 1000000000 | |
53 cycle_start = nil | |
54 cycle_length = max_cycle_length | |
55 (1..max_cycle_length).each do |iter| | |
56 # puts "Cycle #{iter}" | |
57 platform = cycle(platform) | |
58 if iter % 1000 == 0 | |
59 puts iter | |
60 end | |
61 cycle_start = previous_states.index platform | |
62 if !cycle_start.nil? | |
63 cycle_start += 1 # Compensate for zero-indexing in array | |
64 cycle_length = iter - cycle_start | |
65 # puts "#{iter} - #{cycle_start} + 1 = #{cycle_length}" | |
66 break | |
67 end | |
68 previous_states << platform | |
69 puts "\n\n" | |
70 end | |
71 # Already did the first cycle of the loop, so skip it | |
72 #puts "#{(max_cycle_length - cycle_start)} % #{cycle_length} = #{((max_cycle_length - cycle_start) % cycle_length)} extras" | |
73 ((max_cycle_length - cycle_start) % cycle_length).times {|n| platform = cycle(platform)} | |
74 total_load = platform.reduce(0) do |weight, col| | |
75 col_weight = col.each_with_index.reduce(0) do |accum, cell| | |
76 cell_contents, cell_pos = cell | |
77 accum + (cell_contents == "O" ? (COL_SIZE - cell_pos) : 0) | |
78 end | |
79 # puts "#{col} = #{col_weight}" | |
80 weight + col_weight | |
81 end | |
82 puts total_load |