no this isn't about alexandria ocasio-cortez
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

update

+794
+148
cmd/eight/main.go
··· 1 + package main 2 + 3 + import ( 4 + "cmp" 5 + "fmt" 6 + "math" 7 + "slices" 8 + "strconv" 9 + "strings" 10 + 11 + "tangled.org/evan.jarrett.net/aoc2025/internal/puzzle" 12 + ) 13 + 14 + type Edge struct { 15 + A Coord 16 + B Coord 17 + Distance float64 18 + } 19 + 20 + type Coord struct { 21 + x int 22 + y int 23 + z int 24 + } 25 + 26 + func (c Coord) Distance(other Coord) float64 { 27 + dx := float64(other.x - c.x) 28 + dy := float64(other.y - c.y) 29 + dz := float64(other.z - c.z) 30 + return math.Sqrt(dx*dx + dy*dy + dz*dz) 31 + } 32 + 33 + func buildEdges(coords []Coord) []Edge { 34 + var edges []Edge 35 + for i := range coords { 36 + for j := i + 1; j < len(coords); j++ { 37 + edges = append(edges, Edge{ 38 + A: coords[i], 39 + B: coords[j], 40 + Distance: coords[i].Distance(coords[j]), 41 + }) 42 + } 43 + } 44 + slices.SortFunc(edges, func(a, b Edge) int { 45 + return cmp.Compare(a.Distance, b.Distance) 46 + }) 47 + return edges 48 + } 49 + 50 + type DayEight struct { 51 + coordinates []Coord 52 + edges []Edge 53 + numPairs int 54 + } 55 + 56 + func (d *DayEight) ParseInput(input string) error { 57 + for line := range strings.SplitSeq(strings.TrimSpace(input), "\n") { 58 + line = strings.TrimSpace(line) 59 + if line == "" { 60 + continue 61 + } 62 + parts := strings.Split(line, ",") 63 + if len(parts) != 3 { 64 + return fmt.Errorf("invalid input: %s", line) 65 + } 66 + x, _ := strconv.Atoi(parts[0]) 67 + y, _ := strconv.Atoi(parts[1]) 68 + z, _ := strconv.Atoi(parts[2]) 69 + d.coordinates = append(d.coordinates, Coord{ 70 + x: x, 71 + y: y, 72 + z: z, 73 + }) 74 + } 75 + d.edges = buildEdges(d.coordinates) 76 + 77 + return nil 78 + } 79 + 80 + func (d *DayEight) Part1() (int, error) { 81 + circuit := make(map[Coord]int) 82 + for i, c := range d.coordinates { 83 + circuit[c] = i 84 + } 85 + 86 + // Connect the numPairs shortest pairs 87 + for i := 0; i < d.numPairs && i < len(d.edges); i++ { 88 + circuitA := circuit[d.edges[i].A] 89 + circuitB := circuit[d.edges[i].B] 90 + 91 + if circuitA != circuitB { 92 + for c := range circuit { 93 + if circuit[c] == circuitB { 94 + circuit[c] = circuitA 95 + } 96 + } 97 + } 98 + } 99 + 100 + // Count sizes of each circuit 101 + sizes := make(map[int]int) 102 + for _, circuitID := range circuit { 103 + sizes[circuitID]++ 104 + } 105 + 106 + var sizeList []int 107 + for _, s := range sizes { 108 + sizeList = append(sizeList, s) 109 + } 110 + slices.Sort(sizeList) 111 + slices.Reverse(sizeList) 112 + 113 + return sizeList[0] * sizeList[1] * sizeList[2], nil 114 + } 115 + 116 + func (d *DayEight) Part2() (int, error) { 117 + circuit := make(map[Coord]int) 118 + for i, c := range d.coordinates { 119 + circuit[c] = i 120 + } 121 + 122 + var finalA, finalB Coord 123 + 124 + // loop through all edges until nothing left 125 + for _, e := range d.edges { 126 + circuitA := circuit[e.A] 127 + circuitB := circuit[e.B] 128 + 129 + if circuitA != circuitB { 130 + for c := range circuit { 131 + if circuit[c] == circuitB { 132 + circuit[c] = circuitA 133 + } 134 + } 135 + d.numPairs-- 136 + if d.numPairs == 1 { 137 + finalA = e.A 138 + finalB = e.B 139 + } 140 + } 141 + } 142 + fmt.Printf("Final coordinates: %v, %v\n", finalA, finalB) 143 + return finalA.x * finalB.x, nil 144 + } 145 + 146 + func main() { 147 + puzzle.Run(8, &DayEight{numPairs: 1000}) 148 + }
+61
cmd/eight/main_test.go
··· 1 + package main 2 + 3 + import ( 4 + "testing" 5 + ) 6 + 7 + const testInput = `162,817,812 8 + 57,618,57 9 + 906,360,560 10 + 592,479,940 11 + 352,342,300 12 + 466,668,158 13 + 542,29,236 14 + 431,825,988 15 + 739,650,466 16 + 52,470,668 17 + 216,146,977 18 + 819,987,18 19 + 117,168,530 20 + 805,96,715 21 + 346,949,466 22 + 970,615,88 23 + 941,993,340 24 + 862,61,35 25 + 984,92,344 26 + 425,690,689 27 + ` 28 + 29 + func TestPart1(t *testing.T) { 30 + d := &DayEight{numPairs: 10} 31 + if err := d.ParseInput(testInput); err != nil { 32 + t.Fatalf("ParseInput failed: %v", err) 33 + } 34 + 35 + got, err := d.Part1() 36 + if err != nil { 37 + t.Fatalf("Part1 failed: %v", err) 38 + } 39 + 40 + want := 40 41 + if got != want { 42 + t.Errorf("Part1() = %d, want %d", got, want) 43 + } 44 + } 45 + 46 + func TestPart2(t *testing.T) { 47 + d := &DayEight{numPairs: 20} 48 + if err := d.ParseInput(testInput); err != nil { 49 + t.Fatalf("ParseInput failed: %v", err) 50 + } 51 + 52 + got, err := d.Part2() 53 + if err != nil { 54 + t.Fatalf("Part2 failed: %v", err) 55 + } 56 + 57 + want := 25272 58 + if got != want { 59 + t.Errorf("Part2() = %d, want %d", got, want) 60 + } 61 + }
+123
cmd/nine/main.go
··· 1 + package main 2 + 3 + import ( 4 + "strconv" 5 + "strings" 6 + 7 + "tangled.org/evan.jarrett.net/aoc2025/internal/puzzle" 8 + ) 9 + 10 + type Tuple struct { 11 + x int 12 + y int 13 + } 14 + 15 + func (t *Tuple) getArea(o Tuple) int { 16 + abs := func(n int) int { 17 + if n < 0 { 18 + return -n 19 + } 20 + return n 21 + } 22 + 23 + return (abs(t.x-o.x) + 1) * (abs(t.y-o.y) + 1) 24 + } 25 + 26 + func (t Tuple) AreaContainsWall(o Tuple, vertical map[int][]Wall, horizontal map[int][]Wall) bool { 27 + minX, maxX := min(t.x, o.x), max(t.x, o.x) 28 + minY, maxY := min(t.y, o.y), max(t.y, o.y) 29 + 30 + // Check vertical 31 + for x := minX + 1; x < maxX; x++ { 32 + for _, w := range vertical[x] { 33 + if w.start < maxY && w.end > minY { 34 + return true 35 + } 36 + } 37 + } 38 + 39 + // Check horizontal 40 + for y := minY + 1; y < maxY; y++ { 41 + for _, w := range horizontal[y] { 42 + if w.start < maxX && w.end > minX { 43 + return true 44 + } 45 + } 46 + } 47 + 48 + return false 49 + } 50 + 51 + type Wall struct { 52 + start int 53 + end int 54 + } 55 + 56 + type DayNine struct { 57 + pairs []Tuple 58 + } 59 + 60 + func (d *DayNine) ParseInput(input string) error { 61 + for line := range strings.SplitSeq(strings.TrimSpace(input), "\n") { 62 + line = strings.TrimSpace(line) 63 + if line == "" { 64 + continue 65 + } 66 + xy := strings.Split(line, ",") 67 + x, _ := strconv.Atoi(xy[0]) 68 + y, _ := strconv.Atoi(xy[1]) 69 + d.pairs = append(d.pairs, Tuple{x, y}) 70 + } 71 + return nil 72 + } 73 + 74 + func (d *DayNine) Part1() (int, error) { 75 + maxArea := 0 76 + for i := 0; i < len(d.pairs); i++ { 77 + for j := i + 1; j < len(d.pairs); j++ { 78 + area := d.pairs[i].getArea(d.pairs[j]) 79 + maxArea = max(maxArea, area) 80 + } 81 + } 82 + return maxArea, nil 83 + } 84 + 85 + func buildWalls(points []Tuple) (vertical map[int][]Wall, horizontal map[int][]Wall) { 86 + vertical = make(map[int][]Wall) 87 + horizontal = make(map[int][]Wall) 88 + 89 + for i := 0; i < len(points); i++ { 90 + for j := i + 1; j < len(points); j++ { 91 + p1, p2 := points[i], points[j] 92 + if p1.x == p2.x { 93 + // Vertical wall 94 + y1, y2 := min(p1.y, p2.y), max(p1.y, p2.y) 95 + vertical[p1.x] = append(vertical[p1.x], Wall{y1, y2}) 96 + } else if p1.y == p2.y { 97 + // Horizontal wall 98 + x1, x2 := min(p1.x, p2.x), max(p1.x, p2.x) 99 + horizontal[p1.y] = append(horizontal[p1.y], Wall{x1, x2}) 100 + } 101 + } 102 + } 103 + return vertical, horizontal 104 + } 105 + 106 + func (d *DayNine) Part2() (int, error) { 107 + vert, horiz := buildWalls(d.pairs) 108 + maxArea := 0 109 + 110 + for i := 0; i < len(d.pairs); i++ { 111 + for j := i + 1; j < len(d.pairs); j++ { 112 + if !d.pairs[i].AreaContainsWall(d.pairs[j], vert, horiz) { 113 + maxArea = max(maxArea, d.pairs[i].getArea(d.pairs[j])) 114 + } 115 + } 116 + } 117 + 118 + return maxArea, nil 119 + } 120 + 121 + func main() { 122 + puzzle.Run(9, &DayNine{}) 123 + }
+49
cmd/nine/main_test.go
··· 1 + package main 2 + 3 + import ( 4 + "testing" 5 + ) 6 + 7 + const testInput = `7,1 8 + 11,1 9 + 11,7 10 + 9,7 11 + 9,5 12 + 2,5 13 + 2,3 14 + 7,3 15 + ` 16 + 17 + func TestPart1(t *testing.T) { 18 + d := &DayNine{} 19 + if err := d.ParseInput(testInput); err != nil { 20 + t.Fatalf("ParseInput failed: %v", err) 21 + } 22 + 23 + got, err := d.Part1() 24 + if err != nil { 25 + t.Fatalf("Part1 failed: %v", err) 26 + } 27 + 28 + want := 50 29 + if got != want { 30 + t.Errorf("Part1() = %d, want %d", got, want) 31 + } 32 + } 33 + 34 + func TestPart2(t *testing.T) { 35 + d := &DayNine{} 36 + if err := d.ParseInput(testInput); err != nil { 37 + t.Fatalf("ParseInput failed: %v", err) 38 + } 39 + 40 + got, err := d.Part2() 41 + if err != nil { 42 + t.Fatalf("Part2 failed: %v", err) 43 + } 44 + 45 + want := 24 46 + if got != want { 47 + t.Errorf("Part2() = %d, want %d", got, want) 48 + } 49 + }
+90
cmd/seven/main.go
··· 1 + package main 2 + 3 + import ( 4 + "strings" 5 + 6 + "tangled.org/evan.jarrett.net/aoc2025/internal/puzzle" 7 + ) 8 + 9 + type tuple [2]int 10 + 11 + type DaySeven struct { 12 + lines []string 13 + splitCount int 14 + visited map[tuple]int 15 + } 16 + 17 + func (d *DaySeven) ParseInput(input string) error { 18 + lines := strings.Split(strings.TrimSpace(input), "\n") 19 + d.lines = lines 20 + 21 + return nil 22 + } 23 + 24 + func (d *DaySeven) findPathsOne(i, col int) { 25 + if col < 0 || col >= len(d.lines[0]) { 26 + return 27 + } 28 + 29 + // continue until ^ or no more lines 30 + for i < len(d.lines) && d.lines[i][col] != '^' { 31 + i++ 32 + } 33 + 34 + if i >= len(d.lines) { 35 + return 36 + } 37 + 38 + pos := tuple{i, col} 39 + if d.visited[pos] > 0 { 40 + return 41 + } 42 + d.visited[pos] = d.splitCount 43 + 44 + d.splitCount++ 45 + d.findPathsOne(i+1, col-1) 46 + d.findPathsOne(i+1, col+1) 47 + } 48 + 49 + func (d *DaySeven) Part1() (int, error) { 50 + start := strings.Index(d.lines[0], "S") 51 + d.visited = make(map[tuple]int) 52 + d.splitCount = 0 53 + d.findPathsOne(0, start) 54 + 55 + return d.splitCount, nil 56 + } 57 + 58 + func (d *DaySeven) findPathsTwo(i, col int) int { 59 + if col < 0 || col >= len(d.lines[0]) { 60 + return 0 61 + } 62 + 63 + // continue until ^ or no more lines 64 + for i < len(d.lines) && d.lines[i][col] != '^' { 65 + i++ 66 + } 67 + 68 + pos := tuple{i, col} 69 + if count, ok := d.visited[pos]; ok { 70 + return count 71 + } 72 + 73 + if i >= len(d.lines) { 74 + return 1 75 + } 76 + d.visited[pos] = d.findPathsTwo(i+1, col-1) + d.findPathsTwo(i+1, col+1) 77 + return d.visited[pos] 78 + } 79 + 80 + func (d *DaySeven) Part2() (int, error) { 81 + start := strings.Index(d.lines[0], "S") 82 + d.visited = make(map[tuple]int) 83 + d.splitCount = d.findPathsTwo(0, start) 84 + 85 + return d.splitCount, nil 86 + } 87 + 88 + func main() { 89 + puzzle.Run(7, &DaySeven{}) 90 + }
+57
cmd/seven/main_test.go
··· 1 + package main 2 + 3 + import ( 4 + "testing" 5 + ) 6 + 7 + const testInput = `.......S....... 8 + ............... 9 + .......^....... 10 + ............... 11 + ......^.^...... 12 + ............... 13 + .....^.^.^..... 14 + ............... 15 + ....^.^...^.... 16 + ............... 17 + ...^.^...^.^... 18 + ............... 19 + ..^...^.....^.. 20 + ............... 21 + .^.^.^.^.^...^. 22 + ............... 23 + ` 24 + 25 + func TestPart1(t *testing.T) { 26 + d := &DaySeven{} 27 + if err := d.ParseInput(testInput); err != nil { 28 + t.Fatalf("ParseInput failed: %v", err) 29 + } 30 + 31 + got, err := d.Part1() 32 + if err != nil { 33 + t.Fatalf("Part1 failed: %v", err) 34 + } 35 + 36 + want := 21 37 + if got != want { 38 + t.Errorf("Part1() = %d, want %d", got, want) 39 + } 40 + } 41 + 42 + func TestPart2(t *testing.T) { 43 + d := &DaySeven{} 44 + if err := d.ParseInput(testInput); err != nil { 45 + t.Fatalf("ParseInput failed: %v", err) 46 + } 47 + 48 + got, err := d.Part2() 49 + if err != nil { 50 + t.Fatalf("Part2 failed: %v", err) 51 + } 52 + 53 + want := 40 54 + if got != want { 55 + t.Errorf("Part2() = %d, want %d", got, want) 56 + } 57 + }
+134
cmd/six/main.go
··· 1 + package main 2 + 3 + import ( 4 + "strconv" 5 + "strings" 6 + 7 + "tangled.org/evan.jarrett.net/aoc2025/internal/puzzle" 8 + ) 9 + 10 + type Problem struct { 11 + numbers []int 12 + operation string 13 + } 14 + 15 + func (p *Problem) getCount() int { 16 + var count int 17 + switch p.operation { 18 + case "+": 19 + count = 0 20 + for i := range p.numbers { 21 + count += p.numbers[i] 22 + } 23 + case "*": 24 + count = 1 25 + for i := range p.numbers { 26 + count *= p.numbers[i] 27 + } 28 + } 29 + return count 30 + } 31 + 32 + type DaySix struct { 33 + grid [][]string 34 + problems []Problem 35 + } 36 + 37 + func (d *DaySix) ParseInput(input string) error { 38 + rows := strings.Split(strings.TrimSpace(input), "\n") 39 + 40 + for _, row := range rows { 41 + d.grid = append(d.grid, strings.Fields(row)) 42 + } 43 + 44 + columns := len(d.grid[0]) 45 + numrow := len(d.grid) 46 + 47 + for c := range columns { 48 + var numbers []int 49 + var operation string 50 + for r := range numrow { 51 + ch := d.grid[r][c] 52 + if ch == "+" || ch == "*" { 53 + operation = ch 54 + } else { 55 + n, _ := strconv.Atoi(ch) 56 + numbers = append(numbers, n) 57 + } 58 + } 59 + d.problems = append(d.problems, Problem{ 60 + numbers: numbers, 61 + operation: operation, 62 + }) 63 + } 64 + return nil 65 + } 66 + 67 + func (d *DaySix) Part1() (int, error) { 68 + sum := 0 69 + for _, p := range d.problems { 70 + sum += p.getCount() 71 + } 72 + return sum, nil 73 + } 74 + 75 + func (d *DaySix) ParseInput2(input string) error { 76 + // don't trim space here, we need it to know how many columns 77 + rows := strings.Split(input, "\n") 78 + 79 + // Clear any existing problems from Part1 80 + d.problems = nil 81 + 82 + var numbers []int 83 + var operation string 84 + 85 + // Process character columns right-to-left 86 + for col := len(rows[0]) - 1; col >= 0; col-- { 87 + var numStr string 88 + var op string 89 + 90 + for _, row := range rows { 91 + var ch byte = ' ' 92 + if col < len(row) { 93 + ch = row[col] 94 + } 95 + 96 + if ch >= '0' && ch <= '9' { 97 + numStr += string(ch) 98 + } else if ch == '*' || ch == '+' { 99 + op = string(ch) 100 + } 101 + } 102 + 103 + // A column can have both a number AND an operator 104 + if numStr != "" { 105 + n, _ := strconv.Atoi(numStr) 106 + numbers = append(numbers, n) 107 + } 108 + 109 + if op != "" { 110 + // found operator - save current problem 111 + operation = op 112 + d.problems = append(d.problems, Problem{ 113 + numbers: numbers, 114 + operation: operation, 115 + }) 116 + numbers = nil 117 + operation = "" 118 + } 119 + } 120 + 121 + return nil 122 + } 123 + 124 + func (d *DaySix) Part2() (int, error) { 125 + sum := 0 126 + for _, p := range d.problems { 127 + sum += p.getCount() 128 + } 129 + return sum, nil 130 + } 131 + 132 + func main() { 133 + puzzle.Run(6, &DaySix{}) 134 + }
+45
cmd/six/main_test.go
··· 1 + package main 2 + 3 + import ( 4 + "testing" 5 + ) 6 + 7 + const testInput = `123 328 51 64 8 + 45 64 387 23 9 + 6 98 215 314 10 + * + * + 11 + ` 12 + 13 + func TestPart1(t *testing.T) { 14 + d := &DaySix{} 15 + if err := d.ParseInput(testInput); err != nil { 16 + t.Fatalf("ParseInput failed: %v", err) 17 + } 18 + 19 + got, err := d.Part1() 20 + if err != nil { 21 + t.Fatalf("Part1 failed: %v", err) 22 + } 23 + 24 + want := 4277556 25 + if got != want { 26 + t.Errorf("Part1() = %d, want %d", got, want) 27 + } 28 + } 29 + 30 + func TestPart2(t *testing.T) { 31 + d := &DaySix{} 32 + if err := d.ParseInput2(testInput); err != nil { 33 + t.Fatalf("ParseInput failed: %v", err) 34 + } 35 + 36 + got, err := d.Part2() 37 + if err != nil { 38 + t.Fatalf("Part2 failed: %v", err) 39 + } 40 + 41 + want := 3263827 42 + if got != want { 43 + t.Errorf("Part2() = %d, want %d", got, want) 44 + } 45 + }
+36
cmd/ten/main.go
··· 1 + package main 2 + 3 + import ( 4 + "strings" 5 + 6 + "tangled.org/evan.jarrett.net/aoc2025/internal/puzzle" 7 + ) 8 + 9 + type DayTen struct { 10 + // parsed input fields 11 + } 12 + 13 + func (d *DayTen) ParseInput(input string) error { 14 + for line := range strings.SplitSeq(strings.TrimSpace(input), "\n") { 15 + line = strings.TrimSpace(line) 16 + if line == "" { 17 + continue 18 + } 19 + // TODO: parse line 20 + } 21 + return nil 22 + } 23 + 24 + func (d *DayTen) Part1() (int, error) { 25 + // TODO: solve part 1 26 + return 0, nil 27 + } 28 + 29 + func (d *DayTen) Part2() (int, error) { 30 + // TODO: solve part 2 31 + return 0, nil 32 + } 33 + 34 + func main() { 35 + puzzle.Run(10, &DayTen{}) 36 + }
+41
cmd/ten/main_test.go
··· 1 + package main 2 + 3 + import ( 4 + "testing" 5 + ) 6 + 7 + const testInput = `` 8 + 9 + func TestPart1(t *testing.T) { 10 + d := &DayTen{} 11 + if err := d.ParseInput(testInput); err != nil { 12 + t.Fatalf("ParseInput failed: %v", err) 13 + } 14 + 15 + got, err := d.Part1() 16 + if err != nil { 17 + t.Fatalf("Part1 failed: %v", err) 18 + } 19 + 20 + want := 0 // TODO: set expected value 21 + if got != want { 22 + t.Errorf("Part1() = %d, want %d", got, want) 23 + } 24 + } 25 + 26 + func TestPart2(t *testing.T) { 27 + d := &DayTen{} 28 + if err := d.ParseInput(testInput); err != nil { 29 + t.Fatalf("ParseInput failed: %v", err) 30 + } 31 + 32 + got, err := d.Part2() 33 + if err != nil { 34 + t.Fatalf("Part2 failed: %v", err) 35 + } 36 + 37 + want := 0 // TODO: set expected value 38 + if got != want { 39 + t.Errorf("Part2() = %d, want %d", got, want) 40 + } 41 + }
+4
internal/puzzle/puzzle.go
··· 5 5 Part1() (T1, error) 6 6 Part2() (T2, error) 7 7 } 8 + 9 + type Part2Parser interface { 10 + ParseInput2(input string) error 11 + }
+6
internal/puzzle/runner.go
··· 23 23 } 24 24 fmt.Printf("Part 1: %v\n", result1) 25 25 26 + if p2, ok := any(p).(Part2Parser); ok { 27 + if err := p2.ParseInput2(input); err != nil { 28 + log.Fatalf("Failed to parse input for part 2: %v", err) 29 + } 30 + } 31 + 26 32 result2, err := p.Part2() 27 33 if err != nil { 28 34 log.Fatalf("Failed to solve part 2: %v", err)