Skip to content

Instantly share code, notes, and snippets.

@carlwiedemann
Last active December 16, 2024 03:19
Show Gist options
  • Save carlwiedemann/ff88a47a68fd3c9533a32698be87833c to your computer and use it in GitHub Desktop.
Save carlwiedemann/ff88a47a68fd3c9533a32698be87833c to your computer and use it in GitHub Desktop.
Advent of Code 2024 day015.rb
require_relative "main"
module Day015
INPUT = File.read("INPUT.txt")
ROBOT = "@"
BOX = "O"
WALL = "#"
EMPTY = "."
UP = "^"
DOWN = "v"
LEFT = "<"
RIGHT = ">"
DIR_MAP = {
UP => V[0, -1],
DOWN => V[0, 1],
LEFT => V[-1, 0],
RIGHT => V[1, 0]
}
parts = INPUT.split("\n\n")
grid = parts[0].to_grid
dirs = parts[1].delete("\n").chars.map { |c| DIR_MAP[c] }
##########
# Part 1 #
##########
r = grid.find(ROBOT)
grid.set_value(r, EMPTY)
dirs.each do |dir|
potential = r + dir
case grid.get_value(potential)
when EMPTY
r = potential
when BOX
frontier = potential
while grid.get_value(frontier) == BOX
frontier += dir
end
if grid.get_value(frontier) == EMPTY
while frontier != potential
grid.set_value(frontier, BOX)
frontier -= dir
end
grid.set_value(potential, EMPTY)
r = potential
end
else
# Wall, do nothing
end
end
answer1 = 0
grid.each do |v, value|
if value == BOX
answer1 += 100 * v.y + v.x
end
end
pp answer1
##########
# Part 2 #
##########
BOX2L = "["
BOX2R = "]"
grid.reset
grid = grid.as_string.gsub("#", "##").gsub("O", "[]").gsub(".", "..").gsub("@", "@.").to_grid
r = grid.find(ROBOT)
grid.set_value(r, EMPTY)
dirs.each do |dir|
potential = r + dir
case grid.get_value(potential)
when EMPTY
r = potential
when BOX2L, BOX2R
if [DIR_MAP[LEFT], DIR_MAP[RIGHT]].include?(dir)
frontier = potential
while [BOX2L, BOX2R].include?(grid.get_value(frontier))
frontier += dir * 2
end
if grid.get_value(frontier) == EMPTY
while frontier != potential
first, second = (dir == DIR_MAP[LEFT]) ? [BOX2L, BOX2R] : [BOX2R, BOX2L]
grid.set_value(frontier, first)
frontier -= dir
grid.set_value(frontier, second)
frontier -= dir
end
grid.set_value(potential, EMPTY)
r = potential
end
else
frontiers = [[potential]]
stop = false
loop do
frontiers[-1].each do |v|
if grid.get_value(v) == BOX2L && !frontiers[-1].include?(v.right)
frontiers[-1].push(v.right)
elsif grid.get_value(v) == BOX2R && !frontiers[-1].include?(v.left)
frontiers[-1].push(v.left)
end
end
nexts = frontiers[-1].map { |v| v + dir }
stop = nexts.any? { |v| grid.get_value(v) == WALL }
break if stop || nexts.all? { |v| grid.get_value(v) == EMPTY }
frontiers.push(nexts.select { |v| [BOX2L, BOX2R].include?(grid.get_value(v)) })
end
unless stop
frontiers.reverse_each do |frontier|
frontier.each do |v|
grid.set_value(v + dir, grid.get_value(v))
grid.set_value(v, EMPTY)
end
end
r = potential
end
end
else
# Wall, do nothing
end
end
answer2 = 0
grid.each do |v, value|
if value == BOX2L
answer2 += 100 * v.y + v.x
end
end
pp answer2
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment