feat: completed day 7 for advent of code 2025

This commit is contained in:
Ceferino Patino 2025-12-07 11:36:26 -06:00
commit 3399702096
Signed by: c4patino
SSH key fingerprint: SHA256:Wu+cU1t+7zVT9wzew/4meNmeulo66NzMqc22MdDBgXI
4 changed files with 172 additions and 0 deletions

View file

@ -15,6 +15,7 @@ import (
"cpatino.com/advent-of-code/2025/day04"
"cpatino.com/advent-of-code/2025/day05"
"cpatino.com/advent-of-code/2025/day06"
"cpatino.com/advent-of-code/2025/day07"
)
var days = map[int]func(string) (any, any){
@ -24,6 +25,7 @@ var days = map[int]func(string) (any, any){
4: day04.Run,
5: day05.Run,
6: day06.Run,
7: day07.Run,
}
var rootCmd = &cobra.Command{

120
2025/day07/day07.go Executable file
View file

@ -0,0 +1,120 @@
package day07
import (
"bufio"
"os"
)
type Beam struct {
x, y int
}
type Grid struct {
cells [][]rune
}
func Run(filename string) (any, any) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var grid [][]rune
startX, startY := -1, -1
row := 0
for scanner.Scan() {
line := scanner.Text()
rowRunes := []rune(line)
if startX == -1 {
for col, ch := range rowRunes {
if ch == 'S' {
startX, startY = row, col
}
}
}
grid = append(grid, rowRunes)
row++
}
if err := scanner.Err(); err != nil {
panic(err)
}
g := Grid{cells: grid}
part1 := Part1(&g, startX, startY)
part2 := Part2(&g, startX, startY)
return part1, part2
}
func Part1(grid *Grid, startX, startY int) int {
visited := make(map[Beam]bool)
splits := 0
queue := []Beam{{startX, startY}}
for len(queue) > 0 {
pos := queue[0]
queue = queue[1:]
nx, ny := pos.x+1, pos.y
if nx < 0 || ny < 0 || nx >= len(grid.cells) || ny >= len(grid.cells[0]) {
continue
}
state := Beam{nx, ny}
if visited[state] {
continue
}
visited[state] = true
cell := grid.cells[nx][ny]
if cell == '^' {
splits++
if ny-1 >= 0 {
queue = append(queue, Beam{nx, ny - 1})
}
if ny+1 < len(grid.cells[0]) {
queue = append(queue, Beam{nx, ny + 1})
}
} else {
queue = append(queue, Beam{nx, ny})
}
}
return splits
}
func Part2(grid *Grid, startX, startY int) int {
memo := make(map[Beam]int)
var dfs func(x, y int) int
dfs = func(x, y int) int {
if x < 0 || y < 0 || x >= len(grid.cells) || y >= len(grid.cells[0]) {
return 1
}
state := Beam{x, y}
if v, ok := memo[state]; ok {
return v
}
cell := grid.cells[x][y]
if cell == '^' {
left, right := 0, 0
if y-1 >= 0 {
left = dfs(x+1, y-1)
}
if y+1 < len(grid.cells[0]) {
right = dfs(x+1, y+1)
}
res := left + right
memo[state] = res
return res
}
res := dfs(x+1, y)
memo[state] = res
return res
}
return dfs(startX+1, startY)
}

34
2025/day07/day07_test.go Executable file
View file

@ -0,0 +1,34 @@
package day07
import (
"os"
"testing"
)
type TestCase struct {
FileName string
Part1 any
Part2 any
}
func TestDay07(t *testing.T) {
tests := []TestCase{
{"test.txt", 21, 40},
{"input.txt", 1573, 15093663987272},
}
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)
}
}
}

16
2025/day07/test.txt Executable file
View file

@ -0,0 +1,16 @@
.......S.......
...............
.......^.......
...............
......^.^......
...............
.....^.^.^.....
...............
....^.^...^....
...............
...^.^...^.^...
...............
..^...^.....^..
...............
.^.^.^.^.^...^.
...............