Advent of Code solutions

Merge branch 'main' of github.com:foxfriends/advent-of-code

+145 -5
+2 -1
2025/3/p2.tri
··· 1 1 import "trilogy:debug" use dbg 2 2 import "trilogy:io" use readlines 3 3 import "trilogy:string" use chars, chomp 4 - import "trilogy:number" use from_digit, max 4 + import "trilogy:number" use from_digit 5 + import "trilogy:compare" use max 5 6 import "trilogy:iterator" as it 6 7 import "trilogy:array" as arr use take, skip 7 8
+2 -2
2025/5/p2.tri
··· 3 3 import "trilogy:array" use sort_by, fold 4 4 import "trilogy:parsec" use parse, apply, integer, char, per_line 5 5 import "trilogy:iterator" as it 6 - import "trilogy:number" use max 6 + import "trilogy:compare" use max, asc 7 7 8 8 proc input!() { 9 9 let range = do() { ··· 18 18 proc main!() { 19 19 let fresh:_ = readall!() 20 20 |> parse input 21 - |> sort_by (fn a b. a.'left < b.'left) 21 + |> sort_by (asc <| fn a. a.'left) 22 22 |> fold (fn (fresh:index) (low:high). fresh + ((max index (high + 1)) - (max index low)):(max index (high + 1))) (0:0) 23 23 dbg!(fresh) 24 24 }
+2 -1
2025/7/p1.tri
··· 1 1 import "trilogy:debug" use dbg 2 2 import "trilogy:io" use readlines 3 3 import "trilogy:string" use split, chomp 4 - import "trilogy:number" use max, im 4 + import "trilogy:compare" use max 5 + import "trilogy:number" use im 5 6 import "trilogy:array" use map, reduce, length 6 7 import "trilogy:set" use push, contains, collect 7 8 import "trilogy:iterator" as it
+2 -1
2025/7/p2.tri
··· 1 1 import "trilogy:debug" use dbg 2 2 import "trilogy:io" use readlines 3 3 import "trilogy:string" use split, chomp 4 - import "trilogy:number" use max, im 4 + import "trilogy:number" use im 5 + import "trilogy:compare" use max 5 6 import "trilogy:array" use map, reduce, length 6 7 import "trilogy:set" use push, contains, collect 7 8 import "trilogy:iterator" as it
+1
2025/8/p1.tri
··· 4 4 import "trilogy:array" use collect, sort_by, take, reduce 5 5 import "trilogy:core" use length 6 6 import "trilogy:iterator" as it 7 + import "trilogy:compare" use asc 7 8 import "trilogy:set" use union 8 9 import "trilogy:heap" use heap 9 10
+27
2025/9/p1.tri
··· 1 + import "trilogy:io" use readlines 2 + import "trilogy:debug" use dbg 3 + import "trilogy:parsec" use parse, sep_by, char, integer 4 + import "trilogy:array" use collect, length 5 + import "trilogy:number" use abs 6 + import "trilogy:compare" use max 7 + import "trilogy:iterator" use map 8 + 9 + func area [x1, y1] [x2, y2] = (abs (x1 - x2) + 1) * (abs (y1 - y2) + 1) 10 + 11 + proc main!() { 12 + let points = readlines 13 + |> map (parse (sep_by (char ',') integer)) 14 + |> collect 15 + 16 + let mut best = 0 17 + let mut i = 0 18 + while i < length points { 19 + let mut j = i + 1 20 + while j < length points { 21 + best max= (area (points.i) (points.j)) 22 + j += 1 23 + } 24 + i += 1 25 + } 26 + dbg!(best) 27 + }
+109
2025/9/p2.tri
··· 1 + import "trilogy:io" use readlines 2 + import "trilogy:debug" use dbg 3 + import "trilogy:parsec" use parse, sep_by, char, integer 4 + import "trilogy:array" use collect, length, map, reduce, first, tail, filter, sort, sort_by, any, push, zip 5 + import "trilogy:number" use abs 6 + import "trilogy:compare" use max, asc 7 + import "trilogy:iterator" as it 8 + 9 + func area [x1, y1] [x2, y2] = (abs (x1 - x2) + 1) * (abs (y1 - y2) + 1) 10 + 11 + func is_horizontal [_, y1]:[_, y2] = y1 == y2 12 + func is_vertical [x1, _]:[x2, _] = x1 == x2 13 + 14 + func collide p1:p2 [bx1, by1]:[bx2, by2] = 15 + let [px1, px2] = sort [x p1, x p2], 16 + let [py1, py2] = sort [y p1, y p2], 17 + px1 < bx2 && px2 > bx1 && py1 < by2 && py2 > by1 18 + 19 + func x [a, _] = a 20 + func y [_, a] = a 21 + 22 + func left a:_ = a 23 + 24 + func contains_by key (a:b) (p1:p2) = 25 + let [w, z] = sort [key p1, key p2], 26 + w <= a && a <= z && w <= b && b <= z 27 + 28 + proc main!() { 29 + let points = readlines 30 + |> it::map (parse (sep_by (char ',') integer)) 31 + |> collect 32 + dbg!('points(length points)) 33 + 34 + let edges = zip points [..tail points, first points] 35 + dbg!('edges(length edges)) 36 + 37 + # It has been observed that the shape is convex and without holes or interior crossings 38 + # 39 + # So we can make a series of rectangles that represent the illegal area by sending beams 40 + # from each edge 41 + let verticals = sort_by (asc <| (x << left)) <| filter is_vertical edges 42 + dbg!('verticals(length verticals)) 43 + 44 + let horizontals = sort_by (asc <| (y << left)) <| filter is_horizontal edges 45 + dbg!('horizontals(length horizontals)) 46 + 47 + let xs = map (x << left) verticals 48 + dbg!('xs(length xs)) 49 + 50 + let ys = map (y << left) horizontals 51 + dbg!('ys(length ys)) 52 + 53 + let [min_x, .._, max_x] = xs 54 + let [min_y, .._, max_y] = ys 55 + 56 + let illegal = [] 57 + 58 + dbg!(min_x:max_x) 59 + dbg!(min_y:max_y) 60 + 61 + let x_ranges = zip xs (tail xs) 62 + let mut i = 0 63 + while i < length x_ranges { 64 + let x1:x2 and range = x_ranges.i 65 + i += 1 66 + if x1 == x2 { continue unit } 67 + let [y1, .._, y2] = horizontals 68 + |> filter (contains_by x range) 69 + |> map (y << left) 70 + |> sort 71 + push!(illegal, [x1, min_y]:[x2, y1]) 72 + push!(illegal, [x1, y2]:[x2, max_y]) 73 + } 74 + dbg!('illegal(length illegal)) 75 + 76 + let y_ranges = zip ys (tail ys) 77 + let mut i = 0 78 + while i < length y_ranges { 79 + let y1:y2 and range = y_ranges.i 80 + i += 1 81 + if y1 == y2 { continue unit } 82 + let [x1, .._, x2] = verticals 83 + |> filter (contains_by y range) 84 + |> map (x << left) 85 + |> sort 86 + push!(illegal, [min_x, y1]:[x1, y2]) 87 + push!(illegal, [x2, y1]:[max_x, y2]) 88 + } 89 + dbg!('illegal(length illegal)) 90 + 91 + # Then we just run standard collision of the area boxes with those 92 + let mut best = 0 93 + let mut i = 0 94 + let len = length points 95 + while i < len { 96 + let mut j = i + 1 97 + while j < len { 98 + let a = points.i 99 + let b = points.j 100 + let candidate = area a b 101 + if candidate > best && !(any (collide (a:b)) illegal) { 102 + best = candidate 103 + } 104 + j += 1 105 + } 106 + i += 1 107 + } 108 + dbg!(best) 109 + }