Mercurial > repos > other > adventofcode2023
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day10.rb Sun Dec 10 19:17:56 2023 +0000 @@ -0,0 +1,82 @@ +#! /usr/bin/env ruby + +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] + +charmap = File.open(file, "r").each_line(chomp: true).map {|line| line.each_char.to_a}.to_a +$map_height = charmap.length +$map_width = charmap[0].length + +# Ugly way to find the start, because we know there's one (for now) +start = charmap.each_with_index.flat_map { |columns, i| j = columns.find_index("S"); if j then [j, i] else nil end }.compact +start_x, start_y = start + +$direction_inversion = {north: :south, south: :north, east: :west, west: :east} + +$pipemap = charmap.map do |row| + row.map do |cell| + case cell + when "|" + [:north, :south] + when "-" + [:east, :west] + when "L" + [:north, :east] + when "J" + [:north, :west] + when "7" + [:south, :west] + when "F" + [:south, :east] + when "S" + # Assume all directions are valid + [:north, :source, :east, :west] + else + [] + end + end +end + +def valid_position? (x, y) + x >= 0 and x < $map_width and y >= 0 and y < $map_height +end + +def get_target_for_step(step) + case step.direction + when :north then [step.x, step.y-1] + when :south then [step.x, step.y+1] + when :east then [step.x+1, step.y] + when :west then [step.x-1, step.y] + end +end + +def get_next_step(step) + new_x, new_y = get_target_for_step(step) + target_inputs = valid_position?(new_x, new_y) ? $pipemap[new_y][new_x] : [] + required_direction = $direction_inversion[step.direction] + target_inputs.include?(required_direction) ? Step.new(new_x, new_y, (target_inputs - [required_direction])[0]) : nil +end + +Step = Struct.new(:x, :y, :direction) + +routes = [:north, :south, :east, :west].map {|dir| [Step.new(start_x, start_y, dir)]} + +while ! routes.any? {|route| last_step = route[-1]; route.length > 1 and last_step.x == start_x and last_step.y == start_y} + routes = routes.map do |route| + next_step = get_next_step(route[-1]) + if next_step + route << next_step + else + nil + end + end.compact +end + +routes.each {|route| puts "Route: #{route.map{|step| [step.x, step.y]}}"} +# Subtract one because we end up back at the start +puts "Steps: #{routes.map{|route| (route.length - 1)/2}}"