Day 11 (Golang)

This commit is contained in:
akp 2020-12-12 20:18:51 +00:00
parent fe3aee042f
commit 7b435c3e05
No known key found for this signature in database
GPG key ID: D3E7EAA31B39637E
6 changed files with 299 additions and 26 deletions

52
.github/README.md vendored
View file

@ -14,33 +14,33 @@ Puzzle inputs and descriptions are not included in this repository. You'll have
<!-- PARSE START -->
| Day | | Python | Go |
| --------------------------- | ------------------------------ | ------------------------------------- | --------------------------------- |
| [1](/01-reportRepair) | ![Completed][check] | [Link](/01-reportRepair/python) | [Link](/01-reportRepair/go) |
| [2](/02-passwordPhilosophy) | ![Completed][check] | [Link](/02-passwordPhilosophy/python) | [Link](/02-passwordPhilosophy/go) |
| [3](/03-tobogganTrajectory) | ![Completed][check] | [Link](/03-tobogganTrajectory/python) | [Link](/03-tobogganTrajectory/go) |
| [4](/04-passportProcessing) | ![Completed][check] | [Link](/04-passportProcessing/python) | [Link](/04-passportProcessing/go) |
| [5](/05-binaryBoarding) | ![Completed][check] | [Link](/05-binaryBoarding/python) | [Link](/05-binaryBoarding/go) |
| [6](/06-customCustoms) | ![Completed][check] | [Link](/06-customCustoms/python) | [Link](/06-customCustoms/go) |
| [7](/07-handyHaversacks) | ![Completed][check] | [Link](/07-handyHaversacks/python) | [Link](/07-handyHaversacks/go) |
| [8](/08-handheldHalting) | ![Completed][check] | [Link](/08-handheldHalting/python) | [Link](/08-handheldHalting/go) |
| [9](/09-encodingError) | ![Completed][check] | [Link](/09-encodingError/python) | [Link](/09-encodingError/go) |
| [10](/10-adapterArray) | ![Completed][check] | [Link](/10-adapterArray/python) | [Link](/10-adapterArray/go) |
| [11](/11-seatingSystem) \* | ![Partially complete][partial] | [Link](/11-seatingSystem/python) | |
| Day | | Python | Go |
| --------------------------- | ------------------- | ------------------------------------- | --------------------------------- |
| [1](/01-reportRepair) | ![Completed][check] | [Link](/01-reportRepair/python) | [Link](/01-reportRepair/go) |
| [2](/02-passwordPhilosophy) | ![Completed][check] | [Link](/02-passwordPhilosophy/python) | [Link](/02-passwordPhilosophy/go) |
| [3](/03-tobogganTrajectory) | ![Completed][check] | [Link](/03-tobogganTrajectory/python) | [Link](/03-tobogganTrajectory/go) |
| [4](/04-passportProcessing) | ![Completed][check] | [Link](/04-passportProcessing/python) | [Link](/04-passportProcessing/go) |
| [5](/05-binaryBoarding) | ![Completed][check] | [Link](/05-binaryBoarding/python) | [Link](/05-binaryBoarding/go) |
| [6](/06-customCustoms) | ![Completed][check] | [Link](/06-customCustoms/python) | [Link](/06-customCustoms/go) |
| [7](/07-handyHaversacks) | ![Completed][check] | [Link](/07-handyHaversacks/python) | [Link](/07-handyHaversacks/go) |
| [8](/08-handheldHalting) | ![Completed][check] | [Link](/08-handheldHalting/python) | [Link](/08-handheldHalting/go) |
| [9](/09-encodingError) | ![Completed][check] | [Link](/09-encodingError/python) | [Link](/09-encodingError/go) |
| [10](/10-adapterArray) | ![Completed][check] | [Link](/10-adapterArray/python) | [Link](/10-adapterArray/go) |
| [11](/11-seatingSystem) \* | ![Completed][check] | [Link](/11-seatingSystem/python) | [Link](/11-seatingSystem/python) |
| [12](/12-rainRisk) | ![Partially complete][partial] | [Link](/12-rainRisk/python) | |
| 13 | | | |
| 14 | | | |
| 15 | | | |
| 16 | | | |
| 17 | | | |
| 18 | | | |
| 19 | | | |
| 20 | | | |
| 21 | | | |
| 22 | | | |
| 23 | | | |
| 24 | | | |
| 25 | | | |
| 13 | | | |
| 14 | | | |
| 15 | | | |
| 16 | | | |
| 17 | | | |
| 18 | | | |
| 19 | | | |
| 20 | | | |
| 21 | | | |
| 22 | | | |
| 23 | | | |
| 24 | | | |
| 25 | | | |
<!-- PARSE END -->

