Advent of Code solutions

2021 day 21

+111
+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 + }