comparison day16.rb @ 22:ad73a2ff3d06

Implement Day 15 part 1 and all of Day 16 Hash implementation was trivial, but I skipped the rest for now. Day 16 part 1 approach works unchanged for part 2! Just needed to run repeatedly with different inputs.
author IBBoard <dev@ibboard.co.uk>
date Sat, 16 Dec 2023 14:42:06 +0000
parents
children
comparison
equal deleted inserted replaced
21:46fb65f2cb94 22:ad73a2ff3d06
1 #! /usr/bin/env ruby
2
3 require "set"
4
5 if ARGV.length != 1
6 abort("Incorrect arguments - needs input file")
7 elsif not File.exist? (ARGV[0])
8 abort("File #{ARGV[0]} did not exist")
9 end
10
11 file = ARGV[0]
12
13 Laser = Struct.new(:x, :y, :direction)
14
15 mirror_map = {
16 "." => {
17 right: [:right],
18 up: [:up],
19 left: [:left],
20 down: [:down]
21 },
22 "/" => {
23 right: [:up],
24 up: [:right],
25 down: [:left],
26 left: [:down]
27 },
28 "\\" => {
29 right: [:down],
30 down: [:right],
31 up: [:left],
32 left: [:up]
33 },
34 "-" => {
35 right: [:right],
36 left: [:left],
37 down: [:left, :right],
38 up: [:left, :right]
39 },
40 "|" => {
41 right: [:up, :down],
42 left: [:up, :down],
43 down: [:down],
44 up: [:up]
45 }
46 }
47
48 def next_positions(puzzle, mirror_map, laser)
49 x_prime, y_prime = case laser.direction
50 when :right then [laser.x + 1, laser.y]
51 when :down then [laser.x, laser.y + 1]
52 when :left then [laser.x - 1, laser.y]
53 when :up then [laser.x, laser.y - 1]
54 end
55 if x_prime < 0 or x_prime >= puzzle[0].length or y_prime < 0 or y_prime >= puzzle.length
56 []
57 else
58 new_space = puzzle[y_prime][x_prime]
59 # puts "#{laser.direction} to #{x_prime}, #{y_prime} (#{new_space})"
60 mirror_map[new_space][laser.direction].map {|dir| Laser.new(x_prime, y_prime, dir)}
61 end
62 end
63
64 puzzle = File.open(file, "r").each_line(chomp: true).map {|line| line.each_char.to_a}
65 lasers = next_positions(puzzle, mirror_map, Laser.new(-1, 0, :right))
66 energised = Array.new(puzzle.length) {Array.new(puzzle[0].length)}
67 energised [0][0] = 1
68 previous_lasers = Set.new
69
70 while lasers != []
71 # puts "#{lasers}"
72 lasers = lasers.flat_map do |laser|
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}
74 end
75 end
76
77 puts energised.flatten.map(&:to_i).reduce(:+)