View file

@ -24,6 +24,18 @@ Test cases
1.1 pass
2.1 pass
Answers
Part 1: 2283
Part 2: 2054
go run .\go\
AoC 2020: day 11 - Seating System
Go go1.15.2
Test cases
1.1 pass
2.1 pass
Answers
Part 1: 2283
Part 2: 2054

View file

@ -0,0 +1,85 @@
package challenge
import (
"reflect"
"strings"
)
const (
openSeat = 'L'
filledSeat = '#'
noSeat = '.'
)
var (
lookupPositions = [][2]int{
{0, 1},
{1, 1},
{1, 0},
{1, -1},
{0, -1},
{-1, -1},
{-1, 0},
{-1, 1},
}
)
func parse(instr string) (o [][]rune) {
for _, x := range strings.Split(strings.TrimSpace(instr), "\n") {
o = append(o, []rune(x))
}
return
}
func iterate(currentHall [][]rune, neighbourCounter func([][]rune, [2]int, [2]int) int, getNewState func(int, rune) rune) [][]rune {
// Copy hall
nextHall := make([][]rune, len(currentHall))
for i, lc := range currentHall {
nextHall[i] = make([]rune, len(lc))
copy(nextHall[i], lc)
}
hallSize := [2]int{len(nextHall[0]), len(nextHall)}
// iterate each chair space
for col := 0; col < hallSize[0]; col += 1 {
for row := 0; row < hallSize[1]; row += 1 {
currentPos := currentHall[row][col]
// It it's the floor, there's nothing we can do with this spot
if currentPos == noSeat {
continue
}
// Count number of adjacent seats
numNeighbours := neighbourCounter(currentHall, [2]int{row, col}, hallSize)
// Execute rules on copied list based on that count
nextHall[row][col] = getNewState(numNeighbours, nextHall[row][col])
}
}
return nextHall
}
func run(currentState [][]rune, neighbourCounter func([][]rune, [2]int, [2]int) int, getNewState func(int, rune) rune) int {
lastState := make([][]rune, 0)
for !reflect.DeepEqual(currentState, lastState) {
lastState = currentState
currentState = iterate(currentState, neighbourCounter, getNewState)
}
totalOccupied := 0
for _, a := range currentState {
for _, b := range a {
if b == filledSeat {
totalOccupied += 1
}
}
}
return totalOccupied
}

View file

@ -0,0 +1,33 @@
package challenge
func getNewStateOne(numNeighbours int, oldState rune) rune {
if numNeighbours == 0 {
return filledSeat
} else if numNeighbours >= 4 && oldState == filledSeat {
return openSeat
}
return oldState
}
func countNeighboursOne(hall [][]rune, currentPos [2]int, hallSize [2]int) (numNeighbours int) {
row := currentPos[0]
col := currentPos[1]
for _, position := range lookupPositions {
test_x_pos := position[0] + col
test_y_pos := position[1] + row
if 0 <= test_x_pos && test_x_pos < hallSize[0] && 0 <= test_y_pos && test_y_pos < hallSize[1] {
if hall[test_y_pos][test_x_pos] == filledSeat {
numNeighbours += 1
}
}
}
return
}
func PartOne(instr string) int {
return run(parse(instr), countNeighboursOne, getNewStateOne)
}

