Last active
December 16, 2024 03:19
-
-
Save carlwiedemann/ff88a47a68fd3c9533a32698be87833c to your computer and use it in GitHub Desktop.
Advent of Code 2024 day015.rb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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