Advent of Code solutions
1import "trilogy:io" use readall
2import "trilogy:debug" use dbg
3import "trilogy:core" use length
4import "trilogy:parsec" use parse, hex_integer, repeat, apply, any, many_1, followed_by, eof
5import "trilogy:bits" as bits
6import "trilogy:string" use chomp
7import "trilogy:compare" use min, max
8import "trilogy:array" use reduce
9
10func from_binary [] = 0
11func from_binary [..rest, true] = (from_binary rest * 2) + 1
12func from_binary [..rest, false] = from_binary rest * 2
13
14proc literal!() {
15 let is_continued = apply any
16 let seg = apply <| repeat 4 any
17 if !is_continued { return seg }
18 let rest = apply literal
19 return [..seg, ..rest]
20}
21
22proc operator!() {
23 let length_type = apply any
24 if length_type == false {
25 let sublength = from_binary <| apply <| repeat 15 any
26 let content_bits = bits::from_array <| apply <| repeat sublength any
27 return parse (followed_by eof <| many_1 packet) content_bits
28 } else {
29 let subpacket_count = from_binary <| apply <| repeat 11 any
30 return apply <| repeat subpacket_count packet
31 }
32}
33
34proc packet!() {
35 let version = from_binary <| apply <| repeat 3 any
36 let type_id = from_binary <| apply <| repeat 3 any
37 return match type_id {
38 case 0 then reduce (+) <| apply operator
39 case 1 then reduce (*) <| apply operator
40 case 2 then reduce min <| apply operator
41 case 3 then reduce max <| apply operator
42 case 4 then from_binary <| apply literal
43 case 5 then match apply operator { case [a, b] if a > b then 1 else 0 }
44 case 6 then match apply operator { case [a, b] if a < b then 1 else 0 }
45 case 7 then match apply operator { case [a, b] if a == b then 1 else 0 }
46 }
47}
48
49proc main!() {
50 let hex_string = chomp readall!()
51 let binary_input = bits::from <| parse hex_integer hex_string
52 let real_len = length hex_string * 4
53 let real_bits = binary_input <<~ (length binary_input - real_len)
54 dbg!(parse packet real_bits)
55}