101 lines
1.6 KiB
Go
101 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
f := os.Stdin
|
|
if len(os.Args) > 1 && os.Args[1] != "-" {
|
|
var err error
|
|
f, err = os.Open(os.Args[1])
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer f.Close()
|
|
}
|
|
|
|
grid, err := readDiagram(f)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
var total int
|
|
for i := 1; ; i++ {
|
|
removed := removePapers(grid)
|
|
total += removed
|
|
fmt.Printf("%2d: removed %d\n", i, removed)
|
|
if removed == 0 {
|
|
break
|
|
}
|
|
}
|
|
fmt.Printf("total %d\n", total)
|
|
}
|
|
|
|
func removePapers(grid [][]bool) (removed int) {
|
|
type position struct {
|
|
x, y int
|
|
}
|
|
var toRemove []position
|
|
for y, row := range grid {
|
|
for x, b := range row {
|
|
if !b {
|
|
continue
|
|
}
|
|
if countAdjacent(grid, x, y) < 4 {
|
|
toRemove = append(toRemove, position{
|
|
x: x,
|
|
y: y,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
for _, pos := range toRemove {
|
|
grid[pos.y][pos.x] = false
|
|
}
|
|
return len(toRemove)
|
|
}
|
|
|
|
func countAdjacent(grid [][]bool, x, y int) int {
|
|
var count int
|
|
xFrom := max(x-1, 0)
|
|
yFrom := max(y-1, 0)
|
|
yTo := min(y+1, len(grid)-1)
|
|
|
|
for yi := yFrom; yi <= yTo; yi++ {
|
|
xTo := min(x+1, len(grid[yi])-1)
|
|
|
|
for xi := xFrom; xi <= xTo; xi++ {
|
|
if xi == x && yi == y {
|
|
continue
|
|
}
|
|
if grid[yi][xi] {
|
|
count++
|
|
}
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func readDiagram(r io.Reader) ([][]bool, error) {
|
|
var grid [][]bool
|
|
sc := bufio.NewScanner(r)
|
|
for sc.Scan() {
|
|
var row []bool
|
|
for _, b := range sc.Bytes() {
|
|
switch b {
|
|
case '@', '.':
|
|
row = append(row, b == '@')
|
|
default:
|
|
return nil, fmt.Errorf("read diagram: unexpected character: %q", sc.Bytes())
|
|
}
|
|
}
|
|
grid = append(grid, row)
|
|
}
|
|
return grid, sc.Err()
|
|
}
|