diff --git a/day18/common/lava.go b/day18/common/lava.go new file mode 100644 index 0000000..9689d3f --- /dev/null +++ b/day18/common/lava.go @@ -0,0 +1,139 @@ +package common + +import ( + "bufio" + "math" + "strconv" + "strings" +) + + +type Cube struct { + x, y, z int +} + + +type Grid struct { + cubes map[Cube]struct{} + outsideCubes map[Cube]struct{} + exposedFaces int + insideFaces int + minX, maxX, minY, maxY, minZ, maxZ int +} + +func (grid *Grid) AddCube(x, y, z int) { + grid.cubes[Cube{x, y, z}] = struct{}{} + grid.exposedFaces += 6 + grid.exposedFaces -= 2 * grid.GetCoveredFaces(x, y, z) + + if x <= grid.minX { + grid.minX = x - 1 + } + if x >= grid.maxX { + grid.maxX = x + 1 + } + if y <= grid.minY { + grid.minY = y - 1 + } + if y >= grid.maxY { + grid.maxY = y + 1 + } + if z <= grid.minZ { + grid.minZ = z - 1 + } + if z >= grid.maxZ { + grid.maxZ = z + 1 + } +} + +func (grid *Grid) PropagateWater(cube Cube, visited map[Cube]struct{}) { + grid.outsideCubes[cube] = struct{}{} + + visited2 := make(map[Cube]struct{}) + visited2[cube] = struct{}{} + + cubes := []Cube{{cube.x-1, cube.y, cube.z}, {cube.x+1, cube.y, cube.z}, + {cube.x, cube.y-1, cube.z}, {cube.x, cube.y+1, cube.z}, + {cube.x, cube.y, cube.z-1}, {cube.x, cube.y, cube.z+1}} + for _, cube2 := range cubes { + if _, ok := grid.cubes[cube2]; !ok && cube2.x >= grid.minX && cube2.x <= grid.maxX && + cube2.y >= grid.minY && cube2.y <= grid.maxY && cube2.z >= grid.minZ && cube2.z <= grid.maxZ { + if _, ok := visited[cube2]; !ok { + if _, ok := grid.outsideCubes[cube2]; !ok { + for c := range(visited) { + visited2[c] = visited[c] + } + grid.PropagateWater(cube2, visited2) + } + } + } + } +} + +func (grid *Grid) GetInsideFaces(cube Cube) int { + cubes := []Cube{{cube.x-1, cube.y, cube.z}, {cube.x+1, cube.y, cube.z}, + {cube.x, cube.y-1, cube.z}, {cube.x, cube.y+1, cube.z}, + {cube.x, cube.y, cube.z-1}, {cube.x, cube.y, cube.z+1}} + nFaces := 0 + for _, cube := range cubes { + if _, ok := grid.cubes[cube]; !ok { + if _, ok := grid.outsideCubes[cube]; !ok { + nFaces++ + } + } + } + return nFaces +} + +func (grid *Grid) GetCoveredFaces(x, y, z int) int { + coveredFaces := 0 + if _, found := grid.cubes[Cube{x-1, y, z}]; found { + coveredFaces += 1 + } + if _, found := grid.cubes[Cube{x+1, y, z}]; found { + coveredFaces += 1 + } + if _, found := grid.cubes[Cube{x, y-1, z}]; found { + coveredFaces += 1 + } + if _, found := grid.cubes[Cube{x, y+1, z}]; found { + coveredFaces += 1 + } + if _, found := grid.cubes[Cube{x, y, z-1}]; found { + coveredFaces += 1 + } + if _, found := grid.cubes[Cube{x, y, z+1}]; found { + coveredFaces += 1 + } + return coveredFaces +} + +func (grid *Grid) GetTotalExposedFaces() int { + return grid.exposedFaces +} + +func (grid *Grid) GetTotalOutsideArea() int { + return grid.exposedFaces - grid.insideFaces +} + + +func Parse(scanner bufio.Scanner) Grid { + grid := Grid{make(map[Cube]struct{}), make(map[Cube]struct{}), 0, 0, + math.MaxInt32, math.MinInt32, math.MaxInt32, math.MinInt32, math.MaxInt32, math.MinInt32} + + for scanner.Scan() { + line := scanner.Text() + splittedLine := strings.Split(line, ",") + x, _ := strconv.Atoi(splittedLine[0]) + y, _ := strconv.Atoi(splittedLine[1]) + z, _ := strconv.Atoi(splittedLine[2]) + grid.AddCube(x, y, z) + } + + grid.PropagateWater(Cube{grid.minX, grid.minY, grid.minZ}, make(map[Cube]struct{})) + for cube := range(grid.cubes) { + grid.insideFaces += grid.GetInsideFaces(cube) + } + + return grid +} diff --git a/day18/ex1/main.go b/day18/ex1/main.go new file mode 100644 index 0000000..b308fbf --- /dev/null +++ b/day18/ex1/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "aoc2022/day18/common" + "bufio" + "fmt" + "os" +) + +func main() { + grid := common.Parse(*bufio.NewScanner(os.Stdin)) + + fmt.Println(grid.GetTotalExposedFaces()) +} diff --git a/day18/ex2/main.go b/day18/ex2/main.go new file mode 100644 index 0000000..37de2dc --- /dev/null +++ b/day18/ex2/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "aoc2022/day18/common" + "bufio" + "fmt" + "os" +) + +func main() { + grid := common.Parse(*bufio.NewScanner(os.Stdin)) + + fmt.Println(grid.GetTotalOutsideArea()) +}