Mercurial > repos > other > adventofcode2023
comparison day10.rb @ 16:9b1d04091335
Path finding through the pipes for day 10
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 10 Dec 2023 19:17:56 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:5c8d2d181b94 | 16:9b1d04091335 |
---|---|
1 #! /usr/bin/env ruby | |
2 | |
3 if ARGV.length != 1 | |
4 abort("Incorrect arguments - needs input file") | |
5 elsif not File.exist? (ARGV[0]) | |
6 abort("File #{ARGV[0]} did not exist") | |
7 end | |
8 | |
9 file = ARGV[0] | |
10 | |
11 charmap = File.open(file, "r").each_line(chomp: true).map {|line| line.each_char.to_a}.to_a | |
12 $map_height = charmap.length | |
13 $map_width = charmap[0].length | |
14 | |
15 # Ugly way to find the start, because we know there's one (for now) | |
16 start = charmap.each_with_index.flat_map { |columns, i| j = columns.find_index("S"); if j then [j, i] else nil end }.compact | |
17 start_x, start_y = start | |
18 | |
19 $direction_inversion = {north: :south, south: :north, east: :west, west: :east} | |
20 | |
21 $pipemap = charmap.map do |row| | |
22 row.map do |cell| | |
23 case cell | |
24 when "|" | |
25 [:north, :south] | |
26 when "-" | |
27 [:east, :west] | |
28 when "L" | |
29 [:north, :east] | |
30 when "J" | |
31 [:north, :west] | |
32 when "7" | |
33 [:south, :west] | |
34 when "F" | |
35 [:south, :east] | |
36 when "S" | |
37 # Assume all directions are valid | |
38 [:north, :source, :east, :west] | |
39 else | |
40 [] | |
41 end | |
42 end | |
43 end | |
44 | |
45 def valid_position? (x, y) | |
46 x >= 0 and x < $map_width and y >= 0 and y < $map_height | |
47 end | |
48 | |
49 def get_target_for_step(step) | |
50 case step.direction | |
51 when :north then [step.x, step.y-1] | |
52 when :south then [step.x, step.y+1] | |
53 when :east then [step.x+1, step.y] | |
54 when :west then [step.x-1, step.y] | |
55 end | |
56 end | |
57 | |
58 def get_next_step(step) | |
59 new_x, new_y = get_target_for_step(step) | |
60 target_inputs = valid_position?(new_x, new_y) ? $pipemap[new_y][new_x] : [] | |
61 required_direction = $direction_inversion[step.direction] | |
62 target_inputs.include?(required_direction) ? Step.new(new_x, new_y, (target_inputs - [required_direction])[0]) : nil | |
63 end | |
64 | |
65 Step = Struct.new(:x, :y, :direction) | |
66 | |
67 routes = [:north, :south, :east, :west].map {|dir| [Step.new(start_x, start_y, dir)]} | |
68 | |
69 while ! routes.any? {|route| last_step = route[-1]; route.length > 1 and last_step.x == start_x and last_step.y == start_y} | |
70 routes = routes.map do |route| | |
71 next_step = get_next_step(route[-1]) | |
72 if next_step | |
73 route << next_step | |
74 else | |
75 nil | |
76 end | |
77 end.compact | |
78 end | |
79 | |
80 routes.each {|route| puts "Route: #{route.map{|step| [step.x, step.y]}}"} | |
81 # Subtract one because we end up back at the start | |
82 puts "Steps: #{routes.map{|route| (route.length - 1)/2}}" |