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