Skip to content

Commit dbbdc41

Browse files
committed
2025 Day05
1 parent b1a3f3a commit dbbdc41

File tree

6 files changed

+137
-0
lines changed

6 files changed

+137
-0
lines changed

2025/day05/.bench

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"Lines":[{"Name":"Part 1","N":13522,"NsPerOp":85678,"AllocedBytesPerOp":0,"AllocsPerOp":0,"MBPerS":0,"Measured":1,"Ord":0},{"Name":"Part 2","N":455313,"NsPerOp":2629,"AllocedBytesPerOp":0,"AllocsPerOp":0,"MBPerS":0,"Measured":1,"Ord":0}],"Measured":1}

2025/day05/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!-- You can add some comments here if you want to :D -->

2025/day05/main.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package main
2+
3+
import (
4+
"aocli/utils"
5+
_ "embed"
6+
"fmt"
7+
"os"
8+
"slices"
9+
"strings"
10+
)
11+
12+
//go:embed input.txt
13+
var input string
14+
15+
//go:embed input_test.txt
16+
var inputTest string
17+
18+
type fresh struct {
19+
start, end int
20+
}
21+
22+
var ranges []fresh
23+
var sections []string
24+
25+
func main() {
26+
// Check argv if we use test input or not
27+
if len(os.Args) > 1 && os.Args[1] == "test" {
28+
input = inputTest
29+
}
30+
31+
// Parse input once
32+
sections = strings.Split(strings.TrimSpace(input), "\n\n")
33+
parseRanges()
34+
35+
answer := doPartOne()
36+
println(answer)
37+
38+
answer = doPartTwo()
39+
println(answer)
40+
}
41+
42+
func parseRanges() {
43+
rangeLines := strings.Split(sections[0], "\n")
44+
ranges = make([]fresh, len(rangeLines))
45+
for i, v := range rangeLines {
46+
fmt.Sscanf(v, "%d-%d", &ranges[i].start, &ranges[i].end)
47+
}
48+
}
49+
50+
func mergeRanges() []fresh {
51+
// Sort and merge overlapping ranges
52+
sorted := make([]fresh, len(ranges))
53+
copy(sorted, ranges)
54+
55+
slices.SortFunc(sorted, func(a, b fresh) int {
56+
return a.start - b.start
57+
})
58+
59+
merged := make([]fresh, 0, len(sorted))
60+
current := sorted[0]
61+
62+
for i := 1; i < len(sorted); i++ {
63+
if sorted[i].start <= current.end+1 {
64+
// Overlapping or adjacent, merge them
65+
current.end = utils.Biggest(current.end, sorted[i].end)
66+
} else {
67+
// No overlap, save current and start new
68+
merged = append(merged, current)
69+
current = sorted[i]
70+
}
71+
}
72+
merged = append(merged, current)
73+
74+
return merged
75+
}

2025/day05/main_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package main
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func BenchmarkPartOne(b *testing.B) {
9+
// Parse input once before benchmark
10+
sections = strings.Split(strings.TrimSpace(input), "\n\n")
11+
parseRanges()
12+
13+
b.ResetTimer()
14+
for n := 0; n < b.N; n++ {
15+
doPartOne()
16+
}
17+
}
18+
19+
func BenchmarkPartTwo(b *testing.B) {
20+
// Parse input once before benchmark
21+
sections = strings.Split(strings.TrimSpace(input), "\n\n")
22+
parseRanges()
23+
24+
b.ResetTimer()
25+
for n := 0; n < b.N; n++ {
26+
doPartTwo()
27+
}
28+
}

2025/day05/part1.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package main
2+
3+
import (
4+
"aocli/utils"
5+
"strings"
6+
)
7+
8+
func doPartOne() int {
9+
ans := 0
10+
for _, v := range strings.Split(sections[1], "\n") {
11+
ingr := utils.Atoi(v)
12+
for _, r := range ranges {
13+
if ingr >= r.start && ingr <= r.end {
14+
ans++
15+
break
16+
}
17+
}
18+
}
19+
return ans
20+
}

2025/day05/part2.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
func doPartTwo() int {
4+
merged := mergeRanges()
5+
6+
ans := 0
7+
for _, r := range merged {
8+
ans += r.end - r.start + 1
9+
}
10+
11+
return ans
12+
}

0 commit comments

Comments
 (0)