123 lines
2 KiB
Go
123 lines
2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/jdkaplan/advent-of-code/aoc"
|
|
)
|
|
|
|
func main() {
|
|
lines := aoc.Input().ReadLines("day25.txt")
|
|
fmt.Println(part1(lines))
|
|
}
|
|
|
|
func part1(lines []string) int {
|
|
f := NewFloor(lines)
|
|
moved := true
|
|
i := 0
|
|
for moved {
|
|
f, moved = f.Tick()
|
|
i++
|
|
}
|
|
return i
|
|
}
|
|
|
|
type RC struct{ r, c int }
|
|
|
|
type Floor struct {
|
|
east, south map[RC]bool
|
|
rows, cols int
|
|
}
|
|
|
|
func NewFloor(lines []string) Floor {
|
|
f := Floor{
|
|
east: make(map[RC]bool),
|
|
south: make(map[RC]bool),
|
|
rows: len(lines),
|
|
cols: len(lines[0]),
|
|
}
|
|
for r, row := range lines {
|
|
for c, char := range row {
|
|
rc := RC{r, c}
|
|
switch char {
|
|
case 'v':
|
|
f.south[rc] = true
|
|
case '>':
|
|
f.east[rc] = true
|
|
}
|
|
}
|
|
}
|
|
return f
|
|
}
|
|
|
|
func (f Floor) Occupied(rc RC) bool {
|
|
return f.east[rc] || f.south[rc]
|
|
}
|
|
|
|
func (f Floor) EastOf(rc RC) RC {
|
|
c := (rc.c + 1) % f.cols
|
|
return RC{rc.r, c}
|
|
}
|
|
|
|
func (f Floor) SouthOf(rc RC) RC {
|
|
r := (rc.r + 1) % f.rows
|
|
return RC{r, rc.c}
|
|
}
|
|
|
|
func (f Floor) Tick() (Floor, bool) {
|
|
next, eastward := f.TickEast()
|
|
next, southward := next.TickSouth()
|
|
return next, eastward || southward
|
|
}
|
|
|
|
func (f Floor) TickEast() (Floor, bool) {
|
|
next := f
|
|
next.east = make(map[RC]bool)
|
|
moved := false
|
|
for rc := range f.east {
|
|
t := f.EastOf(rc)
|
|
if f.Occupied(t) {
|
|
next.east[rc] = true
|
|
} else {
|
|
next.east[t] = true
|
|
moved = true
|
|
}
|
|
}
|
|
return next, moved
|
|
}
|
|
|
|
func (f Floor) TickSouth() (Floor, bool) {
|
|
next := f
|
|
next.south = make(map[RC]bool)
|
|
moved := false
|
|
for rc := range f.south {
|
|
t := f.SouthOf(rc)
|
|
if f.Occupied(t) {
|
|
next.south[rc] = true
|
|
} else {
|
|
next.south[t] = true
|
|
moved = true
|
|
}
|
|
}
|
|
return next, moved
|
|
}
|
|
|
|
func (f Floor) String() string {
|
|
var sb strings.Builder
|
|
for r := 0; r < f.rows; r++ {
|
|
for c := 0; c < f.cols; c++ {
|
|
rc := RC{r, c}
|
|
switch {
|
|
case f.east[rc]:
|
|
sb.WriteByte('>')
|
|
case f.south[rc]:
|
|
sb.WriteByte('v')
|
|
default:
|
|
sb.WriteByte('.')
|
|
}
|
|
}
|
|
sb.WriteString("\n")
|
|
}
|
|
return sb.String()
|
|
}
|