2020-12-12 02:33:00 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2020-12-12 02:57:10 +00:00
|
|
|
"time"
|
2020-12-12 02:33:00 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2020-12-12 02:57:10 +00:00
|
|
|
start := time.Now()
|
2020-12-12 02:33:00 +00:00
|
|
|
partOne()
|
2020-12-12 02:57:10 +00:00
|
|
|
duration := time.Since(start)
|
2020-12-12 02:33:00 +00:00
|
|
|
partTwo()
|
2020-12-12 02:57:10 +00:00
|
|
|
duration2 := time.Since(start)
|
|
|
|
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
2020-12-12 02:33:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type cell struct {
|
|
|
|
taken int // 1: someone there; 0: empty
|
|
|
|
seat bool // t: seat available; f: open floor
|
|
|
|
}
|
|
|
|
|
|
|
|
type waitingRoom struct {
|
|
|
|
seats [][]cell
|
|
|
|
maxCol int
|
|
|
|
maxRow int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *waitingRoom) parseRow(s string) {
|
|
|
|
row := []cell{}
|
|
|
|
|
|
|
|
for _, r := range s {
|
|
|
|
switch {
|
|
|
|
case r == 'L':
|
|
|
|
row = append(row, cell{taken: 0, seat: true})
|
|
|
|
case r == '.':
|
|
|
|
row = append(row, cell{taken: 0, seat: false})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w.seats = append(w.seats, row)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *waitingRoom) countNeighborsPartOne(row, col int) int {
|
|
|
|
c := 0
|
|
|
|
if row-1 > -1 {
|
|
|
|
c = c + w.seats[row-1][col].taken // north
|
|
|
|
if col-1 > -1 {
|
|
|
|
c = c + w.seats[row-1][col-1].taken // northwest
|
|
|
|
}
|
|
|
|
if col+1 < w.maxCol {
|
|
|
|
c = c + w.seats[row-1][col+1].taken // northheast
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if row+1 < w.maxRow {
|
|
|
|
c = c + w.seats[row+1][col].taken // south
|
|
|
|
if col+1 < w.maxCol {
|
|
|
|
c = c + w.seats[row+1][col+1].taken // southeast
|
|
|
|
}
|
|
|
|
if col-1 > -1 {
|
|
|
|
c = c + w.seats[row+1][col-1].taken // southwest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if col-1 > -1 {
|
|
|
|
c = c + w.seats[row][col-1].taken // west
|
|
|
|
}
|
|
|
|
if col+1 < w.maxCol {
|
|
|
|
c = c + w.seats[row][col+1].taken // east
|
|
|
|
}
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *waitingRoom) makeNextStepPartOne() *waitingRoom {
|
|
|
|
newRoom := &waitingRoom{
|
|
|
|
seats: make([][]cell, w.maxRow),
|
|
|
|
maxCol: w.maxCol,
|
|
|
|
maxRow: w.maxRow,
|
|
|
|
}
|
|
|
|
|
|
|
|
for r := range w.seats {
|
|
|
|
newRoom.seats[r] = make([]cell, newRoom.maxCol)
|
|
|
|
for c := range w.seats[r] {
|
|
|
|
if w.seats[r][c].seat && w.seats[r][c].taken == 0 && w.countNeighborsPartOne(r, c) == 0 {
|
|
|
|
newRoom.seats[r][c].seat = w.seats[r][c].seat
|
|
|
|
newRoom.seats[r][c].taken = 1
|
|
|
|
} else if w.seats[r][c].seat && w.seats[r][c].taken == 1 && w.countNeighborsPartOne(r, c) >= 4 {
|
|
|
|
newRoom.seats[r][c].seat = w.seats[r][c].seat
|
|
|
|
newRoom.seats[r][c].taken = 0
|
|
|
|
} else {
|
|
|
|
newRoom.seats[r][c].seat = w.seats[r][c].seat
|
|
|
|
newRoom.seats[r][c].taken = w.seats[r][c].taken
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newRoom
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *waitingRoom) countNeighborsPartTwo(row, col int) int {
|
|
|
|
c := 0
|
|
|
|
trow := row
|
|
|
|
tcol := col
|
|
|
|
|
|
|
|
// south
|
|
|
|
for trow < w.maxRow-1 {
|
|
|
|
trow = trow + 1
|
|
|
|
if w.seats[trow][col].seat {
|
|
|
|
c = c + w.seats[trow][col].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trow = row
|
|
|
|
|
|
|
|
// north
|
|
|
|
for trow > 0 {
|
|
|
|
trow = trow - 1
|
|
|
|
if w.seats[trow][col].seat {
|
|
|
|
c = c + w.seats[trow][col].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trow = row
|
|
|
|
|
|
|
|
// west
|
|
|
|
for tcol > 0 {
|
|
|
|
tcol = tcol - 1
|
|
|
|
if w.seats[row][tcol].seat {
|
|
|
|
c = c + w.seats[row][tcol].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tcol = col
|
|
|
|
|
|
|
|
// east
|
|
|
|
for tcol < w.maxCol-1 {
|
|
|
|
tcol = tcol + 1
|
|
|
|
if w.seats[row][tcol].seat {
|
|
|
|
c = c + w.seats[row][tcol].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tcol = col
|
|
|
|
|
|
|
|
// southeast
|
|
|
|
for trow < w.maxRow-1 && tcol < w.maxCol-1 {
|
|
|
|
trow = trow + 1
|
|
|
|
tcol = tcol + 1
|
|
|
|
if w.seats[trow][tcol].seat {
|
|
|
|
c = c + w.seats[trow][tcol].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trow = row
|
|
|
|
tcol = col
|
|
|
|
|
|
|
|
// southwest
|
|
|
|
for trow < w.maxRow-1 && tcol > 0 {
|
|
|
|
trow = trow + 1
|
|
|
|
tcol = tcol - 1
|
|
|
|
if w.seats[trow][tcol].seat {
|
|
|
|
c = c + w.seats[trow][tcol].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trow = row
|
|
|
|
tcol = col
|
|
|
|
|
|
|
|
// northeast
|
|
|
|
for trow > 0 && tcol < w.maxCol-1 {
|
|
|
|
trow = trow - 1
|
|
|
|
tcol = tcol + 1
|
|
|
|
if w.seats[trow][tcol].seat {
|
|
|
|
c = c + w.seats[trow][tcol].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trow = row
|
|
|
|
tcol = col
|
|
|
|
|
|
|
|
// northwest
|
|
|
|
for trow > 0 && tcol > 0 {
|
|
|
|
trow = trow - 1
|
|
|
|
tcol = tcol - 1
|
|
|
|
if w.seats[trow][tcol].seat {
|
|
|
|
c = c + w.seats[trow][tcol].taken
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *waitingRoom) makeNextStepPartTwo() *waitingRoom {
|
|
|
|
newRoom := &waitingRoom{
|
|
|
|
seats: make([][]cell, w.maxRow),
|
|
|
|
maxCol: w.maxCol,
|
|
|
|
maxRow: w.maxRow,
|
|
|
|
}
|
|
|
|
|
|
|
|
for r := range w.seats {
|
|
|
|
newRoom.seats[r] = make([]cell, newRoom.maxCol)
|
|
|
|
for c := range w.seats[r] {
|
|
|
|
if w.seats[r][c].seat && w.seats[r][c].taken == 0 && w.countNeighborsPartTwo(r, c) == 0 {
|
|
|
|
newRoom.seats[r][c].seat = w.seats[r][c].seat
|
|
|
|
newRoom.seats[r][c].taken = 1
|
|
|
|
} else if w.seats[r][c].seat && w.seats[r][c].taken == 1 && w.countNeighborsPartTwo(r, c) >= 5 {
|
|
|
|
newRoom.seats[r][c].seat = w.seats[r][c].seat
|
|
|
|
newRoom.seats[r][c].taken = 0
|
|
|
|
} else {
|
|
|
|
newRoom.seats[r][c].seat = w.seats[r][c].seat
|
|
|
|
newRoom.seats[r][c].taken = w.seats[r][c].taken
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newRoom
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *waitingRoom) countFilledSeats() int {
|
|
|
|
count := 0
|
|
|
|
for r := range w.seats {
|
|
|
|
for c := range w.seats[r] {
|
|
|
|
count = count + w.seats[r][c].taken
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *waitingRoom) print() {
|
|
|
|
for r := range w.seats {
|
|
|
|
s := ""
|
|
|
|
for c := range w.seats[r] {
|
|
|
|
if !w.seats[r][c].seat {
|
|
|
|
s = s + "."
|
|
|
|
} else if w.seats[r][c].taken == 0 {
|
|
|
|
s = s + "L"
|
|
|
|
} else if w.seats[r][c].taken == 1 {
|
|
|
|
s = s + "#"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Println(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkStasis(old, new *waitingRoom) bool {
|
|
|
|
for r := range old.seats {
|
|
|
|
for c := range old.seats[r] {
|
|
|
|
if old.seats[r][c].seat && old.seats[r][c].taken != new.seats[r][c].taken {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func partOne() {
|
|
|
|
f, _ := os.Open("input")
|
|
|
|
reader := bufio.NewReader(f)
|
|
|
|
scanner := bufio.NewScanner(reader)
|
|
|
|
|
|
|
|
oldRoom := &waitingRoom{}
|
|
|
|
|
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
oldRoom.parseRow(line)
|
|
|
|
}
|
|
|
|
|
|
|
|
oldRoom.maxCol = len(oldRoom.seats[0])
|
|
|
|
oldRoom.maxRow = len(oldRoom.seats)
|
|
|
|
|
|
|
|
for {
|
|
|
|
newRoom := oldRoom.makeNextStepPartOne()
|
|
|
|
if checkStasis(newRoom, oldRoom) {
|
|
|
|
fmt.Println(newRoom.countFilledSeats())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
oldRoom = newRoom
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func partTwo() {
|
|
|
|
f, _ := os.Open("input")
|
|
|
|
reader := bufio.NewReader(f)
|
|
|
|
scanner := bufio.NewScanner(reader)
|
|
|
|
oldRoom := &waitingRoom{}
|
|
|
|
|
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
oldRoom.parseRow(line)
|
|
|
|
}
|
|
|
|
|
|
|
|
oldRoom.maxCol = len(oldRoom.seats[0])
|
|
|
|
oldRoom.maxRow = len(oldRoom.seats)
|
|
|
|
|
|
|
|
for {
|
|
|
|
newRoom := oldRoom.makeNextStepPartTwo()
|
|
|
|
if checkStasis(newRoom, oldRoom) {
|
|
|
|
fmt.Println(newRoom.countFilledSeats())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
oldRoom = newRoom
|
|
|
|
}
|
|
|
|
}
|