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() }