my solutions to advent of code
aoc
advent-of-code
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}