2022 Day 18 Complete
This commit is contained in:
parent
c4d5dae456
commit
667c3a4dc9
2831
2022/day18/input
Normal file
2831
2022/day18/input
Normal file
File diff suppressed because it is too large
Load Diff
205
2022/day18/main.go
Normal file
205
2022/day18/main.go
Normal file
@ -0,0 +1,205 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
func main() {
|
||||
inp := h.StdinToStringSlice()
|
||||
part1(inp)
|
||||
part2(inp)
|
||||
}
|
||||
|
||||
func part1(inp []string) {
|
||||
scan := ParseSurface(inp)
|
||||
var surface int
|
||||
for k := range scan {
|
||||
for _, chk := range []pos{k.Top(), k.Bottom(), k.Left(), k.Right(), k.Front(), k.Back()} {
|
||||
if _, ok := scan[chk]; !ok {
|
||||
surface++
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("# Part 1")
|
||||
fmt.Println("Surface Area:", surface)
|
||||
}
|
||||
func part2(inp []string) {
|
||||
scan := ParseCubes(inp)
|
||||
scanExternal(scan)
|
||||
|
||||
var surface int
|
||||
for _, cb := range scan {
|
||||
if cb.top == nil && !cb.topInt {
|
||||
surface++
|
||||
}
|
||||
if cb.bottom == nil && !cb.bottomInt {
|
||||
surface++
|
||||
}
|
||||
if cb.right == nil && !cb.rightInt {
|
||||
surface++
|
||||
}
|
||||
if cb.left == nil && !cb.leftInt {
|
||||
surface++
|
||||
}
|
||||
if cb.front == nil && !cb.frontInt {
|
||||
surface++
|
||||
}
|
||||
if cb.back == nil && !cb.backInt {
|
||||
surface++
|
||||
}
|
||||
}
|
||||
fmt.Println("# Part 2")
|
||||
fmt.Println("External Surface Area:", surface)
|
||||
}
|
||||
|
||||
func scanExternal(m map[pos]*cube) {
|
||||
min := pos{x: math.MaxInt, y: math.MaxInt, z: math.MaxInt}
|
||||
max := pos{x: math.MinInt, y: math.MinInt, z: math.MinInt}
|
||||
for k := range m {
|
||||
min.x = h.Min(min.x, k.x)
|
||||
min.y = h.Min(min.y, k.y)
|
||||
min.z = h.Min(min.z, k.z)
|
||||
max.x = h.Max(max.x, k.x)
|
||||
max.y = h.Max(max.y, k.y)
|
||||
max.z = h.Max(max.z, k.z)
|
||||
}
|
||||
edges := make(map[pos]bool)
|
||||
for z := min.z - 1; z < max.z+1; z++ {
|
||||
for y := min.y - 1; y < max.y+1; y++ {
|
||||
for x := min.x - 1; x < max.x+1; x++ {
|
||||
edges[pos{min.x, y, z}] = true
|
||||
edges[pos{x, min.y, z}] = true
|
||||
edges[pos{x, y, min.z}] = true
|
||||
edges[pos{max.x, y, z}] = true
|
||||
edges[pos{x, max.y, z}] = true
|
||||
edges[pos{x, y, max.z}] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for k, v := range m {
|
||||
if v.left == nil && !canPath(k.Left(), edges, m) {
|
||||
v.leftInt = true
|
||||
}
|
||||
if v.right == nil && !canPath(k.Right(), edges, m) {
|
||||
v.rightInt = true
|
||||
}
|
||||
if v.top == nil && !canPath(k.Top(), edges, m) {
|
||||
v.topInt = true
|
||||
}
|
||||
if v.bottom == nil && !canPath(k.Bottom(), edges, m) {
|
||||
v.bottomInt = true
|
||||
}
|
||||
if v.front == nil && !canPath(k.Front(), edges, m) {
|
||||
v.frontInt = true
|
||||
}
|
||||
if v.back == nil && !canPath(k.Back(), edges, m) {
|
||||
v.backInt = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func canPath(from pos, to map[pos]bool, scan map[pos]*cube) bool {
|
||||
queue := []pos{from}
|
||||
visit := make(map[pos]bool)
|
||||
result := false
|
||||
for len(queue) > 0 {
|
||||
cur := queue[0]
|
||||
queue = queue[1:]
|
||||
if _, ok := to[cur]; ok {
|
||||
result = true
|
||||
break
|
||||
}
|
||||
if _, ok := visit[cur]; ok {
|
||||
continue
|
||||
}
|
||||
visit[cur] = true
|
||||
moves := []pos{
|
||||
cur.Top(), cur.Bottom(),
|
||||
cur.Left(), cur.Right(),
|
||||
cur.Front(), cur.Back(),
|
||||
}
|
||||
for _, mv := range moves {
|
||||
if _, ok := scan[mv]; ok {
|
||||
continue
|
||||
}
|
||||
queue = append(queue, mv)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func ParseSurface(inp []string) map[pos]bool {
|
||||
m := make(map[pos]bool)
|
||||
for i := range inp {
|
||||
pts := strings.Split(inp[i], ",")
|
||||
m[pos{
|
||||
x: h.Atoi(pts[0]),
|
||||
y: h.Atoi(pts[1]),
|
||||
z: h.Atoi(pts[2]),
|
||||
}] = true
|
||||
}
|
||||
return m
|
||||
}
|
||||
func ParseCubes(inp []string) map[pos]*cube {
|
||||
m := make(map[pos]*cube)
|
||||
for i := range inp {
|
||||
pts := strings.Split(inp[i], ",")
|
||||
pos := pos{
|
||||
x: h.Atoi(pts[0]),
|
||||
y: h.Atoi(pts[1]),
|
||||
z: h.Atoi(pts[2]),
|
||||
}
|
||||
m[pos] = &cube{position: pos}
|
||||
}
|
||||
for k, v := range m {
|
||||
if _, ok := m[k.Top()]; ok {
|
||||
m[k.Top()].bottom = v
|
||||
v.top = m[k.Top()]
|
||||
}
|
||||
if _, ok := m[k.Bottom()]; ok {
|
||||
m[k.Bottom()].top = v
|
||||
v.bottom = m[k.Bottom()]
|
||||
}
|
||||
if _, ok := m[k.Left()]; ok {
|
||||
m[k.Left()].right = v
|
||||
v.left = m[k.Left()]
|
||||
}
|
||||
if _, ok := m[k.Right()]; ok {
|
||||
m[k.Right()].left = v
|
||||
v.right = m[k.Right()]
|
||||
}
|
||||
if _, ok := m[k.Front()]; ok {
|
||||
m[k.Front()].back = v
|
||||
v.front = m[k.Front()]
|
||||
}
|
||||
if _, ok := m[k.Back()]; ok {
|
||||
m[k.Back()].front = v
|
||||
v.back = m[k.Back()]
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
type pos struct{ x, y, z int }
|
||||
|
||||
func (p pos) Top() pos { return pos{x: p.x, y: p.y + 1, z: p.z} }
|
||||
func (p pos) Bottom() pos { return pos{x: p.x, y: p.y - 1, z: p.z} }
|
||||
func (p pos) Left() pos { return pos{x: p.x - 1, y: p.y, z: p.z} }
|
||||
func (p pos) Right() pos { return pos{x: p.x + 1, y: p.y, z: p.z} }
|
||||
func (p pos) Front() pos { return pos{x: p.x, y: p.y, z: p.z - 1} }
|
||||
func (p pos) Back() pos { return pos{x: p.x, y: p.y, z: p.z + 1} }
|
||||
|
||||
type cube struct {
|
||||
position pos
|
||||
top, bottom *cube
|
||||
front, back *cube
|
||||
left, right *cube
|
||||
|
||||
topInt, bottomInt bool
|
||||
frontInt, backInt bool
|
||||
leftInt, rightInt bool
|
||||
}
|
93
2022/day18/problem
Normal file
93
2022/day18/problem
Normal file
@ -0,0 +1,93 @@
|
||||
Advent of Code
|
||||
br0xen (AoC++) 35*
|
||||
|
||||
--- Day 18: Boiling Boulders ---
|
||||
|
||||
You and the elephants finally reach fresh air. You've emerged near the
|
||||
base of a large volcano that seems to be actively erupting! Fortunately,
|
||||
the lava seems to be flowing away from you and toward the ocean.
|
||||
|
||||
Bits of lava are still being ejected toward you, so you're sheltering in
|
||||
the cavern exit a little longer. Outside the cave, you can see the lava
|
||||
landing in a pond and hear it loudly hissing as it solidifies.
|
||||
|
||||
Depending on the specific compounds in the lava and speed at which it
|
||||
cools, it might be forming obsidian! The cooling rate should be based on
|
||||
the surface area of the lava droplets, so you take a quick scan of a
|
||||
droplet as it flies past you (your puzzle input).
|
||||
|
||||
Because of how quickly the lava is moving, the scan isn't very good; its
|
||||
resolution is quite low and, as a result, it approximates the shape of the
|
||||
lava droplet with 1x1x1 cubes on a 3D grid, each given as its x,y,z
|
||||
position.
|
||||
|
||||
To approximate the surface area, count the number of sides of each cube
|
||||
that are not immediately connected to another cube. So, if your scan were
|
||||
only two adjacent cubes like 1,1,1 and 2,1,1, each cube would have a
|
||||
single side covered and five sides exposed, a total surface area of 10
|
||||
sides.
|
||||
|
||||
Here's a larger example:
|
||||
|
||||
2,2,2
|
||||
1,2,2
|
||||
3,2,2
|
||||
2,1,2
|
||||
2,3,2
|
||||
2,2,1
|
||||
2,2,3
|
||||
2,2,4
|
||||
2,2,6
|
||||
1,2,5
|
||||
3,2,5
|
||||
2,1,5
|
||||
2,3,5
|
||||
|
||||
In the above example, after counting up all the sides that aren't
|
||||
connected to another cube, the total surface area is 64.
|
||||
|
||||
What is the surface area of your scanned lava droplet?
|
||||
|
||||
Your puzzle answer was 4548.
|
||||
|
||||
--- Part Two ---
|
||||
|
||||
Something seems off about your calculation. The cooling rate depends on
|
||||
exterior surface area, but your calculation also included the surface area
|
||||
of air pockets trapped in the lava droplet.
|
||||
|
||||
Instead, consider only cube sides that could be reached by the water and
|
||||
steam as the lava droplet tumbles into the pond. The steam will expand to
|
||||
reach as much as possible, completely displacing any air on the outside of
|
||||
the lava droplet but never expanding diagonally.
|
||||
|
||||
In the larger example above, exactly one cube of air is trapped within the
|
||||
lava droplet (at 2,2,5), so the exterior surface area of the lava droplet
|
||||
is 58.
|
||||
|
||||
What is the exterior surface area of your scanned lava droplet?
|
||||
|
||||
Your puzzle answer was 2588.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: **
|
||||
|
||||
References
|
||||
|
||||
Visible links
|
||||
. https://adventofcode.com/
|
||||
. https://adventofcode.com/2022/about
|
||||
. https://adventofcode.com/2022/events
|
||||
. https://adventofcode.com/2022/settings
|
||||
. https://adventofcode.com/2022/auth/logout
|
||||
. Advent of Code Supporter
|
||||
https://adventofcode.com/2022/support
|
||||
. https://adventofcode.com/2022
|
||||
. https://adventofcode.com/2022
|
||||
. https://adventofcode.com/2022/support
|
||||
. https://adventofcode.com/2022/sponsors
|
||||
. https://adventofcode.com/2022/leaderboard
|
||||
. https://adventofcode.com/2022/stats
|
||||
. https://adventofcode.com/2022/sponsors
|
||||
. https://en.wikipedia.org/wiki/Obsidian
|
||||
. https://adventofcode.com/2022
|
||||
. https://adventofcode.com/2022/day/18/input
|
13
2022/day18/testinput
Normal file
13
2022/day18/testinput
Normal file
@ -0,0 +1,13 @@
|
||||
2,2,2
|
||||
1,2,2
|
||||
3,2,2
|
||||
2,1,2
|
||||
2,3,2
|
||||
2,2,1
|
||||
2,2,3
|
||||
2,2,4
|
||||
2,2,6
|
||||
1,2,5
|
||||
3,2,5
|
||||
2,1,5
|
||||
2,3,5
|
Loading…
Reference in New Issue
Block a user