tangled
alpha
login
or
join now
sharparam.com
/
advent-of-code
0
fork
atom
Code for the Advent of Code event
aoc
advent-of-code
0
fork
atom
overview
issues
pulls
pipelines
Add Ruby solution for 2024 day 16
sharparam.com
1 year ago
881cc99b
ea9f71bc
+77
1 changed file
expand all
collapse all
unified
split
src
2024
16
solve.rb
+77
src/2024/16/solve.rb
···
1
1
+
#!/usr/bin/env ruby
2
2
+
# frozen_string_literal: true
3
3
+
4
4
+
require 'bundler/setup'
5
5
+
require 'aoc/point'
6
6
+
7
7
+
Point = AoC::Point2
8
8
+
9
9
+
MAZE = ARGF.readlines.flat_map.with_index { |line, y|
10
10
+
line.chomp.chars.map.with_index { |cell, x|
11
11
+
[Point[x, y], cell]
12
12
+
}
13
13
+
}.to_h
14
14
+
15
15
+
START = MAZE.find { |p, c| c == ?S }[0]
16
16
+
GOAL = MAZE.find { |p, c| c == ?E }[0]
17
17
+
18
18
+
DIRS = [
19
19
+
Point[1, 0], # Right
20
20
+
Point[0, 1], # Down
21
21
+
Point[-1, 0], # Left
22
22
+
Point[0, -1] # Up
23
23
+
].freeze
24
24
+
25
25
+
def display(path)
26
26
+
$width ||= MAZE.keys.map(&:x).max + 1
27
27
+
$height ||= MAZE.keys.map(&:y).max + 1
28
28
+
$height.times do |y|
29
29
+
$width.times do |x|
30
30
+
p = Point[x, y]
31
31
+
c = MAZE[p]
32
32
+
if c == ?. && path.include?(p)
33
33
+
print 'O'
34
34
+
else
35
35
+
print c
36
36
+
end
37
37
+
end
38
38
+
puts
39
39
+
end
40
40
+
end
41
41
+
42
42
+
def dfs2
43
43
+
stack = [[START, Point[1, 0], Set.new, 0, [START, GOAL]]]
44
44
+
min_cost = Float::INFINITY
45
45
+
pos_mins = Hash.new Float::INFINITY
46
46
+
paths = Hash.new { |h, k| h[k] = [] }
47
47
+
48
48
+
until stack.empty?
49
49
+
pos, dir, vis, cost, path = stack.pop
50
50
+
next if cost > min_cost
51
51
+
next if cost > pos_mins[pos] + 1000
52
52
+
if pos == GOAL
53
53
+
paths[cost] << path
54
54
+
min_cost = cost if cost < min_cost
55
55
+
next
56
56
+
end
57
57
+
pos_mins[pos] = cost if cost < pos_mins[pos]
58
58
+
vis.add pos
59
59
+
path << pos
60
60
+
DIRS.each do |new_dir|
61
61
+
new_pos = pos + new_dir
62
62
+
if !vis.include?(new_pos) && MAZE[new_pos] != ?#
63
63
+
turn_cost = new_dir == dir ? 0 : 1000
64
64
+
stack.push [new_pos, new_dir, vis.dup, cost + turn_cost + 1, path.dup]
65
65
+
end
66
66
+
end
67
67
+
end
68
68
+
69
69
+
[min_cost, Set.new(paths[min_cost].flatten)]
70
70
+
end
71
71
+
72
72
+
part1, paths = dfs2
73
73
+
74
74
+
# display(paths)
75
75
+
76
76
+
puts part1
77
77
+
puts paths.size