my solutions to advent of code
aoc advent-of-code
at main 3.3 kB view raw
1import gleam/dict 2import gleam/int 3import gleam/io 4import gleam/list 5import gleam/result 6import gleam/string 7import simplifile as file 8 9type Part2Dict = 10 dict.Dict(Int, Int) 11 12type Align { 13 Left 14 Right 15} 16 17type Operation { 18 Sum 19 Mul 20} 21 22type Part2Line { 23 Part2Line(align: Align, op: Operation, numbers: List(String)) 24} 25 26pub fn main() { 27 let assert Ok(input) = file.read(from: "../input.txt") 28 as "Input file not found" 29 let input = input |> string.trim 30 let input_pt_1 = 31 list.fold(list.range(1, 10), input, fn(acc, _) { 32 acc |> string.replace(" ", " ") 33 }) 34 35 input_pt_1 36 |> string.split("\n") 37 |> list.map(fn(i) { string.trim(i) |> string.split(" ") }) 38 |> list.transpose 39 |> list.map(fn(i) { 40 let i = list.reverse(i) 41 let assert Ok(s) = list.first(i) 42 let i = 43 list.drop(i, 1) |> list.map(fn(i) { int.parse(i) |> result.unwrap(0) }) 44 let r = case s { 45 "+" -> int.sum(i) 46 "*" -> list.reduce(i, int.multiply) |> result.unwrap(0) 47 _ -> panic as "invalid" 48 } 49 r 50 }) 51 |> int.sum 52 |> int.to_string 53 |> io.println 54 55 let lines = 56 input 57 |> string.split("\n") 58 |> list.reverse 59 let assert Ok(last_line) = list.first(lines) 60 let #(_, bounds) = 61 { last_line <> " *" } 62 |> string.to_graphemes 63 |> list.index_fold(#(0, list.new()), fn(acc, char, i) { 64 let #(bound_start, bounds) = acc 65 case char { 66 "*" | "+" if i > 0 -> #(i, list.append([#(bound_start, i - 1)], bounds)) 67 _ -> acc 68 } 69 }) 70 bounds 71 |> list.index_fold(dict.new(), fn(d, bound, i) { 72 let numbers = 73 list.map(lines, fn(line) { 74 string.slice(line, bound.0, bound.1 - bound.0) 75 }) 76 let align = 77 numbers 78 |> list.drop(1) 79 |> list.fold_until(Left, fn(res, number) { 80 case 81 string.trim(number) == number, 82 string.trim_start(number) == number 83 { 84 True, _ -> list.Continue(res) 85 _, True -> list.Stop(Left) 86 _, _ -> list.Stop(Right) 87 } 88 }) 89 let assert Ok(sign) = list.first(numbers) 90 let sign = case string.trim(sign) { 91 "*" -> Mul 92 "+" -> Sum 93 _ -> panic as sign 94 } 95 dict.insert( 96 d, 97 i, 98 Part2Line( 99 align, 100 sign, 101 numbers |> list.drop(1) |> list.map(string.trim) |> list.reverse, 102 ), 103 ) 104 }) 105 |> dict.to_list 106 |> list.map(fn(i) { i.1 }) 107 |> list.map(fn(line) { 108 let d: Part2Dict = dict.new() 109 let d = 110 line.numbers 111 |> list.fold(d, fn(d, number) { 112 let number_len = string.length(number) 113 string.to_graphemes(number) 114 |> list.index_fold(d, fn(d, digit, index) { 115 let assert Ok(digit) = digit |> int.parse 116 let pos = case line.align { 117 Right -> number_len - index 118 Left -> index 119 } 120 dict.insert( 121 d, 122 pos, 123 { dict.get(d, pos) |> result.unwrap(0) } * 10 + digit, 124 ) 125 }) 126 }) 127 let numbers = 128 dict.to_list(d) 129 |> list.map(fn(n) { n.1 }) 130 131 let r = case line.op { 132 Sum -> int.sum(numbers) 133 Mul -> list.reduce(numbers, int.multiply) |> result.unwrap(0) 134 } 135 r 136 }) 137 |> int.sum 138 |> int.to_string 139 |> io.println 140}