+82
cmd/five/main.go
+82
cmd/five/main.go
···
1
+
package main
2
+
3
+
import (
4
+
"fmt"
5
+
"slices"
6
+
"strconv"
7
+
"strings"
8
+
9
+
"tangled.org/evan.jarrett.net/aoc2025/internal/puzzle"
10
+
)
11
+
12
+
type IDRange struct {
13
+
first int
14
+
last int
15
+
}
16
+
17
+
type DayFive struct {
18
+
freshIds []IDRange
19
+
tocheck []int
20
+
}
21
+
22
+
func (d *DayFive) ParseInput(input string) error {
23
+
for line := range strings.SplitSeq(strings.TrimSpace(input), "\n") {
24
+
line = strings.TrimSpace(line)
25
+
if strings.Contains(line, "-") {
26
+
splits := strings.Split(line, "-")
27
+
first, _ := strconv.Atoi(splits[0])
28
+
last, _ := strconv.Atoi(splits[1])
29
+
d.freshIds = append(d.freshIds, IDRange{first, last})
30
+
} else if line == "" {
31
+
continue
32
+
} else {
33
+
ingredient, _ := strconv.Atoi(line)
34
+
d.tocheck = append(d.tocheck, ingredient)
35
+
}
36
+
}
37
+
return nil
38
+
}
39
+
40
+
func (d *DayFive) Part1() (int, error) {
41
+
count := 0
42
+
for _, i := range d.tocheck {
43
+
for _, idrange := range d.freshIds {
44
+
if i >= idrange.first && i <= idrange.last {
45
+
count++
46
+
break
47
+
}
48
+
}
49
+
}
50
+
return count, nil
51
+
}
52
+
53
+
func (d *DayFive) Part2() (int, error) {
54
+
count := 0
55
+
56
+
slices.SortFunc(d.freshIds, func(a, b IDRange) int {
57
+
return a.first - b.first
58
+
})
59
+
var combinedFreshIds []IDRange
60
+
last := d.freshIds[0]
61
+
for _, current := range d.freshIds {
62
+
if current.first <= last.last {
63
+
last.last = max(last.last, current.last)
64
+
} else {
65
+
combinedFreshIds = append(combinedFreshIds, last)
66
+
last = current
67
+
}
68
+
}
69
+
// combine one last time
70
+
combinedFreshIds = append(combinedFreshIds, last)
71
+
72
+
for _, idrange := range combinedFreshIds {
73
+
numInRange := idrange.last - idrange.first + 1
74
+
fmt.Println(numInRange)
75
+
count += numInRange
76
+
}
77
+
return count, nil
78
+
}
79
+
80
+
func main() {
81
+
puzzle.Run(5, &DayFive{})
82
+
}
+52
cmd/five/main_test.go
+52
cmd/five/main_test.go
···
1
+
package main
2
+
3
+
import (
4
+
"testing"
5
+
)
6
+
7
+
const testInput = `3-5
8
+
10-14
9
+
16-20
10
+
12-18
11
+
12
+
1
13
+
5
14
+
8
15
+
11
16
+
17
17
+
32
18
+
`
19
+
20
+
func TestPart1(t *testing.T) {
21
+
d := &DayFive{}
22
+
if err := d.ParseInput(testInput); err != nil {
23
+
t.Fatalf("ParseInput failed: %v", err)
24
+
}
25
+
26
+
got, err := d.Part1()
27
+
if err != nil {
28
+
t.Fatalf("Part1 failed: %v", err)
29
+
}
30
+
31
+
want := 3
32
+
if got != want {
33
+
t.Errorf("Part1() = %d, want %d", got, want)
34
+
}
35
+
}
36
+
37
+
func TestPart2(t *testing.T) {
38
+
d := &DayFive{}
39
+
if err := d.ParseInput(testInput); err != nil {
40
+
t.Fatalf("ParseInput failed: %v", err)
41
+
}
42
+
43
+
got, err := d.Part2()
44
+
if err != nil {
45
+
t.Fatalf("Part2 failed: %v", err)
46
+
}
47
+
48
+
want := 14
49
+
if got != want {
50
+
t.Errorf("Part2() = %d, want %d", got, want)
51
+
}
52
+
}
+107
cmd/four/main.go
+107
cmd/four/main.go
···
1
+
package main
2
+
3
+
import (
4
+
"strings"
5
+
6
+
"tangled.org/evan.jarrett.net/aoc2025/internal/puzzle"
7
+
)
8
+
9
+
type PaperRoll struct {
10
+
row int
11
+
column int
12
+
left int
13
+
right int
14
+
up int
15
+
upLeft int
16
+
upRight int
17
+
down int
18
+
downLeft int
19
+
downRight int
20
+
}
21
+
22
+
func (p *PaperRoll) CanAccess() bool {
23
+
return p.left+p.right+p.up+p.down+p.upLeft+p.upRight+p.downLeft+p.downRight < 4
24
+
}
25
+
26
+
type DayFour struct {
27
+
grid []string
28
+
rolls []PaperRoll
29
+
}
30
+
31
+
const rollchar byte = '@'
32
+
33
+
func getCell(grid []string, i, j int) int {
34
+
if i < 0 || i >= len(grid) || j < 0 || j >= len(grid[i]) {
35
+
return 0
36
+
}
37
+
if grid[i][j] == rollchar {
38
+
return 1
39
+
}
40
+
return 0
41
+
}
42
+
43
+
func (d *DayFour) ParseInputArr(input []string) {
44
+
for i, line := range d.grid {
45
+
line = strings.TrimSpace(line)
46
+
if line == "" {
47
+
continue
48
+
}
49
+
for j, ch := range line {
50
+
if ch == rune(rollchar) {
51
+
p := PaperRoll{
52
+
row: i,
53
+
column: j,
54
+
left: getCell(d.grid, i, j-1),
55
+
right: getCell(d.grid, i, j+1),
56
+
up: getCell(d.grid, i-1, j),
57
+
upLeft: getCell(d.grid, i-1, j-1),
58
+
upRight: getCell(d.grid, i-1, j+1),
59
+
down: getCell(d.grid, i+1, j),
60
+
downLeft: getCell(d.grid, i+1, j-1),
61
+
downRight: getCell(d.grid, i+1, j+1),
62
+
}
63
+
d.rolls = append(d.rolls, p)
64
+
}
65
+
}
66
+
}
67
+
}
68
+
69
+
func (d *DayFour) ParseInput(input string) error {
70
+
d.grid = strings.Split(strings.TrimSpace(input), "\n")
71
+
d.ParseInputArr(d.grid)
72
+
return nil
73
+
}
74
+
75
+
func (d *DayFour) Part1() (int, error) {
76
+
count := 0
77
+
for _, roll := range d.rolls {
78
+
if roll.CanAccess() {
79
+
count++
80
+
}
81
+
}
82
+
return count, nil
83
+
}
84
+
85
+
func (d *DayFour) Part2() (int, error) {
86
+
count := 0
87
+
changed := true
88
+
89
+
for changed {
90
+
changed = false
91
+
d.rolls = nil
92
+
d.ParseInputArr(d.grid)
93
+
94
+
for _, roll := range d.rolls {
95
+
if roll.CanAccess() {
96
+
d.grid[roll.row] = d.grid[roll.row][:roll.column] + "." + d.grid[roll.row][roll.column+1:]
97
+
count++
98
+
changed = true
99
+
}
100
+
}
101
+
}
102
+
return count, nil
103
+
}
104
+
105
+
func main() {
106
+
puzzle.Run(4, &DayFour{})
107
+
}
+51
cmd/four/main_test.go
+51
cmd/four/main_test.go
···
1
+
package main
2
+
3
+
import (
4
+
"testing"
5
+
)
6
+
7
+
const testInput = `..@@.@@@@.
8
+
@@@.@.@.@@
9
+
@@@@@.@.@@
10
+
@.@@@@..@.
11
+
@@.@@@@.@@
12
+
.@@@@@@@.@
13
+
.@.@.@.@@@
14
+
@.@@@.@@@@
15
+
.@@@@@@@@.
16
+
@.@.@@@.@.
17
+
`
18
+
19
+
func TestPart1(t *testing.T) {
20
+
d := &DayFour{}
21
+
if err := d.ParseInput(testInput); err != nil {
22
+
t.Fatalf("ParseInput failed: %v", err)
23
+
}
24
+
25
+
got, err := d.Part1()
26
+
if err != nil {
27
+
t.Fatalf("Part1 failed: %v", err)
28
+
}
29
+
30
+
want := 13
31
+
if got != want {
32
+
t.Errorf("Part1() = %d, want %d", got, want)
33
+
}
34
+
}
35
+
36
+
func TestPart2(t *testing.T) {
37
+
d := &DayFour{}
38
+
if err := d.ParseInput(testInput); err != nil {
39
+
t.Fatalf("ParseInput failed: %v", err)
40
+
}
41
+
42
+
got, err := d.Part2()
43
+
if err != nil {
44
+
t.Fatalf("Part2 failed: %v", err)
45
+
}
46
+
47
+
want := 43
48
+
if got != want {
49
+
t.Errorf("Part2() = %d, want %d", got, want)
50
+
}
51
+
}
+9
-1
newday.sh
+9
-1
newday.sh
···
50
50
package main
51
51
52
52
import (
53
+
"strings"
54
+
53
55
"tangled.org/evan.jarrett.net/aoc2025/internal/puzzle"
54
56
)
55
57
···
58
60
}
59
61
60
62
func (d *Day${DAY_WORD_CAP}) ParseInput(input string) error {
61
-
// TODO: parse input
63
+
for line := range strings.SplitSeq(strings.TrimSpace(input), "\n") {
64
+
line = strings.TrimSpace(line)
65
+
if line == "" {
66
+
continue
67
+
}
68
+
// TODO: parse line
69
+
}
62
70
return nil
63
71
}
64
72