2024 day 12 Complete!
This commit is contained in:
162
2024/day12/main.go
Normal file
162
2024/day12/main.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
func main() {
|
||||
inp := h.StdinToCoordMap()
|
||||
part1(inp)
|
||||
fmt.Println("")
|
||||
part2(inp)
|
||||
}
|
||||
|
||||
func part1(inp h.CoordByteMap) {
|
||||
fmt.Println("# Part 1")
|
||||
var total int
|
||||
trackedPlots := make(map[h.Coordinate]bool)
|
||||
for y := inp.TLY; y <= inp.BRY; y++ {
|
||||
for x := inp.TLX; x <= inp.BRX; x++ {
|
||||
c := h.Coordinate{X: x, Y: y}
|
||||
if trackedPlots[c] {
|
||||
continue
|
||||
}
|
||||
plant := inp.Get(c)
|
||||
region := findRegion(inp, c, make(map[h.Coordinate]bool))
|
||||
area := len(region)
|
||||
var perimeter int
|
||||
for k := range region {
|
||||
trackedPlots[k] = true
|
||||
for _, chk := range []h.Coordinate{k.North(), k.East(), k.South(), k.West()} {
|
||||
if inp.Get(chk) != plant {
|
||||
perimeter++
|
||||
}
|
||||
}
|
||||
}
|
||||
total = total + (area * perimeter)
|
||||
}
|
||||
}
|
||||
fmt.Println("Total Price:", total)
|
||||
}
|
||||
|
||||
func part2(inp h.CoordByteMap) {
|
||||
fmt.Println("# Part 2")
|
||||
var total int
|
||||
trackedPlots := make(map[h.Coordinate]bool)
|
||||
for y := inp.TLY; y <= inp.BRY; y++ {
|
||||
for x := inp.TLX; x <= inp.BRX; x++ {
|
||||
c := h.Coordinate{X: x, Y: y}
|
||||
if trackedPlots[c] {
|
||||
continue
|
||||
}
|
||||
region := findRegion(inp, c, make(map[h.Coordinate]bool))
|
||||
area := len(region)
|
||||
for k := range region {
|
||||
trackedPlots[k] = true
|
||||
}
|
||||
sides := findSides(region)
|
||||
total = total + (area * sides)
|
||||
}
|
||||
}
|
||||
fmt.Println("Total Price:", total)
|
||||
}
|
||||
|
||||
func findRegion(inp h.CoordByteMap, start h.Coordinate, checked map[h.Coordinate]bool) map[h.Coordinate]bool {
|
||||
ret := make(map[h.Coordinate]bool)
|
||||
bt := inp.Get(start)
|
||||
ret[start] = true
|
||||
for _, chk := range []h.Coordinate{start.North(), start.East(), start.South(), start.West()} {
|
||||
if checked[chk] {
|
||||
continue
|
||||
}
|
||||
if inp.Get(chk) == bt {
|
||||
checked[chk] = true
|
||||
ret[chk] = true
|
||||
for k := range findRegion(inp, chk, checked) {
|
||||
ret[k] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var (
|
||||
N = h.Coordinate{X: 0, Y: -1}
|
||||
NE = h.Coordinate{X: 1, Y: -1}
|
||||
E = h.Coordinate{X: 1, Y: 0}
|
||||
SE = h.Coordinate{X: 1, Y: 1}
|
||||
S = h.Coordinate{X: 0, Y: 1}
|
||||
SW = h.Coordinate{X: -1, Y: 1}
|
||||
W = h.Coordinate{X: -1, Y: 0}
|
||||
NW = h.Coordinate{X: -1, Y: -1}
|
||||
)
|
||||
|
||||
func findSides(region map[h.Coordinate]bool) int {
|
||||
var sides int
|
||||
for chk := range region {
|
||||
sides = sides + checkForExteriorCorner(chk, region)
|
||||
sides = sides + checkForInteriorCorner(chk, region)
|
||||
}
|
||||
return sides
|
||||
}
|
||||
|
||||
// checkForExteriorCorner returns how many exterior corners 'chk' is a part of
|
||||
func checkForExteriorCorner(chk h.Coordinate, region map[h.Coordinate]bool) int {
|
||||
var ret int
|
||||
// Check orthoganal neighbor pairs (N/E, E/S, S/W, W/N) for an exterior corner
|
||||
if checkDiff(chk, N, region) {
|
||||
if checkDiff(chk, E, region) {
|
||||
ret++
|
||||
}
|
||||
if checkDiff(chk, W, region) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
if checkDiff(chk, S, region) {
|
||||
if checkDiff(chk, E, region) {
|
||||
ret++
|
||||
}
|
||||
if checkDiff(chk, W, region) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// checkForInteriorCorner returns how many interior corners 'chk' is a part of
|
||||
func checkForInteriorCorner(chk h.Coordinate, region map[h.Coordinate]bool) int {
|
||||
var ret int
|
||||
// Check for interior corner (N/E != NE, E/S != SE, S/W != SW, W/N != NW)
|
||||
if checkDiff(chk, NE, region) {
|
||||
if checkSame(chk, N, region) && checkSame(chk, E, region) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
if checkDiff(chk, SE, region) {
|
||||
if checkSame(chk, S, region) && checkSame(chk, E, region) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
if checkDiff(chk, SW, region) {
|
||||
if checkSame(chk, S, region) && checkSame(chk, W, region) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
if checkDiff(chk, NW, region) {
|
||||
if checkSame(chk, N, region) && checkSame(chk, W, region) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func checkDiff(chk, dir h.Coordinate, region map[h.Coordinate]bool) bool {
|
||||
return !checkSame(chk, dir, region)
|
||||
}
|
||||
|
||||
func checkSame(chk, dir h.Coordinate, region map[h.Coordinate]bool) bool {
|
||||
_, ok := region[chk.Add(dir)]
|
||||
return ok
|
||||
}
|
||||
Reference in New Issue
Block a user