2022 Day 23 Complete
This commit is contained in:
201
2022/day23/main.go
Normal file
201
2022/day23/main.go
Normal file
@@ -0,0 +1,201 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
func main() {
|
||||
inp := h.StdinToStringSlice()
|
||||
part1(inp)
|
||||
part2(inp)
|
||||
}
|
||||
|
||||
func part1(inp []string) {
|
||||
field := plotElves(inp)
|
||||
for i := 0; i < 10; i++ {
|
||||
proposals := buildProposals(field, i)
|
||||
for k, v := range proposals {
|
||||
delete(field, v)
|
||||
field[k] = true
|
||||
}
|
||||
}
|
||||
fmt.Println("# Part 1")
|
||||
fmt.Println("Empty Tiles:", countEmpties(field))
|
||||
}
|
||||
func part2(inp []string) {
|
||||
field := plotElves(inp)
|
||||
var lastHash string
|
||||
for i := 0; i < 100000000; i++ {
|
||||
proposals := buildProposals(field, i)
|
||||
for k, v := range proposals {
|
||||
delete(field, v)
|
||||
field[k] = true
|
||||
}
|
||||
currHash := fieldHash(field)
|
||||
if currHash == lastHash {
|
||||
fmt.Println("# Part 2")
|
||||
fmt.Println("Stable on round", i+1)
|
||||
return
|
||||
}
|
||||
lastHash = currHash
|
||||
}
|
||||
fmt.Println("# Part 2")
|
||||
fmt.Println("No solution found.")
|
||||
}
|
||||
func fieldHash(field map[h.Coordinate]bool) string {
|
||||
var sorted []h.Coordinate
|
||||
for k := range field {
|
||||
sorted = append(sorted, k)
|
||||
}
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
if sorted[i].X == sorted[j].X {
|
||||
return sorted[i].Y > sorted[j].Y
|
||||
}
|
||||
return sorted[i].X > sorted[j].X
|
||||
})
|
||||
return fmt.Sprintf("%v", sorted)
|
||||
}
|
||||
|
||||
func countEmpties(field map[h.Coordinate]bool) int {
|
||||
maxX, minX := math.MinInt, math.MaxInt
|
||||
maxY, minY := math.MinInt, math.MaxInt
|
||||
for k := range field {
|
||||
maxX = h.Max(maxX, k.X)
|
||||
minX = h.Min(minX, k.X)
|
||||
maxY = h.Max(maxY, k.Y)
|
||||
minY = h.Min(minY, k.Y)
|
||||
}
|
||||
var ret int
|
||||
for y := minY; y <= maxY; y++ {
|
||||
for x := minX; x <= maxX; x++ {
|
||||
if _, ok := field[h.Coordinate{X: x, Y: y}]; !ok {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
func printField(field map[h.Coordinate]bool) {
|
||||
maxX, minX := math.MinInt, 0
|
||||
maxY, minY := math.MinInt, 0
|
||||
for k := range field {
|
||||
maxX = h.Max(maxX, k.X)
|
||||
minX = h.Min(minX, k.X)
|
||||
maxY = h.Max(maxY, k.Y)
|
||||
minY = h.Min(minY, k.Y)
|
||||
}
|
||||
maxX = maxX + 2
|
||||
maxY = maxY + 2
|
||||
for y := minY; y <= maxY; y++ {
|
||||
for x := minX; x <= maxX; x++ {
|
||||
if _, ok := field[h.Coordinate{X: x, Y: y}]; ok {
|
||||
fmt.Print("#")
|
||||
} else {
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
func plotElves(inp []string) map[h.Coordinate]bool {
|
||||
field := make(map[h.Coordinate]bool)
|
||||
for y := range inp {
|
||||
for x := range inp[y] {
|
||||
if inp[y][x] == '#' {
|
||||
field[h.Coordinate{X: x, Y: y}] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return field
|
||||
}
|
||||
func buildProposals(field map[h.Coordinate]bool, round int) map[h.Coordinate]h.Coordinate {
|
||||
props := make(map[h.Coordinate]h.Coordinate)
|
||||
var errProps []h.Coordinate
|
||||
for k := range field {
|
||||
var neighbors []h.Coordinate
|
||||
for _, n := range k.GetAllNeighbors() {
|
||||
if _, ok := field[n]; ok {
|
||||
neighbors = append(neighbors, n)
|
||||
}
|
||||
}
|
||||
if len(neighbors) == 0 {
|
||||
continue
|
||||
}
|
||||
var hasNorth, hasEast, hasSouth, hasWest bool
|
||||
for _, n := range neighbors {
|
||||
if n.Y < k.Y {
|
||||
hasNorth = true
|
||||
}
|
||||
if n.Y > k.Y {
|
||||
hasSouth = true
|
||||
}
|
||||
if n.X < k.X {
|
||||
hasWest = true
|
||||
}
|
||||
if n.X > k.X {
|
||||
hasEast = true
|
||||
}
|
||||
}
|
||||
addProp := func(c h.Coordinate) {
|
||||
if _, ok := props[c]; ok {
|
||||
errProps = append(errProps, c)
|
||||
} else {
|
||||
props[c] = k
|
||||
}
|
||||
}
|
||||
testNorth := func(c h.Coordinate) bool {
|
||||
if !hasNorth {
|
||||
addProp(k.North())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
testSouth := func(c h.Coordinate) bool {
|
||||
if !hasSouth {
|
||||
addProp(k.South())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
testWest := func(c h.Coordinate) bool {
|
||||
if !hasWest {
|
||||
addProp(k.West())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
testEast := func(c h.Coordinate) bool {
|
||||
if !hasEast {
|
||||
addProp(k.East())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
findProposal := func(c h.Coordinate, tests ...func(h.Coordinate) bool) {
|
||||
for i := range tests {
|
||||
if tests[i](c) == true {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
switch round % 4 {
|
||||
case 0: // North First
|
||||
findProposal(k, testNorth, testSouth, testWest, testEast)
|
||||
case 1: // South First
|
||||
findProposal(k, testSouth, testWest, testEast, testNorth)
|
||||
case 2: // West First
|
||||
findProposal(k, testWest, testEast, testNorth, testSouth)
|
||||
case 3: // East First
|
||||
findProposal(k, testEast, testNorth, testSouth, testWest)
|
||||
}
|
||||
}
|
||||
// Now remove all conflicts
|
||||
for i := range errProps {
|
||||
delete(props, errProps[i])
|
||||
}
|
||||
return props
|
||||
}
|
||||
Reference in New Issue
Block a user