My code for Advent of Code 2020 in Go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

126 lines
2.6 KiB

package main
import (
"bufio"
"fmt"
"os"
"reflect"
"strings"
)
func main() {
var scannedSeats, currentSeats [][]rune
file, _ := os.Open("input.txt")
defer file.Close()
for scanner := bufio.NewScanner(file); scanner.Scan(); {
row := []rune{}
for _, r := range scanner.Text() {
row = append(row, r)
}
scannedSeats = append(scannedSeats, row)
}
// Part 1
currentSeats = scannedSeats
rounds:
for {
newSeats := [][]rune{}
for i := range currentSeats {
row := []rune{}
for j, r := range currentSeats[i] {
newRune := r
if os := occupiedAdjacent(currentSeats, position{i, j}); r == 'L' && os == 0 {
newRune = '#'
} else if r == '#' && os >= 4 {
newRune = 'L'
}
row = append(row, newRune)
}
newSeats = append(newSeats, row)
}
if reflect.DeepEqual(currentSeats, newSeats) {
break rounds
}
currentSeats = newSeats
}
fmt.Println("Part 1:", countOccupied(currentSeats))
// Part 2
currentSeats = scannedSeats
rounds2:
for {
newSeats := [][]rune{}
for i := range currentSeats {
row := []rune{}
for j, r := range currentSeats[i] {
newRune := r
if cs := canSeeAdjacent(currentSeats, position{i, j}); r == 'L' && cs == 0 {
newRune = '#'
} else if r == '#' && cs >= 5 {
newRune = 'L'
}
row = append(row, newRune)
}
newSeats = append(newSeats, row)
}
if reflect.DeepEqual(currentSeats, newSeats) {
break rounds2
}
currentSeats = newSeats
}
fmt.Println("Part 2:", countOccupied(currentSeats))
}
type position struct {
row, pos int
}
var dirs = []position{
{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1},
}
func direction(pos, dir position) position {
return position{pos.row + dir.row, pos.pos + dir.pos}
}
func isSafe(seats [][]rune, p position) bool {
return !(p.row < 0 || p.row >= len(seats) || p.pos < 0 || p.pos >= len(seats[p.row]))
}
func occupied(seats [][]rune, p position) bool {
return isSafe(seats, p) && seats[p.row][p.pos] == '#'
}
func occupiedAdjacent(seats [][]rune, pos position) (o int) {
for _, dir := range dirs {
if occupied(seats, direction(pos, dir)) {
o++
}
}
return
}
func canSee(seats [][]rune, p, dir position) bool {
return isSafe(seats, p) && seats[p.row][p.pos] != 'L' && (seats[p.row][p.pos] == '#' || canSee(seats, direction(p, dir), dir))
}
func canSeeAdjacent(seats [][]rune, pos position) (o int) {
for _, dir := range dirs {
if canSee(seats, direction(pos, dir), dir) {
o++
}
}
return
}
func countOccupied(seats [][]rune) (o int) {
for _, ro := range seats {
o += strings.Count(string(ro), "#")
}
return
}