From f8ae82eefb8e03433d6e2bbc32f86d785cd7f7c2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Durham" Date: Sat, 26 Dec 2020 10:59:05 -0800 Subject: [PATCH] Solutions for Day Eleven --- day11/input.txt | 98 +++++++++++++++ day11/main.go | 299 +++++++++++++++++++++++++++++++++++++++++++++ day11/main_test.go | 116 ++++++++++++++++++ 3 files changed, 513 insertions(+) create mode 100644 day11/input.txt create mode 100644 day11/main.go create mode 100644 day11/main_test.go diff --git a/day11/input.txt b/day11/input.txt new file mode 100644 index 0000000..c05b38d --- /dev/null +++ b/day11/input.txt @@ -0,0 +1,98 @@ +LLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLL.LL.L.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL +LLLLLLLLLL.LLLLLL.L.LLLLLLL.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLL..LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLL..L.LLLLLLLLLLLLLLL.LL.LLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLL.LLLLL +LLLLLLLLLL.LL..LLLL.LLLLLLL.LLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLL..LLLLLLLL +LL.L..L.L..L.LL..L.....LLLL..L.L.LL..L...LLLLLL...L.....L.....LL.L...LLLLL..L.LL..L..L.LL.. +LLLLLLLLLL.LLLLLLLL.LLLLLLLL.LLLL.LLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL +LLLLLLLLLL..LLLLLLL.LLLLLLL.LLLLL.L.LLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL +L.LLLLLLLLLL.LLL..LLLLLLLLL.LLLLL.LLLLL..LLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLL.LLLL..LLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLL..LLLLLLLLLLL.L.LL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLL.L.LLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLL.LLLLL +.......LL.L....L......L....L...L.LL..L..L...L.LL.L.LL..L..L.L.LLL.....L...LL..L..L..L.LL..L +LLL.LLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.L.LL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLL.LLL.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL..LLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL +LLLLLLL.LL.LLLL.LLL..LLLLLL.LLLLL.LLLLLLLLLL.LLLL.LLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LL.LLLLL.LLLLLLLLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLL.LLLL.LLL +LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLL.LLLLLLLL +.LL..LL.L.L....L...L.........L......LL.L..........L....L...L.L..L.L.L.LLL...LLL.L.....L.L.. +LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLL.L.LLL.LLL.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLL..LLLLL.LLLLL.LLLLLLLL +LL.LLLLLLL.LL.LLLLL.LLLLLLL.LLLLLLLLLLLLLLLL..LLL.LLL.LLLLL.LLLLLLLL..LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LL..LL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLL.L.LLLLLLLL.LL.LLLL.LLLL.LLLLLLLLL.LLL.LLLLL.L.LLLL.LLLLL.LLLLLLLL +LL.LLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LL.LLLLLLL.LLLL..LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLL +......L.L......L.L.LLL.L.......L.LL..L..........LLL.LL..L.L............LL.LL.L.LL.......L.. +LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLL.LLLLLLLLLLLLLL +LLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLL.L.LLL.LLLLL.LLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLL..LLLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLL.L.LLL.LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL +LLLLL.LLLL.LLLL.LLLLLLLLLLL.LLLLL.LLLLL.LLLL..LL..LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLL.LL +LL.LLLLLLLLLLLLLLLL.LLL.LLL.LLLLL.L.LLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLL.L.LLLLLLLLLLLLLLLLLLL +LLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLL..LLLLLLLLL..L.LLLLLLLL +........LL.........L........L.L.LL..L.......L....L.....L.......L...L.L..L..........L......L +LL.LLLLLLL.LLLLLLLL.LLLLLL.LLL.LLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLL.LLL.LLLLLL.LLLLL.LLLLLL.L +LLLLLLLLLL.LLLLLLLLLLLLLLLL..LLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLL.LLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLL.LL.L.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLL.L.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL +...L....L.LL..L.......L..L...L.LL..LL.L....LL......L...L..L.....LL.LL....L.L..L.....L..L.L. +LLLLLLLLLLLLLLLLLLLLLLLL.LL.LLLLL.LLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLL..LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLLLL.LLL.LLLLLLLLL.LLL.LL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLL.LLLLLLLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLL.LLL.LLLL +L.L..LL..L..LL....L...LL...L.LL...L.L.......LL.......L.LLL....L.....L..L.L..L...L.L.L.L.... +LLLLLLLLLL.LLLLLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LL.LLLLLLLLL.LLLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLL.L.LLLLL.LL +LLLLLLLLLLLLLL.LLLL..LLLLLL.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLLL..LLLLLLLL.LLLLLL.LLL.L.LLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLL.LL.L.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL +LLLLLLLLLL.LLLLL.LL.LLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +...LLL.LL.LL.LLL......L.L.L..L..L....L........L........L...LL....L.LLL....LLL..L.......LLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLL.LL.LLLLLLLLL.L.LLL.LLL.LLL.LLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLL.LLLLL.LLLL.LLLL.LLL.LLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLL.L.LLLLLLLL..LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLL.L +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLL.LLLL.LLLLLLLLL..LLLLLLL..LLLLLL.LLLLL.LLLLLL.L +LLLLLLLLLL.LLLLLLLLLL.LLLLL.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL. +LLLLLLLLLL.LL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLL.LLLLLL.LLL.LLLLL.LLLLLLLLLLLLLLLLLLLLL +LL.LL.LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.L..LL.LLL.LLLLLLLLLLLLLL +L.L........L...LL.L..L....LLLL...LL.L......L.L....L...L.L..LL......LL......L....L..L.LL..L. +LLLLLLLLLLLLLLLLLLL..L.LLLL.L.LLLLLLLLL.LLLLLLLLL.LLLLLLLLL..LLLLLL.L.L..LLL.LLLLL.LLLLLLLL +LLLLLLLL.L.LLLL.LLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLLLL.LL.L.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLL.L +LLLLLLLLL..LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.L.LLLL.LLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLL.LL.LLLLL.LLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL +LLLLLLLLLLLLLLLL..L.LLLLLLL.LLLLL.LLL.L.LLLL..LLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLL.LLLLLLLL +...LL......L..LL.....L.LLLLLL..LL.LLL...L.L...LLL.LL........L......LLL..L.L.L.L..L..LLL.L.. +LL.LLL.LLL.LLLLLLLL.L.LLLLL.LLLLL.L.LLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLL.L.LL.LLLL..LLLLL.LL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLL.LLLLL..LLLLLLLL.LLLLL.L.LLLLL.LLLLL.LLL.LLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLL.LL.LLLL. +LLLLLLLLLLLLLLLLLLL.LLL.LLL.LLLL.LLLLLL.LL.L.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +.......LLL....LLL.LL.L.L.L....LLL..L..L...L.LL.LLLL...LL............LL..LL....L..L...L.LLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLL.LLL +LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLLL.LLLLLL..L.LLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLL.LLLL.LLLLLLLL.LLLLLLL..LLLL.LLLLLLLLLL.LLLL.LLLLLLLLL.LLL.LLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLL..LLLL.LLL +LLLLLLLLLL.LLLLLLL..LLLLLLL.LLLLL..LLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLL..LLLLL.LLLL.LLLL.LLLLLLLLL.L.LLLLLLL.LLLLLLLLLLLL.L.LLLLLL +LLLLLLLLLL.LLLLL.L..LLLLLLL.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +.....L...L..L.L..L.LLLLLLLLL....L.LL...LL...L.LL..L..L.L..L.L.....L...L.LL...L.L.......L..L +LLLLLLLLLLLLLLLLLLL.LLLLL.L.LLLLL.LLLLL.LLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLL.LLLL.LL.LLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLL.LLL.LLLLL.LLL.L.LLLL.LLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLL.LLLLLLLL +LLLLLLLL.L.LLLLLLLL.LLLLLLL.L.LLL.LLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLL.LLLLLLLL +LLLLLLLLLL.LLL.LLLL.LLLLLLL.LL.LL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLL. +LLLLLLLLLL.LLLLLLL..LLLLLLL.LLLLL.LLLLL.LLLLLLLLL.LLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLL.LLLLL.LLL..LLLL.LLLLLLL.L.LLLLLLLLL..LLLLLLLLLLLLLLLLLLL. diff --git a/day11/main.go b/day11/main.go new file mode 100644 index 0000000..8d79a75 --- /dev/null +++ b/day11/main.go @@ -0,0 +1,299 @@ +package main + +import ( + "errors" + "fmt" + "io/ioutil" + "strings" +) + +func main() { + input, err := ioutil.ReadFile("input.txt") + if err != nil { + panic(err.Error()) + } + + wr := NewWaitingRoom(string(input)) + + // Part One + complete, _ := SimulateSeating(wr) + fmt.Printf("Answer 1: %v occupied seats\n", complete.OccupiedSeatCount()) + + // Part Two + complete, _ = SimulateAlternateSeating(wr) + fmt.Printf("Answer 2: %v occupied seats, using alternate strategy\n", complete.OccupiedSeatCount()) +} + +// WaitingRoom represents a collection of seats in a waiting room +type WaitingRoom struct { + seats [][]rune +} + +// NewWaitingRoom creates a WaitingRoom from a string input +func NewWaitingRoom(input string) WaitingRoom { + var wr = WaitingRoom{} + for _, row := range strings.Split(input, "\n") { + if len(row) == 0 { + continue + } + + var seats []rune + for _, seat := range row { + seats = append(seats, seat) + } + wr.seats = append(wr.seats, seats) + } + + return wr +} + +// Print a WaitingRoom to the console +func (wr WaitingRoom) Print() { + for _, row := range wr.seats { + for _, seat := range row { + fmt.Printf("%c", seat) + } + fmt.Printf("\n") + } +} + +// OccupiedSeatCount returns the number of occupied seats in the waiting room. +func (wr WaitingRoom) OccupiedSeatCount() int { + count := 0 + + for _, row := range wr.seats { + for _, seat := range row { + if seat == '#' { + count++ + } + } + } + + return count +} + +// Clone creates an exact duplicate of a WaitingRoom +func (wr WaitingRoom) Clone() WaitingRoom { + var cp = WaitingRoom{} + + for _, row := range wr.seats { + var newRow []rune + + for _, seat := range row { + newRow = append(newRow, seat) + } + + cp.seats = append(cp.seats, newRow) + } + + return cp +} + +// AdjacentSeatCount returns the number of occupied seats +// in the eight seat positions next to a given x,y +// coordinate in the WaitingRoom: +// Left, Right, Up, Down, and Diagonal. +func (wr WaitingRoom) AdjacentSeatCount(x, y int) int { + count := 0 + + for i := x - 1; i <= x+1; i++ { + for j := y - 1; j <= y+1; j++ { + // Ignore the target seat + if i == x && j == y { + continue + } + + // Check WaitingRoom bounds + if i < 0 || i >= len(wr.seats) { + continue + } + if j < 0 || j >= len(wr.seats[i]) { + continue + } + + if wr.seats[i][j] == '#' { + count++ + } + } + } + + return count +} + +// AlternateAdjacentSeatCount returns the number of occupied +// seats, considering the first chair that is visible in +// each of the eight directions around the target seat. +func (wr WaitingRoom) AlternateAdjacentSeatCount(x, y int) int { + count := 0 + + for _, dir := range []string{"N", "NW", "W", "SW", "S", "SE", "E", "NE"} { + seat, err := wr.FindDirectionalSeat(dir, x, y) + if err != nil { + continue + } + if seat == '#' { + count++ + } + } + + return count +} + +var translations = map[string][]int{ + "N": {0, -1}, + "NW": {1, -1}, + "W": {1, 0}, + "SW": {1, 1}, + "S": {0, 1}, + "SE": {-1, 1}, + "E": {-1, 0}, + "NE": {-1, -1}, +} + +func translate(dir string, x, y int) (int, int) { + offset, exists := translations[dir] + if !exists { + panic("Invalid direction lookup") + } + + return x + offset[0], y + offset[1] +} + +// FindDirectionalSeat returns the first seat found in a given direction +// from a given set of coordinates. +func (wr WaitingRoom) FindDirectionalSeat(direction string, x, y int) (rune, error) { + + var seat rune + + for { + xPrime, yPrime := translate(direction, x, y) + + // Check X bounds + if xPrime < 0 || xPrime >= len(wr.seats[0]) { + return seat, errors.New("out of bounds") + } + + // Check Y bounds + if yPrime < 0 || yPrime >= len(wr.seats) { + return seat, errors.New("out of bounds") + } + + // If this new spot contains a seat we + // will return it. If not, carry on. + if wr.seats[yPrime][xPrime] == 'L' || wr.seats[yPrime][xPrime] == '#' { + return wr.seats[yPrime][xPrime], nil + } + + x = xPrime + y = yPrime + } +} + +// IsEqual tells us if two WaitingRooms have an identical configuration +func IsEqual(wrA, wrB WaitingRoom) bool { + for i := 0; i < len(wrA.seats); i++ { + for j := 0; j < len(wrA.seats[i]); j++ { + if wrA.seats[i][j] != wrB.seats[i][j] { + return false + } + } + } + + return true +} + +// DoTick simulates a single round of seating in the wating room. +func DoTick(wrA WaitingRoom) WaitingRoom { + var wrB = wrA.Clone() + + for i := 0; i < len(wrA.seats); i++ { + for j := 0; j < len(wrA.seats[i]); j++ { + + // Start by copying the current seat value to the new waiting room + wrB.seats[i][j] = wrA.seats[i][j] + + // Rule: + // If a seat is empty (L) and there are no occupied seats adjacent to it, + // the seat becomes occupied. + if wrA.seats[i][j] == 'L' && wrA.AdjacentSeatCount(i, j) == 0 { + wrB.seats[i][j] = '#' + } + + // Rule: + // If a seat is occupied (#) and four or more seats adjacent to it are + // also occupied, the seat becomes empty. + if wrA.seats[i][j] == '#' && wrA.AdjacentSeatCount(i, j) >= 4 { + wrB.seats[i][j] = 'L' + } + } + } + + return wrB +} + +// DoAlternateTick simulates a single round of seating in the wating room, +// using alternate rules. +func DoAlternateTick(wrA WaitingRoom) WaitingRoom { + var wrB = wrA.Clone() + + for i := 0; i < len(wrA.seats); i++ { + for j := 0; j < len(wrA.seats[i]); j++ { + + // Start by copying the current seat value to the new waiting room + // wrB.seats[i][j] = wrA.seats[i][j] + + // Rule: + // If a seat is empty (L) and there are no occupied seats adjacent to it, + // the seat becomes occupied. + if wrA.seats[i][j] == 'L' && wrA.AlternateAdjacentSeatCount(j, i) == 0 { + wrB.seats[i][j] = '#' + } + + // Rule: + // If a seat is occupied (#) and five or more seats adjacent to it are + // also occupied, the seat becomes empty. + if wrA.seats[i][j] == '#' && wrA.AlternateAdjacentSeatCount(j, i) >= 5 { + wrB.seats[i][j] = 'L' + } + } + } + + return wrB +} + +// SimulateSeating runs a waiting room through a full seating process +func SimulateSeating(wr WaitingRoom) (WaitingRoom, int) { + rounds := 0 + var previous WaitingRoom = wr + + for { + + next := DoTick(previous) + + if IsEqual(next, previous) { + return previous, rounds + } + + previous = next + rounds++ + } +} + +// SimulateAlternateSeating runs a waiting room through a full seating process +func SimulateAlternateSeating(wr WaitingRoom) (WaitingRoom, int) { + rounds := 0 + var previous WaitingRoom = wr + + for { + + next := DoAlternateTick(previous) + + if IsEqual(next, previous) { + return previous, rounds + } + + previous = next + rounds++ + } + +} diff --git a/day11/main_test.go b/day11/main_test.go new file mode 100644 index 0000000..79b01f0 --- /dev/null +++ b/day11/main_test.go @@ -0,0 +1,116 @@ +package main + +import ( + "testing" +) + +func TestNewWaitingRoom(t *testing.T) { + wr := NewWaitingRoom(getTestInput()) + + if len(wr.seats[0]) != 10 { + t.Errorf("Expected a row to have 10 seats, got %v", len(wr.seats[0])) + } + + if len(wr.seats) != 10 { + t.Errorf("Expected to have 10 rows, got %v", len(wr.seats)) + } +} + +func TestSeatingSimulation(t *testing.T) { + wr := NewWaitingRoom(getTestInput()) + + complete, _ := SimulateSeating(wr) + occupiedSeatCount := complete.OccupiedSeatCount() + + if occupiedSeatCount != 37 { + t.Errorf("Expected %v seats to be occupied, got %v", 37, occupiedSeatCount) + } +} + +func TestAlternateeatingSimulation(t *testing.T) { + wr := NewWaitingRoom(getTestInput()) + + complete, _ := SimulateAlternateSeating(wr) + occupiedSeatCount := complete.OccupiedSeatCount() + + if occupiedSeatCount != 26 { + t.Errorf("Expected %v seats to be occupied, got %v", 26, occupiedSeatCount) + } +} + +func TestAlternateTicks(t *testing.T) { + wrA := NewWaitingRoom(getAlternateFirstTickInput()) + wrB := NewWaitingRoom(getAlternateSecondTickInput()) + + attempt := DoAlternateTick(wrA) + + if !IsEqual(wrB, attempt) { + t.Error("Expected a different result from an alternate tick") + } +} + +func TestFindDirectionalSeats(t *testing.T) { + wr := NewWaitingRoom(` +.......#. +...#..... +.#....... +......... +..#L....# +....#.... +......... +#........ +...#.....`, + ) + + count := wr.AlternateAdjacentSeatCount(3, 4) + + if count != 8 { + t.Errorf("Expected to find %v seats, found %v", 8, count) + } + +} + +func getTestInput() string { + return ` +L.LL.LL.LL +LLLLLLL.LL +L.L.L..L.. +LLLL.LL.LL +L.LL.LL.LL +L.LLLLL.LL +..L.L..... +LLLLLLLLLL +L.LLLLLL.L +L.LLLLL.LL +` +} + +func getAlternateFirstTickInput() string { + return ` +#.##.##.## +#######.## +#.#.#..#.. +####.##.## +#.##.##.## +#.#####.## +..#.#..... +########## +#.######.# +#.#####.## +` +} + +func getAlternateSecondTickInput() string { + return ` +#.LL.LL.L# +#LLLLLL.LL +L.L.L..L.. +LLLL.LL.LL +L.LL.LL.LL +L.LLLLL.LL +..L.L..... +LLLLLLLLL# +#.LLLLLL.L +#.LLLLL.L# +` +}