diff options
Diffstat (limited to 'codingquest2024/src/day5/solution.gleam')
-rw-r--r-- | codingquest2024/src/day5/solution.gleam | 67 |
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) }) +} |