2022 Day 18 Complete

This commit is contained in:
Brian Buller 2022-12-20 15:55:12 -06:00
parent c4d5dae456
commit 667c3a4dc9
4 changed files with 3142 additions and 0 deletions

2831
2022/day18/input Normal file

File diff suppressed because it is too large Load Diff

205
2022/day18/main.go Normal file
View 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
View 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
View 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