annotate day16.rb @ 26:eb6c3a7d2f72

Constrained and more optimised route finding * Track routes so we can see if we have gone straight for too long * Track multiple routes so we can use a non-optimal route to X if it makes another route to Y through X possible (e.g. optimal route takes three consecutive steps to X, but then has to turn, whereas a longer straight earlier and two consecutive steps to X gives a much better next hop to Y) * We have a start point, so only include the nodes from the search front in "unvisited" to avoid looking at lots of irrelevant nodes
author IBBoard <dev@ibboard.co.uk>
date Sun, 17 Dec 2023 20:13:03 +0000
parents ad73a2ff3d06
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
22
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
1 #! /usr/bin/env ruby
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
2
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
3 require "set"
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
4
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
5 if ARGV.length != 1
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
6 abort("Incorrect arguments - needs input file")
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
7 elsif not File.exist? (ARGV[0])
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
8 abort("File #{ARGV[0]} did not exist")
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
9 end
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
10
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
11 file = ARGV[0]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
12
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
13 Laser = Struct.new(:x, :y, :direction)
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
14
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
15 mirror_map = {
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
16 "." => {
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
17 right: [:right],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
18 up: [:up],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
19 left: [:left],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
20 down: [:down]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
21 },
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
22 "/" => {
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
23 right: [:up],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
24 up: [:right],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
25 down: [:left],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
26 left: [:down]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
27 },
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
28 "\\" => {
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
29 right: [:down],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
30 down: [:right],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
31 up: [:left],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
32 left: [:up]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
33 },
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
34 "-" => {
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
35 right: [:right],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
36 left: [:left],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
37 down: [:left, :right],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
38 up: [:left, :right]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
39 },
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
40 "|" => {
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
41 right: [:up, :down],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
42 left: [:up, :down],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
43 down: [:down],
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
44 up: [:up]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
45 }
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
46 }
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
47
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
48 def next_positions(puzzle, mirror_map, laser)
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
49 x_prime, y_prime = case laser.direction
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
50 when :right then [laser.x + 1, laser.y]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
51 when :down then [laser.x, laser.y + 1]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
52 when :left then [laser.x - 1, laser.y]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
53 when :up then [laser.x, laser.y - 1]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
54 end
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
55 if x_prime < 0 or x_prime >= puzzle[0].length or y_prime < 0 or y_prime >= puzzle.length
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
56 []
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
57 else
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
58 new_space = puzzle[y_prime][x_prime]
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
59 # puts "#{laser.direction} to #{x_prime}, #{y_prime} (#{new_space})"
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
60 mirror_map[new_space][laser.direction].map {|dir| Laser.new(x_prime, y_prime, dir)}
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
61 end
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
62 end
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
63
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
64 puzzle = File.open(file, "r").each_line(chomp: true).map {|line| line.each_char.to_a}
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
65 lasers = next_positions(puzzle, mirror_map, Laser.new(-1, 0, :right))
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
66 energised = Array.new(puzzle.length) {Array.new(puzzle[0].length)}
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
67 energised [0][0] = 1
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
68 previous_lasers = Set.new
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
69
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
70 while lasers != []
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
71 # puts "#{lasers}"
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
72 lasers = lasers.flat_map do |laser|
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
73 next_positions(puzzle, mirror_map, laser).filter {|new_laser| !previous_lasers.include? new_laser}.each {|new_laser| energised[new_laser.y][new_laser.x] = 1; previous_lasers << new_laser}
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
74 end
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
75 end
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
76
ad73a2ff3d06 Implement Day 15 part 1 and all of Day 16
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
77 puts energised.flatten.map(&:to_i).reduce(:+)