Skip to content

Commit

Permalink
Year 2016: Day 24
Browse files Browse the repository at this point in the history
  • Loading branch information
joshleaves committed Mar 14, 2024
1 parent d79660d commit 563c1e3
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ I'm also adding notes that may be useful if you're learning Ruby.

Notes for solving:
* [2015, complete](year_2015.md)
* [2016, up to day 23](year_2016.md)
* [2016, up to day 24](year_2016.md)
* [2023, up to day 04](year_2023.md)

# How to use
Expand Down
39 changes: 39 additions & 0 deletions spec/year_2016/day_24_input
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#####################################################################################################################################################################################
#.....#.#.....#.#.#...#.....#.#.#.#.....#3......#...........#.#.....#.....#.............#.#...#...#.....#...#.........#.#...............#.....#.....#.........................#.....#
#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#####.#.#.#.#####.#.###.#.#.###.#.#####.###.#.#.#.#.#####.#.#.#.#####.#.#.#####.#.#.#####.###.#.#.###.###.###.#.###.#.###.###.#.#######.#######
#.....#...#.#.....#...#.........#...........#.......#...#.#.....#.....#.#.#.......#...#.#...#...#...#.#...#...#.#...#.#.#.#.......#...#...#.....#.....#.....#...#...#.......#.#...#.#
###.#####.#.#######.###.#.#.#.#.#.#####.#.#.#.#####.#.###.#.#####.#.#.#.#.#####.#.#.#.#.#.###.#.###.#.#####.#.#.#.#.###.#.#.#.###.#.#.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#.#####.#.#.#.#
#...#1......#.....#.#.#.#.....#.#.#.....#...#.#...#.......#...........#.............#...#.....#.......#.....#.....#.#.......#.#...#.#.#.#.......#...#.#...........#.#.....#...#.#...#
#.#.###.#.###.#.#.#.#.#.#.#######.#.#.###.#.#.#.###.#####.###.#.#.#.#.#.###.#.#####.#.#.#####.#####.#.#.#.#.#.#.#.###.###.#.#####.#.#.#####.#.#.#.#.#.#.#.###.#####.###.#.#.#.#.###.#
#.....#.#.....#.#...#.#.....#.#.#.#.........#.#.#.......#.#.#.......#...#...#...#.....#.#...#.......#.....#.......#...#.....#...#...#.......#...#.#.....#...#.#.....#.#...#.#...#...#
#.#.#.#.#####.#.###.#.#.#.###.#.###.#.#.#####.#.#####.#.#.#.#.#####.#.#.#.###.#######.#.###.#.###.#.#.#.#.#.#.#####.###.#####.#.#.#.#.#####.#####.#.###.#.#.#.#.#.#.#.#####.###.#.###
#...#.#...#.........#.#...#.#...#.....#.#.....#.......#.........#.....#.....#.........#.....#...#.#.#.#.....#.#.................#.#.#.......#.......#.......#...#...#.......#.#...#.#
#.#.#.#.#.#.#.###.#.###.###.#.#.#.###.###.#.#.#.#.#.#.#########.#.###.#.#.#####.#.#.#.###.#######.#.###.#.#.#.#.#.#.#.###.#.#.###.#######.#.###.#.#.#.#.###.#.#.#.#####.###.#.#.###.#
#...#.#.#.#.#...#...#...#.............#.....#.....#...#...#.#.....#...#...#.....#.#.....#...#...........#.#.#.#.......#...#.............#...#.#...#...........#...#2#...#.....#.#.#.#
###.###.#.#####.#.#.#.#.#.#.#.#.#.#.###.###.#.#.#.###.###.#.#.#.#.#.#.###.###.#.#.#.#.###.#.#.#.###.#####.###.###.#.#.#.###.#######.###.###.#.#.#.#####.#####.###.#.#.#####.#.#.#.###
#.......#...#...........#.......#...#.#.......#.....#.....#...#...#.#.........#.......#...#.#...#...........#.#...#.#...............#.#.#.....#.......#.#.#.#.....#.........#.#.#.#.#
###.#.#.#.#.#.#.#####.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#####.#.###.#.###.#.#.#.#########.###.#.###.#.###.#.#.#.#.#######.#####.###.#.#.#.#.#####.#####.#.#.#.#.#.#######.#.###.#.#.#.#
#...#.....#.#.............#...#.#.....#.#...#.......#.........#...#...#.#...#...........#...#...........#...#...#.................#...#.#.#.....#.......#.#.#.......#...#...#...#...#
###.#.#######.#.#.#.###.#.#.#.###.#.#.#.#.#.###.#####.#.###.#.#.#.###.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#####.#.#####.#.#.#.#.#.#######.#.#.#.###.#.#.#.#.#.###.#.###.#########.###.#.#.#
#.....#...#.....#.....#...#.........#.#...#.....#...#.................#...#.#.#.......#.....#...#.#.................#.#.#.........#.....#...#.#...#.....#.................#.#.....#.#
#.#####.#.#.#####.###.#.#.#.###.###.#.#########.#.#######.###.###.#.#.#.#.#.#.#.###.#.#.#####.#.###.#.#########.#.###.###.#.###.###.#.#.#.#.#.###.#####.#.#.#######.#.###.#.#.###.###
#0#...#.#...#...........#.#.............#.#.......#.....#.#.#.....#.#.#...#.....#.#.#.......#.#...#.................#.#.#.....#...#.#.........#.......#.#...#.......#.......#.....#.#
#####.#.###.#.#.###.#####.###.#######.###.#.#.###.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#####.###.#.#####.#.#.#.###.#.#.#.#########.#.#.#.###.#.#.###.#.#####.#.#.#.#.#.###.###.#.#.#.#
#...#.#.....#.#.#...#.......#.#.#...#.........#.......#...#.#.....#.............#...........#...#.#.......#.#.....#.#...........#...#.........#.#...#.#.....#.......#...#.......#...#
###.###.###.#.###.###.#.###.###.#.#.#.#########.#####.###.#######.#.###.#.#.#.###.#.#.#.#.#.#.#.#####.###.#.#.#.#.#.#.#####.###.#.#.###.#####.#.#.#####.#.#.###.#.#####.#.#.#.#.#.#.#
#.......#...............#.....#...#...#.#...#.........#...........#.....#.....#.......#...#.....#.......#.#.#.#...#...............#.....#.....#...#.#...#...#.#.#.#.#.....#...#.#.#4#
#.#.#.#.#.#####.###.#.#####.#.###.#.###.#.#.#.###.###.#.#####.#.#####.#.#######.#.#####.#.#######.#.###.#.#.#.###.###.###.#####.#.###.#.#.#.#####.#.#.#.###.#.#.###.###.#.#.#.#.#.###
#...#...........#.......#...#.....#.#.......#.....#.........#.#.......#.#...#...#...........#.......#.....#...#...#...#.#...#.....#...#.........#...#...#.....#.....#...#...#...#...#
###.#.###.#############.#.###.###.#.###.#.#.#.#.#.#.#.#.###.#####.#.#.#.#.#.#####.###.#.#.#.#.###.#.#.#.#.#.###.#.#.###.#.#.#.###.###.#.#.###.#.#.#.#.#.#.#####.#.#.#.#.#.#.###.#.###
#...#.....#.#...#.#.#.#...........#.......#...#.....#...#...................#...#...#.#.#.#...#.......#...............#...#...#...#...#.#.#5#...#...#.#...#...#.#...#.#...#...#.#...#
#.###.###.#.#.#.#.#.#.###.#.#######.#.#.#.###.#.#.#.#.#.#.###.#.###.###.#.#.#.#.#.###.#.#.#.#.#.###.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#####.#.#.#######.#.#.#.#.#.#####.#.#######.#.#.#
#.........#.#...#.#...#...#.............#.....#...#.#.#.#.#.#.....#.#...#.....#.#.#.........#.....#.........#.....#...........#...#.........#.....#...#.#.#.#...#...........#...#...#
#.#.#.#######.#.#####.#.#.#.###.#.#######.#####.#.#.###.#.#.#.###.###.#.###.#.#.#.###.#.#.#.#####.#.###.#.#.#.#.#.#.#####.#.#.###.#.#.#.#.#####.###.#####.#.#.#.#.###.#.#.#####.#####
#...#...............#.#.......#.......#.......#.........#.#.#.#...#...#...#.......#.#.....#.#...........#...#.#.#...........#.#...#.......#.........#...#...#.....#...#.#.....#.#...#
###.#.#.#.#.#########.#.#.#.#.#.#####.#.#######.#.###.#.#.#.###.###.#.#.#.#.#.###.#.#.###.#.#####.#.###########.#.#.#####.#####.#####.#####.#.#.#.#.#.#.#####.#.#.#########.#.###.#.#
#.#...#.....#.......#.....#...#.......#.#.#...#...#...#.........#...#...#.#...#.#.........#.#.......#.#.#...#...#.........#.#.........#.....#.#.#...#.......#.#.....#.......#.#.....#
#.#.###.#.###.#.#.#.#.###.#########.#.#.#.#.#.#.###.#.#.#####.#.#.#####.#####.#.#.#########.#.#.#.###.#.#####.#.#.###.###.#.#.#.#.#.#####.###.#.###########.#.#.#.#.#.#######.#####.#
#........7#.....#.#...#.#.#.#.........#...#.#...........#.....#.......#.........#.........#.....#.......#.#.......#.#.#...#...#.#.#....6#.#.........................#...#.#.......#.#
#.###.#.###.###.###.#.#.###.###.#####.###.#.#.###.#####.###.#.###.#.#.#.#.#.#.#.#.#####.#.#.#####.#######.#.###.#.#.#####.#####.#.#.#.###.#.#.#.#.#####.#.#.###.#####.#.#.#.#.#.#.#.#
#.#...#.#...#.#.....#.#.......#...#.....#...#...#...#...#.#.....#...#.#...#...#...#.#.............#.............#.#...#.............#.#.....#.....#.......#.#.#.#.........#...#...#.#
#####################################################################################################################################################################################
33 changes: 33 additions & 0 deletions spec/year_2016/day_24_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'year_2016/day_24'

