package main import ( "strings" "tangled.org/evan.jarrett.net/aoc2025/internal/puzzle" ) type PaperRoll struct { row int column int left int right int up int upLeft int upRight int down int downLeft int downRight int } func (p *PaperRoll) CanAccess() bool { return p.left+p.right+p.up+p.down+p.upLeft+p.upRight+p.downLeft+p.downRight < 4 } type DayFour struct { grid []string rolls []PaperRoll } const rollchar byte = '@' func getCell(grid []string, i, j int) int { if i < 0 || i >= len(grid) || j < 0 || j >= len(grid[i]) { return 0 } if grid[i][j] == rollchar { return 1 } return 0 } func (d *DayFour) ParseInputArr(input []string) { for i, line := range d.grid { line = strings.TrimSpace(line) if line == "" { continue } for j, ch := range line { if ch == rune(rollchar) { p := PaperRoll{ row: i, column: j, left: getCell(d.grid, i, j-1), right: getCell(d.grid, i, j+1), up: getCell(d.grid, i-1, j), upLeft: getCell(d.grid, i-1, j-1), upRight: getCell(d.grid, i-1, j+1), down: getCell(d.grid, i+1, j), downLeft: getCell(d.grid, i+1, j-1), downRight: getCell(d.grid, i+1, j+1), } d.rolls = append(d.rolls, p) } } } } func (d *DayFour) ParseInput(input string) error { d.grid = strings.Split(strings.TrimSpace(input), "\n") d.ParseInputArr(d.grid) return nil } func (d *DayFour) Part1() (int, error) { count := 0 for _, roll := range d.rolls { if roll.CanAccess() { count++ } } return count, nil } func (d *DayFour) Part2() (int, error) { count := 0 changed := true for changed { changed = false d.rolls = nil d.ParseInputArr(d.grid) for _, roll := range d.rolls { if roll.CanAccess() { d.grid[roll.row] = d.grid[roll.row][:roll.column] + "." + d.grid[roll.row][roll.column+1:] count++ changed = true } } } return count, nil } func main() { puzzle.Run(4, &DayFour{}) }