diff --git a/2021/day25/main.go b/2021/day25/main.go new file mode 100644 index 0000000..7a2634a --- /dev/null +++ b/2021/day25/main.go @@ -0,0 +1,123 @@ +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() +}