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}}"