2020 Day 11 Complete
This commit is contained in:
263
2020/day11/main.go
Normal file
263
2020/day11/main.go
Normal file
@@ -0,0 +1,263 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
const (
|
||||
EMPTY = 'L'
|
||||
FULL = '#'
|
||||
FLOOR = '.'
|
||||
|
||||
N = iota
|
||||
NE
|
||||
E
|
||||
SE
|
||||
S
|
||||
SW
|
||||
W
|
||||
NW
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("# Day 11")
|
||||
inp := h.StdinToStringSlice()
|
||||
pt := h.GetArgNumber(1)
|
||||
if pt == "1" {
|
||||
part1(inp)
|
||||
} else {
|
||||
part2(inp)
|
||||
}
|
||||
}
|
||||
|
||||
func part1(inp []string) {
|
||||
fmt.Println("## Part 1")
|
||||
w := BuildWaitingRoom(inp)
|
||||
var last string
|
||||
for w.String() != last {
|
||||
last = w.String()
|
||||
w.Tick()
|
||||
}
|
||||
fmt.Println(w)
|
||||
fmt.Printf("At stabilization there are %d occupied seats\n", w.OccupiedSeats())
|
||||
}
|
||||
|
||||
func part2(inp []string) {
|
||||
fmt.Println("## Part 2")
|
||||
w := BuildWaitingRoom(inp)
|
||||
var last string
|
||||
for w.String() != last {
|
||||
last = w.String()
|
||||
w.VisibleTick()
|
||||
}
|
||||
fmt.Println(w)
|
||||
fmt.Printf("At stabilization there are %d occupied seats\n", w.OccupiedSeats())
|
||||
}
|
||||
|
||||
type WaitingRoom struct {
|
||||
Layout map[h.Coordinate]byte
|
||||
NorthMost int
|
||||
SouthMost int
|
||||
EastMost int
|
||||
WestMost int
|
||||
}
|
||||
|
||||
func BuildWaitingRoom(inp []string) *WaitingRoom {
|
||||
ret := WaitingRoom{
|
||||
Layout: make(map[h.Coordinate]byte),
|
||||
NorthMost: h.MAX_INT,
|
||||
SouthMost: h.MIN_INT,
|
||||
EastMost: h.MIN_INT,
|
||||
WestMost: h.MAX_INT,
|
||||
}
|
||||
|
||||
for y := range inp {
|
||||
for x := range inp[y] {
|
||||
ret.Layout[h.Coordinate{X: x, Y: y}] = inp[y][x]
|
||||
if x < ret.WestMost {
|
||||
ret.WestMost = x
|
||||
}
|
||||
if x > ret.EastMost {
|
||||
ret.EastMost = x
|
||||
}
|
||||
}
|
||||
if y < ret.NorthMost {
|
||||
ret.NorthMost = y
|
||||
}
|
||||
if y > ret.SouthMost {
|
||||
ret.SouthMost = y
|
||||
}
|
||||
}
|
||||
return &ret
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) OccupiedSeats() int {
|
||||
var ret int
|
||||
for k := range w.Layout {
|
||||
if !w.CoordEmpty(k) {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) CoordEmpty(c h.Coordinate) bool {
|
||||
return w.Layout[c] != FULL
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) ShouldFill(c h.Coordinate) bool {
|
||||
if w.Layout[c] == FULL || w.Layout[c] == FLOOR {
|
||||
return false
|
||||
}
|
||||
return w.CoordEmpty(c.North()) && w.CoordEmpty(c.NE()) && w.CoordEmpty(c.East()) && w.CoordEmpty(c.SE()) && w.CoordEmpty(c.South()) && w.CoordEmpty(c.SW()) && w.CoordEmpty(c.West()) && w.CoordEmpty(c.NW())
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) ShouldEmpty(c h.Coordinate) bool {
|
||||
if w.Layout[c] == EMPTY || w.Layout[c] == FLOOR {
|
||||
return false
|
||||
}
|
||||
var fullSeats int
|
||||
for _, v := range []h.Coordinate{c.North(), c.NE(), c.East(), c.SE(), c.South(), c.SW(), c.West(), c.NW()} {
|
||||
if !w.CoordEmpty(v) {
|
||||
fullSeats++
|
||||
if fullSeats >= 4 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) Tick() {
|
||||
wrk := make(map[h.Coordinate]byte)
|
||||
for k := range w.Layout {
|
||||
wrk[k] = w.Layout[k]
|
||||
switch w.Layout[k] {
|
||||
case EMPTY:
|
||||
if w.ShouldFill(k) {
|
||||
wrk[k] = FULL
|
||||
}
|
||||
|
||||
case FULL:
|
||||
if w.ShouldEmpty(k) {
|
||||
wrk[k] = EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
for k := range wrk {
|
||||
w.Layout[k] = wrk[k]
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) IsFloor(c h.Coordinate) bool {
|
||||
return w.Layout[c] == FLOOR
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) GetCoordInDir(c h.Coordinate, dir int) h.Coordinate {
|
||||
switch dir {
|
||||
case N:
|
||||
return c.North()
|
||||
case NE:
|
||||
return c.NE()
|
||||
case E:
|
||||
return c.East()
|
||||
case SE:
|
||||
return c.SE()
|
||||
case S:
|
||||
return c.South()
|
||||
case SW:
|
||||
return c.SW()
|
||||
case W:
|
||||
return c.West()
|
||||
case NW:
|
||||
return c.NW()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) DirectionEmpty(c h.Coordinate, dir int) bool {
|
||||
c = w.GetCoordInDir(c, dir)
|
||||
for w.IsFloor(c) {
|
||||
c = w.GetCoordInDir(c, dir)
|
||||
}
|
||||
return w.CoordEmpty(c)
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) VisibleShouldFill(c h.Coordinate) bool {
|
||||
if w.Layout[c] == FULL || w.Layout[c] == FLOOR {
|
||||
return false
|
||||
}
|
||||
return w.DirectionEmpty(c, N) && w.DirectionEmpty(c, NE) && w.DirectionEmpty(c, E) && w.DirectionEmpty(c, SE) && w.DirectionEmpty(c, S) && w.DirectionEmpty(c, SW) && w.DirectionEmpty(c, W) && w.DirectionEmpty(c, NW)
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) VisibleShouldEmpty(c h.Coordinate) bool {
|
||||
if w.Layout[c] == EMPTY || w.Layout[c] == FLOOR {
|
||||
return false
|
||||
}
|
||||
var fullSeats int
|
||||
for _, v := range []int{N, NE, E, SE, S, SW, W, NW} {
|
||||
if !w.DirectionEmpty(c, v) {
|
||||
fullSeats++
|
||||
if fullSeats >= 5 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *WaitingRoom) VisibleTick() {
|
||||
wrk := make(map[h.Coordinate]byte)
|
||||
for k := range w.Layout {
|
||||
wrk[k] = w.Layout[k]
|
||||
switch w.Layout[k] {
|
||||
case EMPTY:
|
||||
if w.VisibleShouldFill(k) {
|
||||
wrk[k] = FULL
|
||||
}
|
||||
|
||||
case FULL:
|
||||
if w.VisibleShouldEmpty(k) {
|
||||
wrk[k] = EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
for k := range wrk {
|
||||
w.Layout[k] = wrk[k]
|
||||
}
|
||||
}
|
||||
|
||||
func (w WaitingRoom) String() string {
|
||||
var ret string
|
||||
for y := w.NorthMost; y <= w.SouthMost; y++ {
|
||||
for x := w.WestMost; x <= w.EastMost; x++ {
|
||||
ret = ret + string(w.Layout[h.Coordinate{X: x, Y: y}])
|
||||
}
|
||||
ret = ret + "\n"
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func DirToStr(dir int) string {
|
||||
switch dir {
|
||||
case N:
|
||||
return "N"
|
||||
case NE:
|
||||
return "NE"
|
||||
case E:
|
||||
return "E"
|
||||
case SE:
|
||||
return "SE"
|
||||
case S:
|
||||
return "S"
|
||||
case SW:
|
||||
return "SW"
|
||||
case W:
|
||||
return "W"
|
||||
case NW:
|
||||
return "NW"
|
||||
}
|
||||
return "-"
|
||||
}
|
||||
Reference in New Issue
Block a user