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 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{} }