Day 23
This commit is contained in:
228
day23/common/seeds.go
Normal file
228
day23/common/seeds.go
Normal file
@@ -0,0 +1,228 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
|
||||
type Tile byte
|
||||
|
||||
const (
|
||||
Empty Tile = iota
|
||||
Elf
|
||||
)
|
||||
|
||||
|
||||
type Direction byte
|
||||
|
||||
const (
|
||||
East Direction = iota
|
||||
West
|
||||
North
|
||||
South
|
||||
)
|
||||
|
||||
func (direction Direction) GetNext() Direction {
|
||||
switch direction {
|
||||
case North:
|
||||
return South
|
||||
case South:
|
||||
return West
|
||||
case West:
|
||||
return East
|
||||
default:
|
||||
return North
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type Coordinates struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
|
||||
type Map struct {
|
||||
tiles map[Coordinates]Tile
|
||||
currentRound Direction
|
||||
boundedCoordinates []Coordinates
|
||||
}
|
||||
|
||||
func (tileMap *Map) Round() bool {
|
||||
nextCoordinates := map[Coordinates][]Coordinates{}
|
||||
isFinalRound := true
|
||||
|
||||
for coordinates, tile := range tileMap.tiles {
|
||||
if tile == Elf {
|
||||
neighbor := false
|
||||
outer:
|
||||
for i := -1; i <= 1; i++ {
|
||||
for j := -1; j <= 1; j++ {
|
||||
if i != 0 || j != 0 {
|
||||
if tile, ok := tileMap.tiles[Coordinates{coordinates.x+i, coordinates.y+j}]; ok && tile == Elf {
|
||||
neighbor = true
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !neighbor {
|
||||
continue
|
||||
}
|
||||
|
||||
var nextC Coordinates
|
||||
round := tileMap.currentRound
|
||||
move := false
|
||||
|
||||
loop:
|
||||
for i := 0; i < 4; i++ {
|
||||
switch round {
|
||||
case North:
|
||||
tile1, ok1 := tileMap.tiles[Coordinates{coordinates.x-1, coordinates.y-1}]
|
||||
tile2, ok2 := tileMap.tiles[Coordinates{coordinates.x, coordinates.y-1}]
|
||||
tile3, ok3 := tileMap.tiles[Coordinates{coordinates.x+1, coordinates.y-1}]
|
||||
nextC = Coordinates{coordinates.x, coordinates.y-1}
|
||||
if (!ok1 || tile1 == Empty) && (!ok2 || tile2 == Empty) && (!ok3 || tile3 == Empty) {
|
||||
move = true
|
||||
break loop
|
||||
}
|
||||
case South:
|
||||
tile1, ok1 := tileMap.tiles[Coordinates{coordinates.x-1, coordinates.y+1}]
|
||||
tile2, ok2 := tileMap.tiles[Coordinates{coordinates.x, coordinates.y+1}]
|
||||
tile3, ok3 := tileMap.tiles[Coordinates{coordinates.x+1, coordinates.y+1}]
|
||||
nextC = Coordinates{coordinates.x, coordinates.y+1}
|
||||
if (!ok1 || tile1 == Empty) && (!ok2 || tile2 == Empty) && (!ok3 || tile3 == Empty) {
|
||||
move = true
|
||||
break loop
|
||||
}
|
||||
case West:
|
||||
tile1, ok1 := tileMap.tiles[Coordinates{coordinates.x-1, coordinates.y-1}]
|
||||
tile2, ok2 := tileMap.tiles[Coordinates{coordinates.x-1, coordinates.y}]
|
||||
tile3, ok3 := tileMap.tiles[Coordinates{coordinates.x-1, coordinates.y+1}]
|
||||
nextC = Coordinates{coordinates.x-1, coordinates.y}
|
||||
if (!ok1 || tile1 == Empty) && (!ok2 || tile2 == Empty) && (!ok3 || tile3 == Empty) {
|
||||
move = true
|
||||
break loop
|
||||
}
|
||||
case East:
|
||||
tile1, ok1 := tileMap.tiles[Coordinates{coordinates.x+1, coordinates.y-1}]
|
||||
tile2, ok2 := tileMap.tiles[Coordinates{coordinates.x+1, coordinates.y}]
|
||||
tile3, ok3 := tileMap.tiles[Coordinates{coordinates.x+1, coordinates.y+1}]
|
||||
nextC = Coordinates{coordinates.x+1, coordinates.y}
|
||||
if (!ok1 || tile1 == Empty) && (!ok2 || tile2 == Empty) && (!ok3 || tile3 == Empty) {
|
||||
move = true
|
||||
break loop
|
||||
}
|
||||
}
|
||||
round = round.GetNext()
|
||||
}
|
||||
|
||||
if move {
|
||||
if _, okc := nextCoordinates[nextC]; !okc {
|
||||
nextCoordinates[nextC] = []Coordinates{}
|
||||
}
|
||||
nextCoordinates[nextC] = append(nextCoordinates[nextC], coordinates)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for nextC := range nextCoordinates {
|
||||
if len(nextCoordinates[nextC]) == 1 {
|
||||
tileMap.tiles[nextCoordinates[nextC][0]] = Empty
|
||||
tileMap.tiles[nextC] = Elf
|
||||
isFinalRound = false
|
||||
}
|
||||
}
|
||||
|
||||
tileMap.currentRound = tileMap.currentRound.GetNext()
|
||||
|
||||
return isFinalRound
|
||||
}
|
||||
|
||||
func (tileMap *Map) GetEmpty() int {
|
||||
nEmpty := 0
|
||||
for x := tileMap.boundedCoordinates[0].x; x <= tileMap.boundedCoordinates[1].x; x++ {
|
||||
for y := tileMap.boundedCoordinates[0].y; y <= tileMap.boundedCoordinates[1].y; y++ {
|
||||
if tileMap.tiles[Coordinates{x, y}] == Empty {
|
||||
nEmpty++
|
||||
}
|
||||
}
|
||||
}
|
||||
return nEmpty
|
||||
}
|
||||
|
||||
func (tileMap *Map) Bound() {
|
||||
minX := math.MaxInt32
|
||||
minY := math.MaxInt32
|
||||
maxX := math.MinInt32
|
||||
maxY := math.MinInt32
|
||||
|
||||
for coordinates, tile := range tileMap.tiles {
|
||||
if tile == Elf {
|
||||
if coordinates.x < minX {
|
||||
minX = coordinates.x
|
||||
}
|
||||
if coordinates.x > maxX {
|
||||
maxX = coordinates.x
|
||||
}
|
||||
if coordinates.y < minY {
|
||||
minY = coordinates.y
|
||||
}
|
||||
if coordinates.y > maxY {
|
||||
maxY = coordinates.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tileMap.boundedCoordinates = []Coordinates{{minX, minY}, {maxX, maxY}}
|
||||
|
||||
for x := minX; x <= maxX; x++ {
|
||||
for y := minY; y <= maxY; y++ {
|
||||
c := Coordinates{x, y}
|
||||
if _, ok := tileMap.tiles[c]; !ok {
|
||||
tileMap.tiles[c] = Empty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tileMap *Map) Print() {
|
||||
for y := tileMap.boundedCoordinates[0].y; y <= tileMap.boundedCoordinates[1].y; y++ {
|
||||
for x := tileMap.boundedCoordinates[0].x; x <= tileMap.boundedCoordinates[1].x; x++ {
|
||||
switch tileMap.tiles[Coordinates{x, y}] {
|
||||
case Empty:
|
||||
fmt.Print(".")
|
||||
case Elf:
|
||||
fmt.Print("#")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func Parse(scanner bufio.Scanner) Map {
|
||||
tileMap := Map{}
|
||||
tileMap.tiles = make(map[Coordinates]Tile)
|
||||
|
||||
i := 0
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
for j := range line {
|
||||
switch line[j] {
|
||||
case '.':
|
||||
tileMap.tiles[Coordinates{j, i}] = Empty
|
||||
case '#':
|
||||
tileMap.tiles[Coordinates{j, i}] = Elf
|
||||
}
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
tileMap.currentRound = North
|
||||
|
||||
return tileMap
|
||||
}
|
||||
19
day23/ex1/main.go
Normal file
19
day23/ex1/main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"aoc2022/day23/common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tileMap := common.Parse(*bufio.NewScanner(os.Stdin))
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
tileMap.Round()
|
||||
}
|
||||
|
||||
tileMap.Bound()
|
||||
fmt.Println(tileMap.GetEmpty())
|
||||
}
|
||||
19
day23/ex2/main.go
Normal file
19
day23/ex2/main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"aoc2022/day23/common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tileMap := common.Parse(*bufio.NewScanner(os.Stdin))
|
||||
|
||||
i := 1
|
||||
for !tileMap.Round() {
|
||||
i++
|
||||
}
|
||||
|
||||
fmt.Println(i)
|
||||
}
|
||||
Reference in New Issue
Block a user