159 lines
3.6 KiB
Go
159 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"AOC2022/helper"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
lines := helper.ReadTextFile(args[0])
|
|
points := make(map[[3]int]bool, len(lines))
|
|
for _, line := range lines {
|
|
point := [3]int{}
|
|
for j, number := range helper.StringSliceToIntSlice(strings.Split(line, ",")) {
|
|
point[j] = number
|
|
}
|
|
points[point] = true
|
|
}
|
|
|
|
fmt.Println(removeOpenSurfacePointsWhichHaveNoConnectionToOutside(points))
|
|
same := false
|
|
pastLenPoints := len(points)
|
|
for !same {
|
|
removeOpenSurfacePointsWhichHaveNoConnectionToOutside(points)
|
|
if pastLenPoints != len(points) {
|
|
pastLenPoints = len(points)
|
|
} else {
|
|
same = true
|
|
}
|
|
}
|
|
|
|
openSurfacesSum := 0
|
|
for point, _ := range points {
|
|
openSurfacesPoint := 6
|
|
neighbors := getNeighbors(point)
|
|
for _, neighbor := range neighbors {
|
|
if points[neighbor] {
|
|
openSurfacesPoint--
|
|
}
|
|
}
|
|
openSurfacesSum += openSurfacesPoint
|
|
}
|
|
fmt.Println(openSurfacesSum)
|
|
|
|
}
|
|
|
|
func removeOpenSurfacePointsWhichHaveNoConnectionToOutside(points map[[3]int]bool) int {
|
|
openSurfacesSum := 0
|
|
openSurfacesPoints := make(map[[3]int]bool)
|
|
for point, _ := range points {
|
|
openSurfacesPoint := 6
|
|
neighbors := getNeighbors(point)
|
|
for _, neighbor := range neighbors {
|
|
if points[neighbor] {
|
|
openSurfacesPoint--
|
|
} else {
|
|
openSurfacesPoints[neighbor] = true
|
|
}
|
|
}
|
|
openSurfacesSum += openSurfacesPoint
|
|
}
|
|
|
|
for point, _ := range openSurfacesPoints {
|
|
if !checkIfPathToOutSideExists(points, point) {
|
|
points[point] = true
|
|
}
|
|
}
|
|
return openSurfacesSum
|
|
}
|
|
|
|
func getNeighbors(point [3]int) (neighbors [6][3]int) {
|
|
directions := [][3]int{{0, -1, 0}, {+1, 0, 0}, {0, 1, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}}
|
|
for i, direction := range directions {
|
|
neighbors[i] = [3]int{point[0] + direction[0], point[1] + direction[1], point[2] + direction[2]}
|
|
}
|
|
return
|
|
}
|
|
|
|
func checkIfPathToOutSideExists(points map[[3]int]bool, startPoint [3]int) bool {
|
|
activePoints := make(map[[3]int]bool)
|
|
pointsCopy := deepCopyMap(points)
|
|
activePoints[startPoint] = true
|
|
foundAWay := false
|
|
areaLimits := getAreaLimits(points)
|
|
for !foundAWay && len(activePoints) > 0 {
|
|
step(&pointsCopy, &activePoints, &foundAWay, areaLimits)
|
|
}
|
|
return foundAWay
|
|
}
|
|
|
|
func step(points *map[[3]int]bool, activePoints *map[[3]int]bool, foundAWay *bool, areaLimits [6]int) {
|
|
activePoint := get_some_key(*activePoints)
|
|
delete(*activePoints, activePoint)
|
|
if (activePoint[0] > areaLimits[0] ||
|
|
activePoint[0] < areaLimits[1]) &&
|
|
(activePoint[1] > areaLimits[2] ||
|
|
activePoint[1] < areaLimits[3]) &&
|
|
(activePoint[2] > areaLimits[4] ||
|
|
activePoint[2] < areaLimits[5]) {
|
|
*foundAWay = true
|
|
return
|
|
|
|
}
|
|
(*points)[activePoint] = true
|
|
neighbors := getNeighbors(activePoint)
|
|
for _, neighbor := range neighbors {
|
|
if !(*points)[neighbor] {
|
|
(*activePoints)[neighbor] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
func getAreaLimits(points map[[3]int]bool) [6]int {
|
|
highestX := -1
|
|
lowestX := 999999
|
|
highestY := -1
|
|
lowestY := 999999
|
|
highestZ := -1
|
|
lowestZ := 999999
|
|
for point, _ := range points {
|
|
if point[0] > highestX {
|
|
highestX = point[0]
|
|
}
|
|
if point[0] < lowestX {
|
|
lowestX = point[0]
|
|
}
|
|
if point[1] > highestY {
|
|
highestY = point[1]
|
|
}
|
|
if point[1] < lowestY {
|
|
lowestY = point[1]
|
|
}
|
|
if point[2] > highestZ {
|
|
highestZ = point[2]
|
|
}
|
|
if point[2] < lowestZ {
|
|
lowestZ = point[2]
|
|
}
|
|
}
|
|
return [6]int{highestX, lowestX, highestY, lowestY, highestZ, lowestZ}
|
|
}
|
|
|
|
func get_some_key[T any](m map[[3]int]T) [3]int {
|
|
for k := range m {
|
|
return k
|
|
}
|
|
return [3]int{-1, -1, -1}
|
|
}
|
|
|
|
func deepCopyMap(points map[[3]int]bool) map[[3]int]bool {
|
|
tmpValves := make(map[[3]int]bool)
|
|
for k, v := range points {
|
|
tmpValves[k] = v
|
|
}
|
|
return tmpValves
|
|
}
|