Skip to content

Instantly share code, notes, and snippets.

@grey-area
Last active December 19, 2022 10:25
Show Gist options
  • Save grey-area/b002b9e99bc2cb2ab2eec26660e8e241 to your computer and use it in GitHub Desktop.
Save grey-area/b002b9e99bc2cb2ab2eec26660e8e241 to your computer and use it in GitHub Desktop.
require "matrix"
require "set"
# Flood fill from min (up until max) stopping when we hit a cube.
def count_outward_faces(cubes, min, max)
# To avoid stack overflow, we aren't recursive, instead we have a list of squares to check.
to_check = [min]
to_check_set = Set[min]
# Keep track of squares we have tested (as you can get to the same square multiple ways).
visited = Set[]
# Our return.
count = 0
# From the current cube we go move by the vector below and to a bounds check on the axis index below.
operations = [
[ Vector[ 1, 0, 0], 0 ],
[ Vector[-1, 0, 0], 0 ],
[ Vector[ 0, 1, 0], 1 ],
[ Vector[ 0, -1, 0], 1 ],
[ Vector[ 0, 0, 1], 2 ],
[ Vector[ 0, 0, -1], 2 ],
]
while to_check.length > 0
t = to_check.pop()
to_check_set.delete(t)
visited << t
operations.each { |op|
test = t + op[0]
if test[op[1]] >= min[op[1]] && test[op[1]] <= max[op[1]]
if cubes.include? test
count += 1
elsif !to_check_set.include?(test) && !visited.include?(test)
to_check << test
to_check_set << test
end
end
}
end
return count
end
def count_all_faces(cubes)
all_faces = {}
cubes.each { |cube|
x0 = cube[0] - 1
x1 = cube[0]
y0 = cube[1] - 1
y1 = cube[1]
z0 = cube[2] - 1
z1 = cube[2]
# Create the 6 faces of this cube.
faces = [
# Left
[
Vector[x0, y0, z0],
Vector[x0, y0, z1],
Vector[x0, y1, z1],
Vector[x0, y1, z0],
],
# Right
[
Vector[x1, y0, z0],
Vector[x1, y0, z1],
Vector[x1, y1, z1],
Vector[x1, y1, z0],
],
# Top
[
Vector[x0, y1, z0],
Vector[x0, y1, z1],
Vector[x1, y1, z1],
Vector[x1, y1, z0],
],
# Bottom
[
Vector[x0, y0, z0],
Vector[x0, y0, z1],
Vector[x1, y0, z1],
Vector[x1, y0, z0],
],
# Front
[
Vector[x0, y0, z0],
Vector[x0, y1, z0],
Vector[x1, y1, z0],
Vector[x1, y0, z0],
],
# Back
[
Vector[x0, y0, z1],
Vector[x0, y1, z1],
Vector[x1, y1, z1],
Vector[x1, y0, z1],
],
]
# Our faces are the keys to the dictionary, the value is how many things use that face.
faces.each { |face|
if !all_faces.include? face
all_faces[face] = 1
else
all_faces[face] += 1
end
}
}
# We want unique faces, so sum the keys that have a value of 1 (only one cube uses that face).
return all_faces.count { |element| element[1] == 1 }
end
if __FILE__ == $0
next_dir = 0
min = Vector[1000000, 1000000, 1000000]
max = Vector[-1000000, -1000000, -1000000]
cubes = Set[]
File.readlines("input.txt").each { |line|
v = line.strip.split(",")
x1 = v[0].to_i
y1 = v[1].to_i
z1 = v[2].to_i
cubes << Vector[x1, y1, z1]
min = Vector[[min[0], x1].min, [min[1], y1].min, [min[2], z1].min]
max = Vector[[max[0], x1].max, [max[1], y1].max, [max[2], z1].max]
}
p1 = count_all_faces(cubes)
puts("Part 1: #{p1}")
p2 = count_outward_faces(cubes, min - Vector[1,1,1], max + Vector[1,1,1])
puts("Part 2: #{p2}")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment