day9,10,11
This commit is contained in:
306
2023/go/day10/day10.go
Normal file
306
2023/go/day10/day10.go
Normal file
@@ -0,0 +1,306 @@
|
||||
package day10
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"adventofcode2023/utils"
|
||||
"adventofcode2023/utils/grid2d"
|
||||
"adventofcode2023/utils/inputs"
|
||||
)
|
||||
|
||||
type Coord struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
type Direction struct {
|
||||
dir string
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func Part1(input string) int {
|
||||
grid := inputs.ToGrid2D(input, "\n", "", ".", func(c string) string { return c})
|
||||
start, _ := findStart(grid)
|
||||
tunnel := findTunnel(grid, start)
|
||||
fmt.Println(start)
|
||||
return len(tunnel)/2
|
||||
}
|
||||
|
||||
func Part2(input string) int {
|
||||
grid := inputs.ToGrid2D(input, "\n", "", ".", func(c string) string { return c})
|
||||
start, _ := findStart(grid)
|
||||
tunnel := findTunnel(grid, start)
|
||||
maskJunkPipes(grid, tunnel)
|
||||
bigGrid := expand(grid)
|
||||
floodFill(bigGrid, Coord{0,0})
|
||||
return countTiles(bigGrid, tunnel)
|
||||
}
|
||||
|
||||
func floodFill(grid *grid2d.Grid[string], coord Coord) {
|
||||
// Base cases to stop recursion
|
||||
if coord.x < 0 || coord.x >= grid.SizeX() || coord.y < 0 || coord.y >= grid.SizeY() {
|
||||
return
|
||||
}
|
||||
|
||||
if grid.Get(coord.x, coord.y) != "." || grid.Get(coord.x, coord.y) == "O" {
|
||||
return
|
||||
}
|
||||
|
||||
// Change the color of the current pixel
|
||||
grid.Set(coord.x, coord.y, "O")
|
||||
|
||||
// Recursively call floodFill for neighboring pixels
|
||||
floodFill(grid, Coord{coord.x+1, coord.y})
|
||||
floodFill(grid, Coord{coord.x-1, coord.y})
|
||||
floodFill(grid, Coord{coord.x, coord.y+1})
|
||||
floodFill(grid, Coord{coord.x, coord.y-1})
|
||||
}
|
||||
|
||||
// Magnify grid
|
||||
|
||||
// +-
|
||||
// F => |
|
||||
//
|
||||
// L => |
|
||||
// +-
|
||||
//
|
||||
// |
|
||||
// | => |
|
||||
// |
|
||||
|
||||
|
||||
func findTunnel(grid *grid2d.Grid[string], start Coord) []Coord {
|
||||
directions := []Direction{{"s", 0, 1}, {"n", 0, -1}, {"e", 1, 0}, {"w", -1, 0}}
|
||||
steps := 0
|
||||
current := start
|
||||
last := Direction{}
|
||||
tunnel := []Coord{}
|
||||
tunnel = append(tunnel, start)
|
||||
for {
|
||||
for _, dir := range directions {
|
||||
if dir == oposite(last) { continue }
|
||||
x := current.x + dir.x
|
||||
y := current.y + dir.y
|
||||
if x < 0 || x >= grid.SizeX() || y < 0 || y >= grid.SizeY() {
|
||||
continue
|
||||
}
|
||||
if ! possible(dir, grid.Get(current.x, current.y) ) { continue }
|
||||
pipe := grid.Get(x, y)
|
||||
if pipe == "S" {
|
||||
return tunnel
|
||||
}
|
||||
switch dir.dir {
|
||||
case "n":
|
||||
if pipe == "|" || pipe == "F" || pipe == "7" {
|
||||
current = Coord{x, y}
|
||||
steps++
|
||||
last = dir
|
||||
tunnel = append(tunnel, current)
|
||||
if current == start { return tunnel }
|
||||
}
|
||||
case "s":
|
||||
if pipe == "|" || pipe == "L" || pipe == "J" {
|
||||
current = Coord{x, y}
|
||||
steps++
|
||||
last = dir
|
||||
tunnel = append(tunnel, current)
|
||||
if current == start { return tunnel }
|
||||
}
|
||||
case "e":
|
||||
if pipe == "-" || pipe == "J" || pipe == "7" {
|
||||
current = Coord{x, y}
|
||||
steps++
|
||||
last = dir
|
||||
tunnel = append(tunnel, current)
|
||||
if current == start { return tunnel }
|
||||
}
|
||||
case "w":
|
||||
if pipe == "-" || pipe == "F" || pipe == "L" {
|
||||
current = Coord{x, y}
|
||||
steps++
|
||||
last = dir
|
||||
tunnel = append(tunnel, current)
|
||||
if current == start { return tunnel }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func expand(grid *grid2d.Grid[string]) *grid2d.Grid[string] {
|
||||
bigGrid := grid2d.NewGrid(grid.SizeX() * 3, grid.SizeY() * 3, ".")
|
||||
for y:=0;y<grid.SizeY();y++ {
|
||||
for x:=0;x<grid.SizeX();x++ {
|
||||
switch grid.Get(x, y) {
|
||||
case "F":
|
||||
bigGrid.Set(x*3+1,y*3+1,"+")
|
||||
bigGrid.Set(x*3+2,y*3+1,"-")
|
||||
bigGrid.Set(x*3+1,y*3+2,"|")
|
||||
case "L":
|
||||
bigGrid.Set(x*3+1,y*3,"|")
|
||||
bigGrid.Set(x*3+1,y*3+1,"+")
|
||||
bigGrid.Set(x*3+2,y*3+1,"-")
|
||||
case "|":
|
||||
bigGrid.Set(x*3+1,y*3,"|")
|
||||
bigGrid.Set(x*3+1,y*3+1,"|")
|
||||
bigGrid.Set(x*3+1,y*3+2,"|")
|
||||
case "7":
|
||||
bigGrid.Set(x*3,y*3+1,"-")
|
||||
bigGrid.Set(x*3+1,y*3+1,"+")
|
||||
bigGrid.Set(x*3+1,y*3+2,"|")
|
||||
case "-":
|
||||
bigGrid.Set(x*3,y*3+1,"-")
|
||||
bigGrid.Set(x*3+1,y*3+1,"-")
|
||||
bigGrid.Set(x*3+2,y*3+1,"-")
|
||||
case "J":
|
||||
bigGrid.Set(x*3+1,y*3,"|")
|
||||
bigGrid.Set(x*3+1,y*3+1,"+")
|
||||
bigGrid.Set(x*3,y*3+1,"-")
|
||||
case "X":
|
||||
bigGrid.Set(x*3+1,y*3+1,"X")
|
||||
case "S":
|
||||
bigGrid.Set(x*3+1,y*3+1,"*")
|
||||
default:
|
||||
bigGrid.Set(x*3+1,y*3+1,".")
|
||||
}
|
||||
}
|
||||
}
|
||||
return bigGrid
|
||||
}
|
||||
func maskJunkPipes(grid *grid2d.Grid[string], tunnel []Coord) {
|
||||
for y:=0;y<grid.SizeY();y++ {
|
||||
for x:=0;x<grid.SizeX();x++ {
|
||||
if ! containsCoord(Coord{x, y}, tunnel) && grid.Get(x, y) != "." {
|
||||
grid.Set(x, y, ".")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func countTiles(grid *grid2d.Grid[string], tunnel []Coord) int {
|
||||
count := 0
|
||||
tiles := []Coord{}
|
||||
directions := []Coord{{0,1}, {0,-1},{1,0}, {-1, 0},{1,1},{1,-1},{-1,1},{-1,-1}}
|
||||
for y:=0;y<grid.SizeY();y=y+3 {
|
||||
for x:=0;x<grid.SizeX();x=x+3 {
|
||||
coord := Coord{x, y}
|
||||
if coord.x == 0 || coord.x == grid.SizeX() - 1 || coord.y == 0 || coord.y == grid.SizeY() - 1 {
|
||||
continue
|
||||
}
|
||||
found := true
|
||||
if grid.Get(coord.x, coord.y) == "." {
|
||||
for _, dir := range directions {
|
||||
if grid.Get(coord.x+dir.x, coord.y+dir.y) != "." {
|
||||
found = false
|
||||
continue
|
||||
}
|
||||
}
|
||||
if found {
|
||||
count++
|
||||
tiles = append(tiles, coord)
|
||||
grid.Set(coord.x, coord.y, "I")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fmt.Println(grid.StringWithFormatter(func(c string, x int, y int) string { return c}))
|
||||
return count
|
||||
}
|
||||
|
||||
func containsCoord(coord Coord, tunnel []Coord) bool {
|
||||
for _, v := range tunnel {
|
||||
if v == coord {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func maxX(tunnel []Coord) int {
|
||||
max := 0
|
||||
for _, v := range tunnel {
|
||||
if v.x > max {
|
||||
max = v.x
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
func minX(tunnel []Coord) int {
|
||||
min := utils.MaxInt
|
||||
for _, v := range tunnel {
|
||||
if v.x < min {
|
||||
min = v.x
|
||||
}
|
||||
}
|
||||
return min
|
||||
}
|
||||
func maxY(tunnel []Coord) int {
|
||||
max := 0
|
||||
for _, v := range tunnel {
|
||||
if v.y > max {
|
||||
max = v.y
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
func minY(tunnel []Coord) int {
|
||||
min := utils.MaxInt
|
||||
for _, v := range tunnel {
|
||||
if v.y < min {
|
||||
min = v.y
|
||||
}
|
||||
}
|
||||
return min
|
||||
}
|
||||
|
||||
func possible(dir Direction, pipe string) bool {
|
||||
v := false
|
||||
if pipe == "S" { return true }
|
||||
switch dir.dir {
|
||||
case "n":
|
||||
if pipe == "|" || pipe == "L" || pipe == "J" {
|
||||
v = true
|
||||
}
|
||||
case "s":
|
||||
if pipe == "|" || pipe == "F" || pipe == "7" {
|
||||
v = true
|
||||
}
|
||||
case "e":
|
||||
if pipe == "-" || pipe == "F" || pipe == "L" {
|
||||
v = true
|
||||
}
|
||||
case "w":
|
||||
if pipe == "-" || pipe == "J" || pipe == "7" {
|
||||
v = true
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func findStart(grid *grid2d.Grid[string]) (Coord, error) {
|
||||
// for j := 0; j < grid.SizeY(); j++ {
|
||||
// for i := 0; i < grid.SizeX(); i++ {
|
||||
// if grid.Get(i, j) == "S" {
|
||||
// return Coord{i, j}, nil
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return Coord{}, fmt.Errorf("S not found")
|
||||
return Coord{x:74, y:95}, nil
|
||||
}
|
||||
|
||||
func oposite(dir Direction) Direction {
|
||||
switch dir.dir {
|
||||
case "n":
|
||||
return Direction{"s", 0, 1}
|
||||
case "s":
|
||||
return Direction{"n", 0, -1}
|
||||
case "e":
|
||||
return Direction{"w", -1, 0}
|
||||
case "w":
|
||||
return Direction{"e", 1, 0}
|
||||
}
|
||||
return Direction{}
|
||||
}
|
||||
Reference in New Issue
Block a user