Advent of Code solutions

stdlib updates

+15 -34
+1 -1
2021/18/p1.tri
··· 62 62 proc main!() { 63 63 readlines 64 64 |> it::map (parse snailfish_number) 65 - |> it::reduce (fn l r. snailfish_reduce (l:r)) 65 + |> it::reduce (fn r l. snailfish_reduce (l:r)) 66 66 |> magnitude 67 67 |> dbg 68 68 }
+2 -2
2023/1/p1.tri
··· 1 1 import "trilogy:io" use readlines, println 2 2 import "trilogy:string" use chars 3 3 import "trilogy:array" use filter, map, fold, collect 4 - import "trilogy:parsec" use parse, integer 4 + import "trilogy:number" use parse_from_digits 5 5 6 6 func is_digit '0' = true 7 7 func is_digit '1' = true ··· 24 24 chars 25 25 >> filter is_digit 26 26 >> combine 27 - >> parse integer 27 + >> parse_from_digits 28 28 ) 29 29 |> fold (+) 0 30 30 println!("${total}")
+2 -2
2023/1/p2.tri
··· 2 2 import "trilogy:debug" use dbg 3 3 import "trilogy:iterator" use map, fold 4 4 import "trilogy:string" use skip 5 - import "trilogy:parsec" use parse, integer 5 + import "trilogy:number" use parse_from_digits 6 6 7 7 func combine [a] = "${a}${a}" 8 8 func combine [a, .._, b] = "${a}${b}" ··· 30 30 let total = readlines 31 31 |> map digits 32 32 |> map combine 33 - |> map (parse integer) 33 + |> map parse_from_digits 34 34 |> fold (+) 0 35 35 dbg!(total) 36 36 }
+2 -3
2023/2/p2.tri
··· 3 3 import "trilogy:compare" use max 4 4 import "trilogy:array" use fold, flatten 5 5 import "trilogy:iterator" as it 6 + import "trilogy:record" use update 6 7 import "trilogy:parsec" use parse, apply, string, integer, char, sep_by_1, prefixed_by, choice 7 8 8 9 slot init = {| "red" => 0, "green" => 0, "blue" => 0 |} 9 10 10 - func max_color {| "red" => best, ..cs |} n:"red" = {| "red" => max n best, ..cs |} 11 - func max_color {| "green" => best, ..cs |} n:"green" = {| "green" => max n best, ..cs |} 12 - func max_color {| "blue" => best, ..cs |} n:"blue" = {| "blue" => max n best, ..cs |} 11 + func max_color n:col rec = update (max n) 0 col rec 13 12 14 13 func power {| "red" => r, "green" => g, "blue" => b |} = r * g * b 15 14
+1 -1
2025/1/p2.tri
··· 10 10 return if dir == 'R' then amt else -amt 11 11 } 12 12 13 - func rotate pos amt = { 13 + func rotate amt pos = { 14 14 let full = abs amt // 100 15 15 let rotated = pos + amt % 100 16 16 let crossed = rotated < 0 || rotated > 99
+1 -3
2025/10/p1.tri
··· 11 11 func target_state '.' = false 12 12 func target_state '#' = true 13 13 14 - func set_bit bb index = set_at index bb 15 - 16 14 proc machine!() { 17 15 let target = bits::from_array 18 16 <| map target_state ··· 21 19 <| many_1 22 20 <| char_of ".#" 23 21 apply <| char ' ' 24 - let buttons = map (fold set_bit (target ^ target)) 22 + let buttons = map (fold set_at (target ^ target)) 25 23 <| apply 26 24 <| sep_by_1 (char ' ') 27 25 <| between (char '(') (char ')')
+1 -3
2025/10/p2.tri
··· 12 12 func target_state '.' = false 13 13 func target_state '#' = true 14 14 15 - func set_bit bb index = bb | (0bb1 ~~> index) 16 - 17 - func button_bits len button = fold set_bit (bits::init_zero len) button 15 + func button_bits len button = fold set_at (bits::init_zero len) button 18 16 19 17 proc machine!() { 20 18 let target = bits::from_array
+2 -2
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 4 + import "trilogy:number" use from_digit, from_digits_base 5 5 import "trilogy:compare" use max 6 6 import "trilogy:iterator" as it 7 7 import "trilogy:array" as arr use take, skip ··· 26 26 >> chars 27 27 >> arr::map from_digit 28 28 >> joltage 29 - >> arr::fold (fn a b. a * 10 + b) 0 29 + >> from_digits_base 10 30 30 ) 31 31 |> it::sum 32 32 dbg!(total)
+1 -1
2025/5/p2.tri
··· 19 19 let fresh:_ = readall!() 20 20 |> parse input 21 21 |> sort_by (asc <| fn a. a.'left) 22 - |> fold (fn (fresh:index) (low:high). fresh + ((max index (high + 1)) - (max index low)):(max index (high + 1))) (0:0) 22 + |> fold (fn (low:high) (fresh:index). fresh + ((max index (high + 1)) - (max index low)):(max index (high + 1))) (0:0) 23 23 dbg!(fresh) 24 24 }
+2 -1
2025/7/p2.tri
··· 4 4 import "trilogy:number" use im 5 5 import "trilogy:compare" use max 6 6 import "trilogy:array" use map, reduce, length 7 + import "trilogy:record" use update 7 8 import "trilogy:set" use push, contains, collect 8 9 import "trilogy:iterator" as it 9 10 ··· 39 40 beams = beams 40 41 |> it::from 41 42 |> it::flat_map (fn beam:val. if contains beam splitters then it::from [beam + 1 + 1i: val, beam - 1 + 1i: val] else it::of (beam + 1i:val)) 42 - |> it::fold (fn rec pos:val. {| ..rec, pos => val + with rec.pos { when 'mia cancel 0 } |}) {||} 43 + |> it::fold (fn pos:val rec. update ((+) val) 0 pos rec) {||} 43 44 i += 1 44 45 } 45 46 dbg!(reduce (+) [val for _:val in beams])
-15
2025/9/p2.tri
··· 29 29 let points = readlines 30 30 |> it::map (parse (sep_by (char ',') integer)) 31 31 |> collect 32 - dbg!('points(length points)) 33 - 34 32 let edges = zip points [..tail points, first points] 35 - dbg!('edges(length edges)) 36 33 37 34 # It has been observed that the shape is convex and without holes or interior crossings 38 35 # 39 36 # So we can make a series of rectangles that represent the illegal area by sending beams 40 37 # from each edge 41 38 let verticals = sort_by (asc <| (x << left)) <| filter is_vertical edges 42 - dbg!('verticals(length verticals)) 43 - 44 39 let horizontals = sort_by (asc <| (y << left)) <| filter is_horizontal edges 45 - dbg!('horizontals(length horizontals)) 46 - 47 40 let xs = map (x << left) verticals 48 - dbg!('xs(length xs)) 49 - 50 41 let ys = map (y << left) horizontals 51 - dbg!('ys(length ys)) 52 42 53 43 let [min_x, .._, max_x] = xs 54 44 let [min_y, .._, max_y] = ys 55 45 56 46 let illegal = [] 57 47 58 - dbg!(min_x:max_x) 59 - dbg!(min_y:max_y) 60 - 61 48 let y_ranges = zip ys (tail ys) 62 49 let mut i = 0 63 50 while i < length y_ranges { ··· 70 57 push!(illegal, [min_x, y1]:[x1, y2]) 71 58 push!(illegal, [x2, y1]:[max_x, y2]) 72 59 } 73 - dbg!('illegal(length illegal)) 74 60 75 61 let x_ranges = zip xs (tail xs) 76 62 let mut i = 0 ··· 84 70 push!(illegal, [x1, min_y]:[x2, y1]) 85 71 push!(illegal, [x1, y2]:[x2, max_y]) 86 72 } 87 - dbg!('illegal(length illegal)) 88 73 89 74 # Then we just run standard collision of the area boxes with those 90 75 let mut best = 0