Mercurial > repos > other > adventofcode2023
annotate day10b.rb @ 35:ca54f9702892
Day 24 part 2 instructions and partial solution
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 18 Apr 2024 19:54:59 +0100 |
parents | 92144824cbb7 |
children |
rev | line source |
---|---|
17
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
1 #! /usr/bin/env ruby |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
2 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
3 if ARGV.length != 1 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
4 abort("Incorrect arguments - needs input file") |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
5 elsif not File.exist? (ARGV[0]) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
6 abort("File #{ARGV[0]} did not exist") |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
7 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
8 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
9 file = ARGV[0] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
10 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
11 charmap = File.open(file, "r").each_line(chomp: true).map {|line| line.each_char.to_a}.to_a |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
12 $map_height = charmap.length |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
13 $map_width = charmap[0].length |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
14 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
15 # Ugly way to find the start, because we know there's one (for now) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
16 start = charmap.each_with_index.flat_map { |columns, i| j = columns.find_index("S"); if j then [j, i] else nil end }.compact |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
17 start_x, start_y = start |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
18 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
19 $direction_inversion = {north: :south, south: :north, east: :west, west: :east} |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
20 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
21 $pipemap = charmap.map do |row| |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
22 row.map do |cell| |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
23 case cell |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
24 when "|" |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
25 [:north, :south] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
26 when "-" |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
27 [:east, :west] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
28 when "L" |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
29 [:north, :east] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
30 when "J" |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
31 [:north, :west] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
32 when "7" |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
33 [:south, :west] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
34 when "F" |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
35 [:south, :east] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
36 when "S" |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
37 # Assume all directions are valid |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
38 [:north, :south, :east, :west] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
39 else |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
40 [] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
41 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
42 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
43 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
44 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
45 def valid_position? (x, y) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
46 x >= 0 and x < $map_width and y >= 0 and y < $map_height |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
47 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
48 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
49 def get_target_for_step(step) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
50 case step.direction |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
51 when :north then [step.x, step.y-1] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
52 when :south then [step.x, step.y+1] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
53 when :east then [step.x+1, step.y] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
54 when :west then [step.x-1, step.y] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
55 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
56 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
57 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
58 def get_next_step(step) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
59 new_x, new_y = get_target_for_step(step) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
60 target_inputs = valid_position?(new_x, new_y) ? $pipemap[new_y][new_x] : [] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
61 required_direction = $direction_inversion[step.direction] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
62 target_inputs.include?(required_direction) ? Step.new(new_x, new_y, (target_inputs - [required_direction])[0]) : nil |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
63 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
64 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
65 Step = Struct.new(:x, :y, :direction) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
66 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
67 first_steps = [:north, :south, :east, :west].map {|dir| Step.new(start_x, start_y, dir)} |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
68 routes = first_steps.map{|v|[v]} |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
69 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
70 while ! routes.any? {|route| last_step = route[-1]; route.length > 1 and last_step.x == start_x and last_step.y == start_y} |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
71 routes = routes.map do |route| |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
72 next_step = get_next_step(route[-1]) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
73 if next_step |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
74 route << next_step |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
75 else |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
76 nil |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
77 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
78 end.compact |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
79 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
80 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
81 # We get two routes - the two opposite directions around the same path |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
82 # so take the first one |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
83 route = routes[0].map {|v| [v.x, v.y]} |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
84 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
85 in_out_transition = [:north, :south] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
86 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
87 State = Struct.new(:crossed_lines, :inside_count, :last_switch) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
88 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
89 # TODO: Replace Source with actual piece based on route |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
90 actual_start_directions = first_steps.map do |v| |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
91 step = get_next_step(v) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
92 !step.nil? and [route[1], route[-2]].include?([step.x, step.y]) ? v.direction : nil |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
93 end.filter {|v| v} |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
94 $pipemap[start_y][start_x] = actual_start_directions |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
95 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
96 cells_inside = $pipemap.each_with_index.map do |row, y| |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
97 row_state = State.new(0, 0, nil) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
98 row.each_with_index do |cell, x| |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
99 if route.include?([x,y]) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
100 if cell == in_out_transition |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
101 row_state.crossed_lines += 1 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
102 elsif cell != [:east, :west] |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
103 this_switch = (cell & in_out_transition) |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
104 if row_state.last_switch.nil? |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
105 row_state.last_switch = this_switch |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
106 else |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
107 if this_switch != row_state.last_switch |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
108 row_state.crossed_lines += 1 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
109 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
110 row_state.last_switch = nil |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
111 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
112 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
113 elsif row_state.crossed_lines % 2.0 != 0 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
114 row_state.inside_count += 1 |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
115 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
116 end |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
117 row_state |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
118 end.reduce(0) {|accum, row_state| accum + row_state.inside_count} |
92144824cbb7
Add "inside the loop" counting for day 10 part 2
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
119 puts cells_inside |