package day_12 import "strings" const Empty = '.' type Map [][]rune type Point struct { x, y int } type Visited map[Point]bool func (m Map) InMap(x, y int) bool { return x >= 0 && x < len(m[0]) && y >= 0 && y < len(m) } func (m Map) At(x, y int) rune { if m.InMap(x, y) { return m[y][x] } return Empty } func (v Visited) At(x, y int) bool { _, visited := v[Point{x, y}] return visited } // task:https://adventofcode.com/2024/day/12 func SolveBasic(input string) int { farmMap := loadMap(input) visited := Visited{} sum := 0 for y, row := range farmMap { for x, value := range row { p := Point{x, y} field := Visited{} if _, present := visited[p]; !present { visit(farmMap, field, x, y, value) area := len(field) parameter := 0 for point := range field { // mark as visited to not visit it more than once visited[point] = true if _, present := field[Point{point.x - 1, point.y}]; !present { parameter++ } if _, present := field[Point{point.x + 1, point.y}]; !present { parameter++ } if _, present := field[Point{point.x, point.y - 1}]; !present { parameter++ } if _, present := field[Point{point.x, point.y + 1}]; !present { parameter++ } } sum += area * parameter } } } return sum } // task:https://adventofcode.com/2024/day/12#part2 func SolveComplex(input string) int { farmMap := loadMap(input) visited := Visited{} sum := 0 for y, row := range farmMap { for x, value := range row { p := Point{x, y} field := Visited{} if _, present := visited[p]; !present { visit(farmMap, field, x, y, value) area := len(field) parameter := countEdges(farmMap, field) for point := range field { // mark as visited to not visit it more than once visited[point] = true } sum += area * parameter } } } return sum } func countEdges(farmMap Map, field Visited) int { borders := map[BorderPoint]bool{} edges := 0 for y, row := range farmMap { for x := range row { if field.At(x, y) { if !field.At(x-1, y) { if !borders[BorderPoint{x, y - 1, LEFT}] { edges++ } borders[BorderPoint{x, y, LEFT}] = true } if !field.At(x, y-1) { if !borders[BorderPoint{x - 1, y, TOP}] { edges++ } borders[BorderPoint{x, y, TOP}] = true } if !field.At(x, y+1) { if !borders[BorderPoint{x - 1, y, BOTTOM}] { edges++ } borders[BorderPoint{x, y, BOTTOM}] = true } if !field.At(x+1, y) { if !borders[BorderPoint{x, y - 1, RIGHT}] { edges++ } borders[BorderPoint{x, y, RIGHT}] = true } } } } return edges } type Direction int const ( LEFT Direction = iota TOP Direction = iota RIGHT Direction = iota BOTTOM Direction = iota ) type BorderPoint struct { x, y int direction Direction } func visit(farmMap Map, field Visited, x int, y int, value rune) { if _, visited := field[Point{x, y}]; visited { return } if farmMap.At(x, y) == value { field[Point{x, y}] = true visit(farmMap, field, x-1, y, value) visit(farmMap, field, x+1, y, value) visit(farmMap, field, x, y-1, value) visit(farmMap, field, x, y+1, value) } } func loadMap(input string) Map { input = strings.ReplaceAll(input, "\r", "") topographicMap := Map{} for _, line := range strings.Split(input, "\n") { topographicMap = append(topographicMap, []rune(line)) } return topographicMap }