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 }