describe Year2016::Day24 do
context 'when Part 1' do
subject(:sample_one) do
<<~HEREDOC
###########
#0.1.....2#
#.#######.#
#4.......3#
###########
HEREDOC
end

it 'gives a final result' do
expect(described_class.new(sample_one, true).to_i).to eq(14)
end
end

context 'when Results' do
subject(:input_data) do
File.read('spec/year_2016/day_24_input')
end

it 'correctly answers part 1' do
expect(described_class.new(input_data, true).to_i).to eq(430)
end

it 'correctly answers part 2' do
expect(described_class.new(input_data).to_i).to eq(700)
end
end
end
13 changes: 13 additions & 0 deletions year_2016.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,16 @@ Year2016::Day21
```

Nothing to say, I'm just a sucker for virtual machines. That said, the test almost takes as long as an episode of Dragon Ball.

## Day 24: Air Duct Spelunking

```
Year2016::Day24
when Part 1
gives a final result
when Results
correctly answers part 1
correctly answers part 2
```

Look here, those are our friends, [BFS](https://en.wikipedia.org/wiki/Breadth-first_search) and [A-*](https://en.wikipedia.org/wiki/A*_search_algorithm)!
104 changes: 104 additions & 0 deletions year_2016/day_24.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
class Year2016
class Day24
attr_accessor :max_x, :max_y, :max_num

# rubocop:disable Metrics/MethodLength
def initialize(input_data, input_part_one = false)
@version = input_part_one ? 1 : 2
@input = input_data.chomp.split("\n")
@max_x = @input[0].length
@max_y = @input.length
@max_num = 0
@input = @input.join.chars.map do |char|
next true if char == '.'
next false if char == '#'

@max_num = [@max_num, char.to_i].max
char.to_i
end
@distances = {}
end
# rubocop:enable Metrics/MethodLength

def safe_passage?(pos_x, pos_y)
@input[pos_x + (pos_y * max_x)] != false
end

def position_of(number)
idx = @input.index(number)
[idx % max_x, (idx / max_x)]
end

EXPAND = [[0, 1], [0, -1], [1, 0], [-1, 0]].freeze

# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
def bfs(start, stop)
seen = Set.new
queue = [[start, 0]]
until queue.empty?
pos, steps = queue.shift
next if seen.include?(pos)
return steps if pos == stop

seen.add(pos)
EXPAND.each do |add_x, add_y|
next_x = pos[0] + add_x
next_y = pos[1] + add_y
correct_x = next_x >= 0 && next_x <= max_x
correct_y = next_y >= 0 && next_y <= max_y
next unless correct_x && correct_y
next unless safe_passage?(next_x, next_y)

queue.push([[next_x, next_y], steps + 1])
end
end
raise 'NOPE'
end
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity

def numbers
@numbers ||= (0..max_num).to_a
end

# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
def shortest_path(pos, done, todo, path, best_path)
return if path > best_path
return path + distance(pos, 0) if todo.empty? && @version == 2
return path if todo.empty? && @version == 1

todo.each do |next_pos|
next_done = done + [next_pos]
next_todo = todo - [next_pos]
next_dist = distance(pos, next_pos)
next_path = shortest_path(next_pos, next_done, next_todo, path + next_dist, best_path)
best_path = [best_path, next_path].min if next_path
end
best_path
end
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength

def distance(from, to)
@distances[[from, to].sort]
end

def calculate_distances
numbers.combination(2) do |combo|
combo.sort!
dist = bfs(position_of(combo[0]), position_of(combo[1]))
@distances[combo] = dist
end
end

def to_i
calculate_distances
best_path = 1000
numbers[1..].each do |next_pos|
next_done = [0, next_pos]
next_todo = numbers - next_done
next_path = shortest_path(next_pos, next_done, next_todo, distance(0, next_pos), best_path)
best_path = [best_path, next_path].min if next_path
end
best_path
end
end
end

0 comments on commit 563c1e3

Please sign in to comment.