Advent of Code solutions

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

+227
+55
2021/20/p1.tri
··· 1 + import "trilogy:debug" use dbg 2 + import "trilogy:io" use readline, readall 3 + import "trilogy:parsec" use parse, apply, repeat, char_of, per_line, many_1 4 + import "trilogy:array" as array use map 5 + import "trilogy:bits" as bits 6 + import "trilogy:number" as number 7 + import "trilogy:core" use length 8 + import "trilogy:iterator" as it 9 + 10 + func infinite_image true cb = with cb!() { when 'outside resume 0bb111 } 11 + func infinite_image false cb = with cb!() { when 'outside resume 0bb000 } 12 + 13 + proc read_at!(image, row, col) { 14 + let outside = yield 'outside 15 + let unpadded = with image.row { when 'mia { return outside } } 16 + let padded = bits::concat outside <| bits::concat unpadded outside 17 + return (padded <~ (col + 3)) ~>> (length padded - 3) 18 + } 19 + 20 + func read_around image row col = { 21 + let a = read_at!(image, row - 1, col - 1) 22 + let b = read_at!(image, row, col - 1) 23 + let c = read_at!(image, row + 1, col - 1) 24 + number::from (a | b ~~> 3 | c ~~> 6) 25 + } 26 + 27 + func enhance_row enhancement image row = 28 + it::range (-1) (length (image.0)) 29 + |> it::map (read_around image row) 30 + |> it::map ((.) enhancement) 31 + |> bits::collect 32 + 33 + func enhance outside enhancement image = { 34 + using infinite_image outside 35 + let enhanced = it::range (-1) (length image) 36 + |> it::map (enhance_row enhancement image) 37 + |> array::collect 38 + let new_outside = enhancement.(read_around image (-3) (-3)) 39 + new_outside:enhanced 40 + } 41 + 42 + proc main!() { 43 + let enhancement = readline!() 44 + |> parse (repeat 512 (char_of ".#")) 45 + |> map ((==) '#') 46 + |> bits::from_array 47 + let "\n" = readline!() 48 + let image = readall!() 49 + |> parse (per_line (many_1 (char_of ".#"))) 50 + |> map (bits::from_array << map ((==) '#')) 51 + let outside:enhanced = enhance false enhancement image 52 + let _:enhanced_2 = enhance outside enhancement enhanced 53 + dbg!(array::reduce (+) <| map bits::pop_count enhanced_2) 54 + exit 0 55 + }
+61
2021/20/p2.tri
··· 1 + import "trilogy:debug" use dbg 2 + import "trilogy:io" use readline, readall 3 + import "trilogy:parsec" use parse, apply, repeat, char_of, per_line, many_1 4 + import "trilogy:array" as array use map 5 + import "trilogy:bits" as bits 6 + import "trilogy:number" as number 7 + import "trilogy:core" use length 8 + import "trilogy:iterator" as it 9 + 10 + func infinite_image true cb = with cb!() { when 'outside resume 0bb111 } 11 + func infinite_image false cb = with cb!() { when 'outside resume 0bb000 } 12 + 13 + proc read_at!(image, row, col) { 14 + let outside = yield 'outside 15 + let unpadded = with image.row { when 'mia { return outside } } 16 + let padded = bits::concat outside <| bits::concat unpadded outside 17 + return (padded <~ (col + 3)) ~>> (length padded - 3) 18 + } 19 + 20 + func read_around image row col = { 21 + let a = read_at!(image, row - 1, col - 1) 22 + let b = read_at!(image, row, col - 1) 23 + let c = read_at!(image, row + 1, col - 1) 24 + number::from (a | b ~~> 3 | c ~~> 6) 25 + } 26 + 27 + func enhance_row enhancement image row = 28 + it::range (-1) (length (image.0)) 29 + |> it::map (read_around image row) 30 + |> it::map ((.) enhancement) 31 + |> bits::collect 32 + 33 + func enhance outside enhancement image = { 34 + using infinite_image outside 35 + let enhanced = it::range (-1) (length image) 36 + |> it::map (enhance_row enhancement image) 37 + |> array::collect 38 + let new_outside = enhancement.(read_around image (-3) (-3)) 39 + new_outside:enhanced 40 + } 41 + 42 + proc main!() { 43 + let enhancement = readline!() 44 + |> parse (repeat 512 (char_of ".#")) 45 + |> map ((==) '#') 46 + |> bits::from_array 47 + let "\n" = readline!() 48 + let mut image = readall!() 49 + |> parse (per_line (many_1 (char_of ".#"))) 50 + |> map (bits::from_array << map ((==) '#')) 51 + let mut outside = false 52 + let mut i = 0 53 + while i < 50 { 54 + let outside_2:image_2 = enhance outside enhancement image 55 + outside = outside_2 56 + image = image_2 57 + i += 1 58 + } 59 + dbg!(array::reduce (+) <| map bits::pop_count image) 60 + exit 0 61 + }
+35
2021/21/p1.tri
··· 1 + import "trilogy:debug" use dbg 2 + import "trilogy:io" use readline 3 + import "trilogy:parsec" use parse, prefixed_by, string, integer 4 + 5 + proc main!() { 6 + let mut p1_position = (parse (prefixed_by (string "Player 1 starting position: ") integer) readline!()) - 1 7 + let mut p2_position = (parse (prefixed_by (string "Player 2 starting position: ") integer) readline!()) - 1 8 + let mut p1_score = 0 9 + let mut p2_score = 0 10 + let mut turn = true 11 + let mut rolls = 0 12 + let mut die = 1 13 + let roll = do() { 14 + let output = die 15 + die += 1 16 + rolls += 1 17 + if (die > 100) { 18 + die = 1 19 + } 20 + return output 21 + } 22 + while p1_score < 1000 && p2_score < 1000 { 23 + let distance = roll!() + roll!() + roll!() 24 + if turn { 25 + p1_position = (p1_position + distance) % 10 26 + p1_score += p1_position + 1 27 + } else { 28 + p2_position = (p2_position + distance) % 10 29 + p2_score += p2_position + 1 30 + } 31 + turn = !turn 32 + } 33 + dbg!(rolls * if p1_score >= 1000 { p2_score } else { p1_score }) 34 + exit 0 35 + }
+76
2021/21/p2.tri
··· 1 + import "trilogy:debug" use dbg 2 + import "trilogy:io" use readline 3 + import "trilogy:parsec" use parse, prefixed_by, string, integer 4 + import "trilogy:array" use push, pop 5 + import "trilogy:compare" use max, min, asc 6 + import "trilogy:heap" use heap 7 + 8 + proc dirac!(cb) { 9 + with cb!() { 10 + when 'roll { 11 + resume 1 12 + resume 2 13 + resume 3 14 + cancel unit 15 + } 16 + } 17 + } 18 + 19 + proc roll!() { 20 + yield 'roll 21 + } 22 + 23 + func next_player (x:y:_:_:_) = min x y 24 + 25 + func cmp (ax:ay:_:_:_) (bx:by:_:_:_) = { 26 + let amin = min ax ay 27 + let amax = max ax ay 28 + let bmin = min bx by 29 + let bmax = max bx by 30 + if amin == bmin then amax <= bmax else amin <= bmin 31 + } 32 + 33 + func asc_eq f a b = f a <= f b 34 + 35 + proc main!() { 36 + let p1_start = (parse (prefixed_by (string "Player 1 starting position: ") integer) readline!()) - 1 37 + let p2_start = (parse (prefixed_by (string "Player 2 starting position: ") integer) readline!()) - 1 38 + 39 + let states = {| 0:0:p1_start:p2_start:true => 1 |} 40 + let min_heap = heap cmp 41 + let queue = [0:0:p1_start:p2_start:true] 42 + 43 + let mut p1_wins = 0 44 + let mut p2_wins = 0 45 + while queue != [] { 46 + let key = min_heap::pop!(queue) 47 + let dups = states.key 48 + using dirac 49 + let distance = roll!() + roll!() + roll!() 50 + let mut p1_score:mut p2_score:mut p1_position:mut p2_position:turn = key 51 + if turn { 52 + p1_position = (p1_position + distance) % 10 53 + p1_score += p1_position + 1 54 + if p1_score >= 21 { 55 + p1_wins += dups 56 + return unit 57 + } 58 + } else { 59 + p2_position = (p2_position + distance) % 10 60 + p2_score += p2_position + 1 61 + if p2_score >= 21 { 62 + p2_wins += dups 63 + return unit 64 + } 65 + } 66 + let new_key = p1_score:p2_score:p1_position:p2_position:!turn 67 + with { states.new_key = dups + states.new_key } { 68 + when 'mia { 69 + min_heap::push!(queue, new_key) 70 + become 0 71 + } 72 + } 73 + } 74 + dbg!(max p1_wins p2_wins) 75 + exit 0 76 + }