feat: completed day 2 for advent of code 2025
This commit is contained in:
parent
7062b47026
commit
683175bfec
4 changed files with 162 additions and 0 deletions
|
|
@ -10,10 +10,12 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"cpatino.com/advent-of-code/2025/day01"
|
"cpatino.com/advent-of-code/2025/day01"
|
||||||
|
"cpatino.com/advent-of-code/2025/day03"
|
||||||
)
|
)
|
||||||
|
|
||||||
var days = map[int]func(string) (any, any){
|
var days = map[int]func(string) (any, any){
|
||||||
1: day01.Run,
|
1: day01.Run,
|
||||||
|
3: day03.Run,
|
||||||
}
|
}
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
|
|
|
||||||
123
2025/day02/day02.go
Executable file
123
2025/day02/day02.go
Executable file
|
|
@ -0,0 +1,123 @@
|
||||||
|
package day02
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Part1(input string) int {
|
||||||
|
total := 0
|
||||||
|
input = strings.TrimSpace(input)
|
||||||
|
if input == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rng := range strings.Split(input, ",") {
|
||||||
|
rng = strings.TrimSpace(rng)
|
||||||
|
if rng == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(rng, "-")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
start, end := 0, 0
|
||||||
|
_, err1 := fmt.Sscanf(parts[0], "%d", &start)
|
||||||
|
_, err2 := fmt.Sscanf(parts[1], "%d", &end)
|
||||||
|
if err1 != nil || err2 != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for id := start; id <= end; id++ {
|
||||||
|
idStr := fmt.Sprintf("%d", id)
|
||||||
|
for k := 1; k <= len(idStr)/2; k++ {
|
||||||
|
if len(idStr) == 2*k && idStr[:k] == idStr[k:] {
|
||||||
|
total += id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
func Part2(input string) int {
|
||||||
|
total := 0
|
||||||
|
input = strings.TrimSpace(input)
|
||||||
|
if input == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rng := range strings.Split(input, ",") {
|
||||||
|
rng = strings.TrimSpace(rng)
|
||||||
|
if rng == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(rng, "-")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
start, end := 0, 0
|
||||||
|
_, err1 := fmt.Sscanf(parts[0], "%d", &start)
|
||||||
|
_, err2 := fmt.Sscanf(parts[1], "%d", &end)
|
||||||
|
if err1 != nil || err2 != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for id := start; id <= end; id++ {
|
||||||
|
idStr := fmt.Sprintf("%d", id)
|
||||||
|
for k := 1; k <= len(idStr)/2; k++ {
|
||||||
|
if len(idStr)%k != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk := idStr[:k]
|
||||||
|
valid := true
|
||||||
|
for i := k; i < len(idStr); i += k {
|
||||||
|
if idStr[i:i+k] != chunk {
|
||||||
|
valid = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if valid && len(idStr)/k >= 2 {
|
||||||
|
total += id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run(filename string) (any, any) {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
var lines []string
|
||||||
|
for scanner.Scan() {
|
||||||
|
lines = append(lines, scanner.Text())
|
||||||
|
}
|
||||||
|
input := strings.Join(lines, "")
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
part1 := Part1(input)
|
||||||
|
part2 := Part2(input)
|
||||||
|
|
||||||
|
return part1, part2
|
||||||
|
}
|
||||||
34
2025/day02/day02_test.go
Executable file
34
2025/day02/day02_test.go
Executable file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package day02
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestCase struct {
|
||||||
|
FileName string
|
||||||
|
Part1 any
|
||||||
|
Part2 any
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDay02(t *testing.T) {
|
||||||
|
tests := []TestCase{
|
||||||
|
{"test.txt", 1227775554, 4174379265},
|
||||||
|
{"input.txt", 40398804950, 65794984339},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
if _, err := os.Stat(test.FileName); os.IsNotExist(err) {
|
||||||
|
t.Fatalf("test file does not exist: %v", test.FileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
part1, part2 := Run(test.FileName)
|
||||||
|
if test.Part1 != nil && part1 != test.Part1 {
|
||||||
|
t.Fatalf("%s: unexpected part1:\nwant:\t%v\ngot:\t%v", test.FileName, test.Part1, part1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.Part2 != nil && part2 != test.Part2 {
|
||||||
|
t.Fatalf("%s: unexpected part2:\nwant:\t%v\ngot:\t%v", test.FileName, test.Part2, part2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
2025/day02/test.txt
Executable file
3
2025/day02/test.txt
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,
|
||||||
|
1698522-1698528,446443-446449,38593856-38593862,565653-565659,
|
||||||
|
824824821-824824827,2121212118-2121212124
|
||||||
Loading…
Add table
Add a link
Reference in a new issue