View file

@ -0,0 +1,43 @@
package challenge
func getNewStateTwo(numNeighbours int, oldState rune) rune {
if numNeighbours == 0 {
return filledSeat
} else if numNeighbours >= 5 && oldState == filledSeat {
return openSeat
}
return oldState
}
func countNeighboursTwo(hall [][]rune, currentPos [2]int, hallSize [2]int) (numNeighbours int) {
row := currentPos[0]
col := currentPos[1]
for _, position := range lookupPositions {
test_x_pos := position[0] + col
test_y_pos := position[1] + row
for 0 <= test_x_pos && test_x_pos < hallSize[0] && 0 <= test_y_pos && test_y_pos < hallSize[1] {
testLocation := hall[test_y_pos][test_x_pos]
if testLocation == filledSeat {
numNeighbours += 1
}
if testLocation == openSeat || testLocation == filledSeat {
break
}
test_x_pos += position[0]
test_y_pos += position[1]
}
}
return
}
func PartTwo(instr string) int {
return run(parse(instr), countNeighboursTwo, getNewStateTwo)
}

100
11-seatingSystem/go/main.go Normal file
View file

@ -0,0 +1,100 @@
package main
import (
"adventOfCode/11-seatingSystem/go/challenge"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"runtime"
"strconv"
"github.com/fatih/color"
)
func main() {
var infoStruct info
{
inb, err := ioutil.ReadFile("info.json")
if err != nil {
fmt.Println("Error: could not open info.json")
os.Exit(-1)
}
err = json.Unmarshal(inb, &infoStruct)
if err != nil {
fmt.Println("Error: could not parse info.json")
os.Exit(-1)
}
}
var (
year = infoStruct.Year
day = infoStruct.Day
title = infoStruct.Title
)
fmt.Fprintf(color.Output, "%s: day %s - %s\n", color.YellowString("AoC "+year), color.BlueString(day), title)
fmt.Fprintf(color.Output, "Go %s\n\n", color.BlueString(runtime.Version()))
var challengeInput string
{
inb, err := ioutil.ReadFile("input.txt")
if err != nil {
fmt.Println("Error: could not open input.txt")
os.Exit(-1)
}
challengeInput = string(inb)
}
runTests(infoStruct)
fmt.Println("Answers")
fmt.Fprintf(color.Output, "Part %s: %s\n", color.BlueString("1"), color.BlueString(strconv.Itoa(challenge.PartOne(challengeInput))))
fmt.Fprintf(color.Output, "Part %s: %s\n", color.BlueString("2"), color.BlueString(strconv.Itoa(challenge.PartTwo(challengeInput))))
}
type tc struct {
Input string `json:"input"`
Expected int `json:"expected"`
}
type info struct {
Year string `json:"year"`
Day string `json:"day"`
Title string `json:"title"`
TestCases struct {
One []tc `json:"one"`
Two []tc `json:"two"`
} `json:"testCases"`
}
func runTests(infoStruct info) {
if len(infoStruct.TestCases.One) == 0 && len(infoStruct.TestCases.Two) == 0 {
fmt.Println("Info: no test cases specified. Skipping tests")
fmt.Println()
return
}
fmt.Println("Test cases")
rt := func(tcs []tc, f func(string) int, n string) {
for i, tc := range tcs {
fmt.Fprintf(color.Output, "%s ", color.BlueString(n+"."+strconv.Itoa(i+1)))
result := f(tc.Input)
if result == tc.Expected {
fmt.Fprintf(color.Output, "%s", color.GreenString("pass"))
} else {
fmt.Fprintf(color.Output, "%s (got %s, expected %s)", color.RedString("fail"), color.BlueString(strconv.Itoa(result)), color.BlueString(strconv.Itoa(tc.Expected)))
}
fmt.Println()
}
}
rt(infoStruct.TestCases.One, challenge.PartOne, "1")
rt(infoStruct.TestCases.Two, challenge.PartTwo, "2")
fmt.Println()
}