aboutsummaryrefslogtreecommitdiff
path: root/codingquest2024/src/day5/solution.gleam
diff options
context:
space:
mode:
Diffstat (limited to 'codingquest2024/src/day5/solution.gleam')
-rw-r--r--codingquest2024/src/day5/solution.gleam67
1 files changed, 67 insertions, 0 deletions
diff --git a/codingquest2024/src/day5/solution.gleam b/codingquest2024/src/day5/solution.gleam
new file mode 100644
index 0000000..6c10693
--- /dev/null
+++ b/codingquest2024/src/day5/solution.gleam
@@ -0,0 +1,67 @@
+import gleam/dict.{type Dict}
+import gleam/io
+import gleam/int
+import gleam/list
+import gleam/regex
+import gleam/result
+import gleam/string
+import simplifile
+
+type Atlas =
+ Dict(String, Dict(String, Int))
+
+pub fn main() {
+ let assert Ok(data) = simplifile.read(from: "./src/day5/data.txt")
+
+ let assert [table, routes] = string.split(data, "\n\n")
+ let assert [header, ..rows] = string.split(table, "\n")
+
+ let dests =
+ header
+ |> string.trim()
+ |> split_on_many_spaces
+
+ let atlas = build_atlas(rows, dests)
+
+ routes
+ |> string.split("\n")
+ |> list.fold(0, fn(acc, route) { acc + find_total_distance(route, atlas) })
+ |> io.debug
+}
+
+fn split_on_many_spaces(str) {
+ let assert Ok(re_spaces) = regex.from_string("\\s+")
+ regex.split(re_spaces, str)
+}
+
+fn build_atlas(rows, dests) {
+ rows
+ |> list.map(split_on_many_spaces)
+ |> list.fold(dict.new(), fn(acc, row) {
+ let assert [from, ..raw_dists] = row
+ let assert Ok(dists) = list.try_map(raw_dists, int.parse)
+ let to_dict =
+ dests
+ |> list.zip(dists)
+ |> dict.from_list()
+
+ dict.insert(acc, from, to_dict)
+ })
+}
+
+fn dist_between(leg: #(String, String), dict: Atlas) -> Int {
+ let assert Ok(dist) =
+ dict
+ |> dict.get(leg.0)
+ |> result.try(dict.get(_, leg.1))
+
+ dist
+}
+
+fn find_total_distance(row: String, atlas: Atlas) {
+ let assert [_, route] = string.split(row, ": ")
+
+ string.split(route, " -> ")
+ |> list.window_by_2
+ |> list.fold(0, fn(acc, leg) { acc + dist_between(leg, atlas) })
+}