AoC2020/day11/day11.go

143 lines
3.1 KiB
Go
Raw Normal View History

2020-12-11 18:46:19 +01:00
package main
import (
"AoC2020/helper"
"fmt"
"os"
)
func main() {
args := os.Args[1:]
input, err := helper.GetInput(args[0])
if err != nil {
fmt.Println(err)
}
fields := setFields(input)
printFields(fields)
fmt.Println(countOccupiedSeat(runMachine(fields, getOcuupiedNeighbours, 4)))
fmt.Println(countOccupiedSeat(runMachine(fields, getOccupiedVisibleSeats, 5)))
}
func runMachine(field [][]rune, neighbourFunction func(int, int, [][]rune) int, maxOccupied int) [][]rune {
changed := true
for changed {
newField := run(field, neighbourFunction, maxOccupied)
changed = !fieldsEqual(newField, field)
field = newField
}
return field
}
func run(fields [][]rune, neighbourFunction func(int, int, [][]rune) int, maxOccupied int) [][]rune {
var newField = make([][]rune, len(fields))
for i, _ := range newField {
newField[i] = make([]rune, len(fields[0]))
copy(newField[i], fields[i])
}
for i := 0; i < len(fields[0]); i++ {
for j := 0; j < len(fields); j++ {
if fields[j][i] == 'L' && neighbourFunction(i, j, fields) == 0 {
newField[j][i] = '#'
}
if fields[j][i] == '#' && neighbourFunction(i, j, fields) >= maxOccupied {
newField[j][i] = 'L'
}
}
}
return newField
}
func fieldsEqual(field1 [][]rune, field2 [][]rune) bool {
for i := 0; i < len(field1[0]); i++ {
for j := 0; j < len(field1); j++ {
if field1[j][i] != field2[j][i] {
return false
}
}
}
return true
}
func getOcuupiedNeighbours(x int, y int, field [][]rune) int {
neighbours := [][]int{{x - 1, y - 1}, {x, y - 1}, {x + 1, y - 1}, {x + 1, y}, {x + 1, y + 1}, {x, y + 1}, {x - 1, y + 1}, {x - 1, y}}
count := 0
for _, val := range neighbours {
if isOccupied(val[0], val[1], field) {
count++
}
}
return count
}
func getOccupiedVisibleSeats(x int, y int, field [][]rune) int {
directions := [][]int{{-1, -1}, {0,-1}, {1,-1}, {+1, 0}, {1,1}, {0,1}, {-1,1}, {-1, 0}}
count := 0
for _, val := range directions {
if getVisibleSeat(x, y, val, field) == '#' {
count++
}
}
return count
}
func getVisibleSeat(x int, y int, direction []int, field [][]rune) rune {
px := x + direction[0]
py := y + direction[1]
for py < len(field) && py >= 0 && px < len(field[0]) && px >= 0 {
if field[py][px] != '.' {
return field[py][px]
}
px += direction[0]
py += direction[1]
}
return '.'
}
func isOccupied(x int, y int, field [][]rune) bool {
if y > len(field)-1 || y < 0 {
return false
}
if x > len(field[0])-1 || x < 0 {
return false
}
if field[y][x] == 35 {
return true
}
return false
}
func printFields(fields [][]rune) {
for _, val := range fields {
fmt.Println(string(val))
}
fmt.Println()
}
func setFields(input []string) [][]rune {
var field = make([][]rune, len(input))
for i, val := range input {
field[i] = stringToRuneArr(val)
}
return field
}
func stringToRuneArr(input string) []rune {
var arr = make([]rune, len(input))
for i, val := range input {
arr[i] = val
}
return arr
}
func countOccupiedSeat(field [][]rune) int {
count := 0
for i := 0; i < len(field[0]); i++ {
for j := 0; j < len(field); j++ {
if field[j][i] == '#' {
count++
}
}
}
return count
}