Advent of Code solutions

marginally faster but still too slow

+40 -30
+40 -30
2025/10/p2.tri
··· 1 1 import "trilogy:io" use readlines 2 2 import "trilogy:debug" use dbg 3 - import "trilogy:core" use to_array, length 4 - import "trilogy:bits" as bits 5 - import "trilogy:set" use contains, union, collect, difference 6 - import "trilogy:compare" use min 3 + import "trilogy:compare" use min, max, asc 7 4 import "trilogy:parsec" use parse, apply, between, many_1, char_of, char, integer, sep_by_1 8 - import "trilogy:array" use map, fold, filter, reverse 5 + import "trilogy:array" use map, fold, filter, reverse, sort_by, reduce, all, flatten 9 6 import "trilogy:iterator" as it 7 + import "trilogy:set" as set use contains 10 8 11 9 proc machine!() { 12 10 let _target = apply ··· 19 17 <| between (char '(') (char ')') 20 18 <| sep_by_1 (char ',') integer 21 19 apply <| char ' ' 22 - let joltage = fold (fn acc n. n:acc) unit 23 - <| reverse 24 - <| apply 20 + let joltage = apply 25 21 <| between (char '{') (char '}') 26 22 <| sep_by_1 (char ',') integer 27 23 return joltage:buttons 28 24 } 29 25 30 - func update_state n:rest 0 = n + 1 : rest 31 - func update_state n:rest i = n : update_state rest (i - 1) 26 + func limit_within target button = reduce min <| map ((.) target) button 32 27 33 - func press_button state [] = state 34 - func press_button state [n, ..rest] = press_button (update_state state n) rest 28 + func sub_at 0 n [m, ..arr] = [m - n, ..arr] 29 + func sub_at i n [m, ..arr] = [m, ..sub_at (i - 1) n arr] 35 30 36 - func below unit unit = true 37 - func below a:ra b:rb = if b <= a then below ra rb else false 31 + func apply_button _ [] target = target 32 + func apply_button n [i, ..rest] target = apply_button n rest <| sub_at i n <| target 38 33 39 - func zero unit = unit 40 - func zero _ : rest = 0 : zero rest 34 + func covers target coverage = 35 + it::from target 36 + |> it::enumerate 37 + |> it::all (fn i:v. v == 0 || contains i coverage) 38 + 39 + proc solvable!(remaining, target, all_buttons and [button, ..buttons]) { 40 + if remaining < reduce max target || !(covers target <| set::collect <| it::from <| flatten all_buttons) { 41 + return false 42 + } 43 + let limit = min remaining <| limit_within target button 44 + return it::range limit 0 45 + |> it::any (fn times. 46 + let new_target = apply_button times button target, 47 + if all ((==) 0) new_target 48 + then true 49 + else buttons != [] && solvable!(remaining - times, new_target, prioritize new_target buttons) 50 + ) 51 + } 52 + 53 + func range_size target buttons button = 54 + let others = set::collect <| it::from <| flatten <| filter ((!=) button) buttons, 55 + let upper = limit_within target button, 56 + let lower = if covers target others then 0 else upper, 57 + upper - lower 58 + 59 + func prioritize target buttons = 60 + sort_by (asc <| range_size target buttons) buttons 41 61 42 62 proc solve!(target:buttons) { 43 - let mut visited = [| zero target |] 44 - let mut states = [| zero target |] 45 - let mut i = 0 46 - while !(contains target states) { 47 - dbg!(i) 48 - let new_states = states 49 - |> it::from 50 - |> it::flat_map (fn state. it::from <| map (press_button state) buttons) 51 - |> it::filter (below target) 52 - |> collect 53 - states = difference new_states visited 54 - visited union= new_states 63 + let mut i = reduce max target 64 + let buttons_ordered = prioritize target buttons 65 + while !solvable!(i, target, buttons_ordered) { 55 66 i += 1 67 + dbg!('try(i)) 56 68 } 57 69 return i 58 70 } ··· 60 72 proc main!() { 61 73 readlines 62 74 |> it::map (parse machine) 63 - |> it::map dbg 64 75 |> it::map solve 65 - |> it::map dbg 66 76 |> it::fold (+) 0 67 77 |> dbg 68 78 }