aboutsummaryrefslogtreecommitdiff
path: root/codingquest2024/src
diff options
context:
space:
mode:
Diffstat (limited to 'codingquest2024/src')
-rw-r--r--codingquest2024/src/codingquest2024.gleam5
-rw-r--r--codingquest2024/src/day1/solution.gleam55
-rw-r--r--codingquest2024/src/day2/solution.gleam66
-rw-r--r--codingquest2024/src/day3/solution.gleam50
-rw-r--r--codingquest2024/src/day4/solution.gleam49
-rw-r--r--codingquest2024/src/day5/solution.gleam67
-rw-r--r--codingquest2024/src/day6/solution.gleam86
-rw-r--r--codingquest2024/src/day7/solution.gleam73
-rw-r--r--codingquest2024/src/day8/solution.gleam26
-rw-r--r--codingquest2024/src/day9/input.txt203
-rw-r--r--codingquest2024/src/day9/solution.gleam0
-rw-r--r--codingquest2024/src/utilities/memo.gleam57
12 files changed, 737 insertions, 0 deletions
diff --git a/codingquest2024/src/codingquest2024.gleam b/codingquest2024/src/codingquest2024.gleam
new file mode 100644
index 0000000..5af4a2a
--- /dev/null
+++ b/codingquest2024/src/codingquest2024.gleam
@@ -0,0 +1,5 @@
+import gleam/io
+
+pub fn main() {
+ io.println("Hello from codingquest2024!")
+}
diff --git a/codingquest2024/src/day1/solution.gleam b/codingquest2024/src/day1/solution.gleam
new file mode 100644
index 0000000..abef2eb
--- /dev/null
+++ b/codingquest2024/src/day1/solution.gleam
@@ -0,0 +1,55 @@
+import gleam/dict.{type Dict}
+import gleam/int
+import gleam/io
+import gleam/list
+import gleam/option.{None, Some}
+import gleam/regex
+import gleam/result
+import gleam/string
+import simplifile
+
+pub type Adjustment {
+ Adjustment(spaceliner: String, value: Int)
+}
+
+pub fn main() {
+ let assert Ok(data) = simplifile.read(from: "./src/day1/data.txt")
+
+ let raw_adjustments = string.split(data, "\n")
+
+ raw_adjustments
+ |> collate_adjustments
+ |> dict.values
+ |> list.reduce(with: int.min)
+ |> result.unwrap(0)
+ |> int.to_string()
+ |> io.println()
+}
+
+fn parse_line(line: String) -> Adjustment {
+ let assert Ok(re) = regex.from_string("[\\s:]+")
+
+ let assert [spaceliner, kind, raw_value] =
+ regex.split(with: re, content: line)
+
+ let assert Ok(value) = int.parse(raw_value)
+ Adjustment(spaceliner, classify_adjustment(kind) * value)
+}
+
+fn classify_adjustment(name: String) -> Int {
+ case name {
+ "Seat" | "Meals" | "Luggage" | "Fee" | "Tax" -> 1
+ "Discount" | "Rebate" -> -1
+ _ -> panic as "unknown adjustment kind"
+ }
+}
+
+fn collate_adjustments(raw_adjustments: List(String)) -> Dict(String, Int) {
+ use acc, this <- list.fold(over: raw_adjustments, from: dict.new())
+ let adjustment = parse_line(this)
+ use maybe_v <- dict.update(in: acc, update: adjustment.spaceliner)
+ case maybe_v {
+ None -> adjustment.value
+ Some(v) -> v + adjustment.value
+ }
+}
diff --git a/codingquest2024/src/day2/solution.gleam b/codingquest2024/src/day2/solution.gleam
new file mode 100644
index 0000000..59f8d29
--- /dev/null
+++ b/codingquest2024/src/day2/solution.gleam
@@ -0,0 +1,66 @@
+import gleam/bit_array
+import gleam/list
+import gleam/int
+import gleam/io
+import gleam/string
+import simplifile
+
+pub type Location {
+ Internal
+ Passenger
+ Other
+}
+
+pub type Packet {
+ Packet(length: Int, endpoint: Location)
+}
+
+pub fn main() {
+ let assert Ok(data) = simplifile.read(from: "./src/day2/data.txt")
+
+ let #(internal_packets, passenger_packets) =
+ data
+ |> string.split("\n")
+ |> list.map(parse_packet)
+ |> list.partition(fn(p) { p.endpoint == Internal })
+
+ {
+ int.to_string(sum_packet_lengths(internal_packets))
+ <> "/"
+ <> int.to_string(sum_packet_lengths(passenger_packets))
+ }
+ |> io.println()
+}
+
+fn parse_packet(raw_packet: String) {
+ let assert Ok(<<
+ _:bytes-size(2),
+ length:int-size(16),
+ _:bytes-size(8),
+ source:bytes-size(4),
+ destination:bytes-size(4),
+ >>) = bit_array.base16_decode(raw_packet)
+
+ Packet(length, set_endpoint(source, destination))
+}
+
+fn set_endpoint(source: BitArray, dest: BitArray) -> Location {
+ case identify_location(source), identify_location(dest) {
+ Other, Internal | Internal, Other -> Internal
+ Other, Passenger | Passenger, Other -> Passenger
+ _, _ -> Other
+ }
+}
+
+fn identify_location(ip: BitArray) -> Location {
+ case ip {
+ <<192, 168, _, _>> -> Internal
+ <<10, 0, _, _>> -> Passenger
+ _ -> Other
+ }
+}
+
+fn sum_packet_lengths(packets: List(Packet)) -> Int {
+ use acc, p <- list.fold(packets, 0)
+ acc + p.length
+}
diff --git a/codingquest2024/src/day3/solution.gleam b/codingquest2024/src/day3/solution.gleam
new file mode 100644
index 0000000..6314060
--- /dev/null
+++ b/codingquest2024/src/day3/solution.gleam
@@ -0,0 +1,50 @@
+import gleam/bit_array
+import gleam/int
+import gleam/io
+import gleam/string
+import gleam/string_builder.{type StringBuilder}
+import simplifile
+
+pub fn main() {
+ let assert Ok(data) = simplifile.read(from: "./src/day3/data.txt")
+
+ data
+ |> string.split(" ")
+ |> build_flat_image(" ", string_builder.new())
+ |> bit_array.from_string()
+ |> print_next_slice()
+}
+
+fn build_flat_image(
+ nums: List(String),
+ pixel: String,
+ acc: StringBuilder,
+) -> String {
+ case nums {
+ [] -> string_builder.to_string(acc)
+ [h, ..t] -> {
+ let assert Ok(n) = int.parse(h)
+ let pixels = string.repeat(pixel, n)
+ build_flat_image(t, next_pixel(pixel), string_builder.append(acc, pixels))
+ }
+ }
+}
+
+fn print_next_slice(str: BitArray) -> Nil {
+ case str {
+ <<slice:bytes-size(100), rest:bytes>> -> {
+ let assert Ok(out) = bit_array.to_string(slice)
+ io.println(out)
+ print_next_slice(rest)
+ }
+ _ -> Nil
+ }
+}
+
+fn next_pixel(p: String) -> String {
+ case p {
+ " " -> "#"
+ "#" -> " "
+ _ -> panic
+ }
+}
diff --git a/codingquest2024/src/day4/solution.gleam b/codingquest2024/src/day4/solution.gleam
new file mode 100644
index 0000000..a03b2be
--- /dev/null
+++ b/codingquest2024/src/day4/solution.gleam
@@ -0,0 +1,49 @@
+import gleam/float
+import gleam/io
+import gleam/list
+import gleam/regex
+import gleam/result
+import gleam/string
+import simplifile
+
+pub type Star {
+ Star(name: String, x: Float, y: Float, z: Float)
+}
+
+pub fn main() {
+ let assert Ok(data) = simplifile.read(from: "./src/day4/data.txt")
+
+ let assert [_, ..stars] = string.split(data, "\n")
+
+ stars
+ |> list.map(parse_star_record)
+ |> list.combination_pairs()
+ |> list.map(star_distance)
+ |> list.reduce(float.min)
+ |> io.debug
+}
+
+fn parse_star_record(str: String) -> Star {
+ let assert Ok(re) = regex.from_string("\\s{2,}")
+
+ let assert [name, ..coords] = regex.split(with: re, content: str)
+ let assert [_, x, y, z] =
+ coords
+ |> list.map(float.parse)
+ |> result.values
+
+ Star(name, x, y, z)
+}
+
+fn star_distance(stars: #(Star, Star)) -> Float {
+ let #(star1, star2) = stars
+ let assert Ok(dist) =
+ float.square_root(
+ sq(star1.x -. star2.x) +. sq(star1.y -. star2.y) +. sq(star1.z -. star2.z),
+ )
+ dist
+}
+
+fn sq(x: Float) -> Float {
+ x *. x
+}
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) })
+}
diff --git a/codingquest2024/src/day6/solution.gleam b/codingquest2024/src/day6/solution.gleam
new file mode 100644
index 0000000..8a0319c
--- /dev/null
+++ b/codingquest2024/src/day6/solution.gleam
@@ -0,0 +1,86 @@
+import gleam/dict
+import gleam/io
+import gleam/list
+import gleam/regex
+import gleam/result
+import gleam/string
+import simplifile
+
+pub opaque type Location {
+ Location(row: Int, col: Int)
+}
+
+pub fn main() {
+ let assert Ok(data) = simplifile.read(from: "./src/day6/data.txt")
+ let assert ["Cipher key: " <> key, "Message: " <> raw_message] =
+ string.split(data, "\n")
+
+ let letter_to_location = make_cipher_grid(key)
+ let location_to_letter =
+ letter_to_location
+ |> dict.fold(dict.new(), fn(acc, k, v) { dict.insert(acc, v, k) })
+
+ raw_message
+ |> string.split(" ")
+ |> list.map(fn(s) {
+ s
+ |> string.to_graphemes
+ |> list.sized_chunk(2)
+ })
+ |> list.map(fn(s) {
+ s
+ |> decode_word(letter_to_location, location_to_letter)
+ |> string.concat()
+ })
+ |> string.join(" ")
+ |> io.println()
+}
+
+fn make_cipher_grid(key) {
+ let assert Ok(in_key) = regex.from_string("[" <> key <> "]")
+ let grid =
+ regex.split(in_key, "abcdefghiklmnopqrstuvwxyz")
+ |> string.concat
+ |> string.append(key, _)
+ |> string.to_graphemes
+ |> list.sized_chunk(5)
+
+ list.index_map(grid, fn(row, r) {
+ list.index_map(row, fn(cell, c) { #(cell, Location(r, c)) })
+ })
+ |> list.flatten
+ |> dict.from_list
+}
+
+fn decode_word(word: List(List(String)), to_loc, to_letter) {
+ case word {
+ [] -> []
+ [[a, b], ..rest] -> [
+ transform_pair(a, b, to_loc, to_letter),
+ ..decode_word(rest, to_loc, to_letter)
+ ]
+ _ -> panic as "bad playfair format"
+ }
+}
+
+fn transform_pair(a, b, to_loc, to_letter) {
+ let assert Ok(Location(r_a, c_a)) = dict.get(to_loc, a)
+ let assert Ok(Location(r_b, c_b)) = dict.get(to_loc, b)
+
+ case r_a == r_b, c_a == c_b {
+ True, _ -> [
+ dict.get(to_letter, Location(r_a, { c_a + 4 } % 5)),
+ dict.get(to_letter, Location(r_b, { c_b + 4 } % 5)),
+ ]
+ _, True -> [
+ dict.get(to_letter, Location({ r_a + 4 } % 5, c_a)),
+ dict.get(to_letter, Location({ r_b + 4 } % 5, c_b)),
+ ]
+ _, _ -> [
+ dict.get(to_letter, Location(r_a, c_b)),
+ dict.get(to_letter, Location(r_b, c_a)),
+ ]
+ }
+ |> result.values
+ |> string.concat
+}
diff --git a/codingquest2024/src/day7/solution.gleam b/codingquest2024/src/day7/solution.gleam
new file mode 100644
index 0000000..2ca7cbf
--- /dev/null
+++ b/codingquest2024/src/day7/solution.gleam
@@ -0,0 +1,73 @@
+import gleam/io
+import gleam/string
+import gleam/set.{type Set}
+import gleam/int
+import gleam/regex.{Match}
+import gleam/option.{Some}
+import simplifile
+
+pub opaque type Item {
+ File(name: String, size: Int)
+ Directory(name: String)
+}
+
+pub fn main() {
+ let assert Ok(data) = simplifile.read(from: "./src/day7/data.txt")
+ let lines = string.split(data, "\n")
+
+ mark_for_deletion(lines, 0, "", set.new())
+ |> io.debug()
+}
+
+fn mark_for_deletion(
+ lines: List(String),
+ deleted: Int,
+ current_folder: String,
+ deleted_folders: Set(String),
+) {
+ case lines {
+ [] -> deleted
+ ["Folder: " <> folder, ..rest] ->
+ mark_for_deletion(rest, deleted, folder, deleted_folders)
+ [file, ..rest] -> {
+ case
+ string.contains(file, "temporary")
+ || string.contains(file, "delete")
+ || set.contains(deleted_folders, current_folder)
+ {
+ True ->
+ case string.contains(file, "[FOLDER") {
+ True -> {
+ file
+ |> get_folder_number()
+ |> set.insert(deleted_folders, _)
+ |> mark_for_deletion(rest, deleted, current_folder, _)
+ }
+ False -> {
+ file
+ |> get_file_size()
+ |> int.add(deleted, _)
+ |> mark_for_deletion(rest, _, current_folder, deleted_folders)
+ }
+ }
+ False ->
+ mark_for_deletion(rest, deleted, current_folder, deleted_folders)
+ }
+ }
+ }
+}
+
+fn get_folder_number(file) {
+ let assert Ok(re) = regex.from_string("\\[FOLDER ([0-9]+)\\]")
+
+ let assert [Match(submatches: [Some(n)], ..)] = regex.scan(re, file)
+ n
+}
+
+fn get_file_size(file) {
+ let assert Ok(re) = regex.from_string("- .+ ([0-9]+)$")
+
+ let assert [Match(submatches: [Some(n)], ..)] = regex.scan(re, file)
+ let assert Ok(n) = int.parse(n)
+ n
+}
diff --git a/codingquest2024/src/day8/solution.gleam b/codingquest2024/src/day8/solution.gleam
new file mode 100644
index 0000000..cb4d907
--- /dev/null
+++ b/codingquest2024/src/day8/solution.gleam
@@ -0,0 +1,26 @@
+import gleam/io
+import gleam/int
+import gleam/list
+import utilities/memo
+
+const options = [40, 12, 2, 1]
+
+const distance = 856
+
+pub fn main() {
+ use cache <- memo.create()
+ solve(distance, cache)
+ |> io.debug
+}
+
+fn solve(target, cache) {
+ use <- memo.memoize(cache, target)
+ case target {
+ 0 -> 1
+ _ ->
+ options
+ |> list.filter(fn(n) { n <= target })
+ |> list.map(fn(n) { solve(target - n, cache) })
+ |> int.sum
+ }
+}
diff --git a/codingquest2024/src/day9/input.txt b/codingquest2024/src/day9/input.txt
new file mode 100644
index 0000000..1d30914
--- /dev/null
+++ b/codingquest2024/src/day9/input.txt
@@ -0,0 +1,203 @@
+#####################################################################################################
+......#.....#.#.......#.....#.....#.....#.#.................#...............#.............#.#.......#
+#.###.#.#.#.#.#.#####.#.#.#.#.###.###.#.#.#.#######.#######.#########.#####.#.#####.#####.#.#.###.#.#
+#.#.#...#.#.#.#.#...#...#.#...#.#.....#.#.#...#...#.#...#.....#.....#.#...#.#.#...#.#...#.#...#...#.#
+#.#.#####.#.#.#.#.#.#####.#####.#######.#.###.#.#.#.#.#.#.###.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#####
+#...#$..#.$...#$#.#.$.#.#$..#.$....$..#.$....$#.#.$.#.#$..#.$.#.#$..#.$.#..$..#.$...#$#.#.$.#.#$#...#
+###.#.#.#.#####.#.###.#.###.#.#######.#.###.###.#####.#####.###.#.###.###.###.#.#####.###.#.#.#.#.#.#
+#.#...#.#.......#...#...#...#.......#.#...#...#...#...#...#.....#.#.....#.#...#.#.....#...#...#.#.#.#
+#.#####.#########.#.#####.#.#########.###.#######.#.#.#.#.#######.###.#.###.###.#.#.#.#.#####.#.#.#.#
+#.....#.#.#.......#...#...#.#...#...#...#...#.....#.#.#.#.#.....#...#.#...#.#.#.#.#.#.#.....#.#...#.#
+#.###$#.#.$.###$####$.#.#$###.$.#.#$#.#.$##.#$####$.#.#$#.#.$.#.#$#.##$##.#$#.#.$##.#$####$.#.#$###.#
+#...#...#.......#...#.#.......#.#.#.#.#...#.#.#.....#...#...#.#...#.#...#.....#.#...#.....#.#...#.#.#
+###.#####.#####.#.#.#.#########.#.#.#.#.#.#.#.#########.#####.#####.#.#.#######.#.#.#.#.###.###.#.#.#
+#.#.#.....#...#.#.#...#...#...#.#.#.#.#.#.#.#.#...#...#...#.#...#...#.#.......#.#.#.#.#...#...#...#.#
+#.#.#.#####.#.###.###.#.#.#.#.#.#.#.###.###.#.#.#.#.#.###.#.###.#.###.#######.#.#.#.#.###.###.#####.#
+#.#.#$#...$.#..$#.#.$.#.#$#.#.$.#.#$#...$...#$..#.$.#..$#.#.$.#..$#...$.#.#$..#.$.#.#$#.#.$...#$....#
+#.#.#.#.#######.#.#.###.#.#.#####.#.#.#.#.#####.#######.#.#.#.#########.#.#.###.#.#.#.#.#.#.###.###.#
+#.#.#.#...#...#.#.#.....#.#.#.....#.#.#.#.....#.#.#...#.#...#...........#.#.....#.#.#...#.#...#.#...#
+#.#.#####.#.#.#.#.#########.#.#####.#.#.#####.#.#.#.#.#.#################.#######.#.###.#.###.#.###.#
+#.#.#.....#.#.....#.......#...#.....#.#.....#.#.#...#.#...#...#...#...#.#.........#.#...#...#.#...#.#
+#.#.#$####$.###$###.$####$####$.###$#.##$####$#.##$##.#$#.#.$.#.#$#.#.$.#.#$####$.###$####$.#.#$#.###
+#.#.#.#...#.#.......#.#...#...#...#...........#.....#.#...#.#...#...#.#.......#.#.....#...#...#.#...#
+#.#.#.###.#.#.#######.#.###.#.###.#######.#########.#.#.###.#########.#######.#.#######.#.#####.###.#
+#.#.#...#...#.....#...#.....#...#.......#.#...#.......#.#...#.......#...#...#...#.......#...#.....#.#
+#.#.#.#.#.#######.#.###########.###.###.#.#.#.#.#######.#.###.#.#######.#.#.###.#####.#####.#####.#.#
+#...#$#.#.$...#$..#.$.#..$#...$...#$#.#.$...#$#...$...#$#...$.#..$....$.#.#$#...$...#$#...$...#$#.#.#
+#.#####.###.#.#.###.#.#.#.#.#.###.#.#.#.#####.#####.#.#.###.#########.#.#.#.###.#.#.#.#.#####.#.#.#.#
+#.#.....#...#...#...#...#...#...#.#...#.#...#.......#.#...#...#...#...#...#...#...#...#.......#...#.#
+#.#.#.#.#.#######.#########.###.#.#####.#.###########.#.#.###.#.#.#.#########.#########.#######.###.#
+#.#.#.#.#.......#.#...#...#...#.#.......#...........#.#.#...#.#.#...#.......#...#...#...#.........#.#
+#.###$#.##$####$#.#.$.#.#$####$.###$####$.###$###.$##.#$###.$.#.#$###.$####$###.$.###$###.$####$###.#
+#.....#.#.....#.#...#.#.#...#.......#...#.......#...#...#.#.#...#.#...#...#.....#...#.#.....#.......#
+#######.###.#.#.#######.###.#.#####.#.#.###.#####.#.#####.#.###.###.###.#.#########.#.#.#####.#####.#
+#.#.....#...#.#.#.......#.#.#...#.....#.#...#...#.#.#.....#.#...#...#...#...........#.#.#...#.#.#...#
+#.#.#####.###.#.#.#######.#.###.#.#####.#####.#.###.#.#.###.#.###.###############.###.#.#.#.#.#.#.###
+#.#.#$....$...#$#...$....$#.#.$.#.#$..#.$...#$#...$.#.#$..#.$.#.#$#...$....$....$....$#.#.$...#$..#.#
+#.#.#.###.#.###.###.#######.#.#####.#.#####.#.#######.###.#.#.#.#.#.###########.#.#######.#####.###.#
+#...#.#.#.#...#.....#.......#.......#.#.......#.....#...#...#.#.#.#.......#.#...#.#.....#...#.......#
+#.###.#.#.###########.#####.#####.###.#####.###.###.###.#####.#.#.#######.#.#.###.#.###.#.#.#######.#
+#.#.#.#.#.#...#.....#...#...#...#...#.....#.#...#.#...#.#...#.#.#.......#...#.#.....#...#.#.#.....#.#
+#.#.#$#.#.$.#.#$###.$##.#$#.#.$.###$###.$.#.#$###.$.###$#.#.$.#.#$###.$####$#.##$####$###.$.#.#$#.#.#
+#.#.....#.#.#.#.#...#.#...#.#.#...#...#.#.#.#.....#.#.....#.#...#...#.......#.#...#.#...#.#.#.#...#.#
+#.#######.#.#.#.#.#.#.###.###.###.#.#.###.#.#####.#.#.#####.###.#.#.###.#####.#.#.#.###.###.#.#.###.#
+#...#.....#.#...#.#...#.#.....#.#...#...#.#.#.....#...#...#...#.#.#...#.#...#.#.#.#...#...#...#.#...#
+###.#.#####.#####.###.#.#######.#######.#.###.#########.#.#####.#.###.#.#.#.#.#.#.#.#.###.#.###.#.###
+#.#.#$....$...#$..#.$.#..$..#.$....$..#.$.#..$#...$.#.#$#.#.$...#$..#.$.#.#$#...$.#.#$..#.$.#..$#.#.#
+#.#.#.###.###.#.###.#.###.#.#.###.###.#.#.#.###.###.#.#.#.#.#######.#.###.#.#####.#.#####.#.#.###.#.#
+#.#.#...#...#.#.#...#.....#.#.#...#...#.#...#...#...#.#.#...#.....#.#.....#.......#.......#.#.#.....#
+#.#.#####.#.#.#.#.#########.#.#.#####.#.###.#.#####.#.#.#####.#####.###############.#########.#####.#
+#.#.....#.#.#.#.#.......#...#.#.....#.#...#...#...#...#...#.....#...#.....................#...#...#.#
+#.###$#.#.$##.#$###.$.###$###.$####$#.##$.###$#.#.$##.#$#.#.$##.#$###.$####$###.$####$###.$.#.#$#.#.#
+#.....#.#.....#...#.#.#...#.#.#...#.#...#.......#...#...#.#.#...#.#.....#.....#...#.....#.#.#.#.#.#.#
+#.#.###.#####.###.#.#.#.###.#.#.#.#.###.###########.###.#.###.###.#####.#.###.#####.###.#.#.###.#.###
+#.#...#.#...#.#...#.#.#.#.....#.#.#...#...#...#...#...#.#...#...#.....#.#...#.........#.#...#...#...#
+#.###.#.#.#.###.###.#.#.#####.#.#####.###.#.#.###.###.#.###.###.#####.###.###########.#.#####.#####.#
+#.#.#$..#.$....$#...$.#.#$..#.$....$#...$...#$....$...#$..#.$.#..$#.#.$...#$....$...#$#.#.$...#$....#
+#.#.#####.#######.###.#.#.#.#.#####.###.#########.#.#########.#.#.#.#######.#######.#.#.#.#####.###.#
+#.#.....#.....#.#.#.#...#.#.#.#.....#.#.#.......#.#.#...#...#.#.#.......#...#.....#.#.#.....#...#.#.#
+#.###.#.#####.#.#.#.#####.#.#.#.###.#.#.###.#####.#.#.#.#.#.#.#.#########.###.###.#.#########.###.#.#
+#.....#.......#.#.......#.#.#...#.#.#.#...#.#.....#.#.#.#.#.#.#...#.......#...#...#...........#.#...#
+#####$####$####$####$##.#$#.##$##.#$#.##$.#.#$####$.#.#$#.#.$.###$#.##$####$####$####$####$####$#.###
+#.........#...#.......#...#.#.....#.....#.#.#.#...#...#...#...#...#...#.....#...................#.#.#
+#.#.#####.#.#.#.#.#########.#.#.#####.###.#.#.#.#.###########.#.#####.#.#####.###.#############.#.#.#
+#.#...#.#...#.#.#.#...#.....#.#.....#.#...#...#.#.......#...#...#.....#...#...#.#.....#...#...#.#...#
+#####.#.#####.#.#.#.#.#.#########.#.#.#.#######.#######.#.#.#####.#######.#.###.#####.#.#.#.#.#####.#
+#....$#.#.$.#..$#.#.$...#$....$...#$#.#.$....$..#.$....$#.#.$....$#...$...#$....$...#$..#.$.#..$..#.#
+#.#####.#.#.#####.#.#####.###.#######.#.#.#######.#.#####.#########.#####.#####.#.#.#####.#.###.###.#
+#.#.......#.....#.#.#...#.#.#.....#...#.#.#.......#.......#.............#...#...#.#.....#.#...#...#.#
+#.###.#####.#####.#.###.#.#.#####.#.###.#.#.###.#.#########.###########.#####.#######.#.#.#.#####.#.#
+#...#...#.#.......#...#.#...#...#.....#.#.#...#.#.....#...#.#.........#.#.....#.......#.#.#.#.....#.#
+#.#.#$#.#.$####$####$.#.#$###.$.#.#$###.$.###$#.##$##.#$#.#.$.###$###.$.#.#$###.$####$#.#.$.#.#$#.#.#
+#.#.#...#...........#.#...#...#.#...#...#.#...#.....#...#.#.#.......#.#...#.....#...#...#...#.#...#.#
+#.#.#.###.#.#####.###.#.###.###.#####.#.#.#########.###.###.#######.###.###.###.#.#.#.#######.#.###.#
+#.#.#.....#.#...#.#...#...#...#.#.....#.#.#.....#...#...#...#...#.#.#...#...#.#.#.#.#.....#...#.#...#
+#.#.#########.#.###.#########.#.#.#####.#.#.###.#.#######.###.#.#.#.#.###.###.#.#.#.#######.#####.###
+#.#..$#...$...#$....$....$#...$.#.#$..#.$...#$..#.$....$..#.$.#..$#.#.$.#..$#...$.#..$....$....$#...#
+#####.#.#############.###.#.###.#.#.#.#.#####.###.#.#########.###.#.###.#.#.#.###.#######.#.###.###.#
+#.....#.#...#.........#.#.#...#.#...#.#...#...#...#.....#.....#...#...#.#.#.#.#.#.#...#...#.#.....#.#
+#.#.###.#.#.#.#########.#.#.#.#.#####.###.#.###.#######.#.###########.#.###.#.#.#.###.#.#####.#####.#
+#.#.#.....#...#.........#.#.#.#.......#...#.#.........#.#...#.........#.....#...#...#.#.#.....#...#.#
+#.###$####$####$####$##.#$###.$####$####$##.#$####$##.#$###.$.###$####$##.#$####$.#.#$#.#.$####$#.#.#
+#.....#.......#.#.....#.#.....#.....#.......#.#.......#...#.#.....#.#.....#.....#.#.#...#.#...#.#...#
+#######.#####.#.#.###.#####.#####.###.#######.#.#########.#.#####.#.#.#####.###.#.#.#.###.#.#.#.#####
+#...#...#...#.#.#...#.......#...#.#...#.......#...........#.....#.#...#.....#.#.#.#.#...#.#.#.#...#.#
+#.#.#.###.###.#.###.#########.#.###.#########.#############.#.#.#.#.###.#####.#.#.#.###.#.#.#.###.#.#
+#.#..$#...$...#$#...$.#..$#...$...#$#...$...#$....$.#..$..#.$.#.#$#.#.$.#..$#...$.#.#$#.#.$.#..$..#.#
+#.#####.#.#.###.#.#####.#.#.#####.#.#.#####.#######.#.###.###.#.#.###.###.#.#.#####.#.#.#.#.#######.#
+#...#.#.#...#.....#.#...#.#.#...#.#...#.....#.......#...#.#...#.#...#.#...#.#.......#...#.#.#.....#.#
+#.#.#.#.#########.#.#.###.#.#.#.#.#####.#####.#######.#.#.#.#######.#.#.###.###.#####.###.#.###.#.#.#
+#.#.#.#.#.......#...#.#.#...#.#...#.....#...#.....#...#.#...#...#...#.....#...#.#...#.....#.....#.#.#
+###.#$#.#.$####$####$.#.#$###.$####$####$.#.#$###.$.###$####$.#.#$###.$####$#.##$.#.#$####$####$#.#.#
+#...#.....#.........#.#.#.....#...#.#.#...#...#...#...#.#.....#...#.#.#.....#.#...#.#.........#...#.#
+#.#########.#######.#.#.#.#####.#.#.#.#.###.###.#######.#.#########.#.#.###.#.#.###.#.#####.#.#.###.#
+#.......#...#.....#...#...#.....#...#.#.#.#.........#...#.....#.......#.#.#...#.#...#.#.#...#.#.#...#
+#.#####.#####.###.#####.#######.#####.#.#.#########.#.#######.###.#####.#.###.#.#.#.#.#.#.#####.#.#.#
+#...#$..#.$...#$..#.$.#..$..#.$.#..$....$...#$..#.$...#$....$...#$#.#.$.#..$..#.$.#.#$#.#.$....$#.#.#
+###.#.#.#.#####.###.#.#####.#.###########.###.#.#####.#.#.#####.#.#.#.###.#####.#.###.#.#########.#.#
+#...#.#.#.#...#.....#.....#...#.....#...#.#...#.#...#.#.#...#...#.#.....#.#.....#...#.#.......#...#.#
+#.###.###.#.#.###########.#####.###.#.#.###.###.#.#.###.###.#.###.#.###.###.#######.#.#.#####.#.###.#
+#...#.......#...........#.........#...#.......#...#.......#...#.......#...........#.....#.......#....
+#####################################################################################################
+
+#####################################################################################################
+#.........#.........#...#.................#.....#.....#...........#...#.....#.....#...........#.....#
+#####.###.#.#######.#.#.###.###.###########.#.###.#.#.###.#######.###.#.#.#.###.#.#####.#.###.#.###.#
+#.....#...#.......#...#...#...#.#...#.......#.....#.#...#.....#.#...#...#.#...#.#.....#.#.#.....#.#.#
+#.###############.#######.###.###.#.#.#############.###.#####.#.###.#####.###.#.#####.#.#.#.#####.#.#
+#....$#...$....$#...$.#.#$..#.$...#$..#.$...#$....$...#$..#.$.#..$#...$...#$..#.$....$#.#.$.#..$#.#.#
+#####.#.#.#.###.#####.#.###.#.#############.#.###.#.#.###.#.###.###.#######.###.#.#####.#.###.#.#.#.#
+#.....#.#.....#.....#.#...#.#.....#.........#...#.#.#.#...#.#.......#...#.......#...#...#.#...#.#...#
+#.###.#.#########.###.###.#.#####.###.###.#####.#.###.#.###.###.#####.#.###########.#####.#.###.#.###
+#.#...#...#.....#.#.......#.....#.....#...#.....#...#.#...#...#.#.....#.#.........#.....#...#...#.#.#
+#.###$###.$.###$#.#.$####$####$.###$###.$##.#$####$.#.#$#.##$.###$####$.#.#$####$.###$#.##$##.#$#.#.#
+#...#.....#.#...#...#...#.....#.#.#.......#.#.....#...#.#...#...#...#...#.#...#.#.#.....#.....#...#.#
+#.#.#.#####.###.###.#.#.#.###.#.#.#.#######.#.###.#####.###.#.#.###.#.#.#.#.#.#.#.###.###.#####.###.#
+#.#.#.....#...#...#.#.#.....#...#...#.......#...#...#...#...#.#.#...#.#.#.#.#...#...#.#.....#.#.#...#
+#.#.#.#######.###.###.#####.#####.###.#########.#.#.#.###.#####.#.###.#.#.#.#######.#.#####.#.#.#.#.#
+#.#..$#...$...#$#...$.#..$#...$...#$..#.$....$..#.$...#$..#.$...#$..#.$.#..$#...$...#$#...$.#.#$#.#.#
+#.#####.#######.#######.#.#.#.#.###.###.#########.#.###.###.#######.#.#####.#.#######.#.#.#.#.#.#.#.#
+#.#...#.....#.......#...#.#.#...#...#...#.......#.#.#.......#.......#.....#.#.....#.....#...#.#...#.#
+#.#.#.#####.#.###.#.###.#.#.#####.#####.###.###.#.###.#######.#########.###.#####.###########.#####.#
+#...#.#...#.#.#...#...#.#...#...#.....#...#...#.#.....#.#...#...#.#...#...#.#...#.......#...#.....#.#
+#####$#.#.$.###$####$.###$###.$.###$#.##$.###$#.##$####$#.#.$##.#$#.#.$##.#$#.##$##.#$#.#.$##.#$###.#
+#.....#.#.#...#.#...#.........#.....#.#.#.....#.........#.#.....#...#...#.#.#.#...#...#.#...#.#.....#
+#.#####.#.###.#.#.#.###############.#.#.#####.#.#######.#.###########.#.#.#.#.#.#.#####.###.#.#######
+#.#.#...#...#.#...#...#...#.......#...#.....#...#.#.....#.............#.#...#.#.#.#.....#...#.....#.#
+#.#.#.#####.#.#####.#.#.#.#######.#####.###.#####.#.###############.#######.#.#.#.#.#####.#.#####.#.#
+#.#.#$..#.$...#$..#.$.#.#$....$.#..$..#.$.#..$#...$.#..$....$....$#.#.$...#$..#.$...#$....$...#$..#.#
+#.#.###.#.#####.#.###.#.#######.#.###.###.#.###.#####.#######.#####.#.###.#####.#####.#.#######.###.#
+#.#...#.#.#.....#...#...#.......#...#.....#.#...#.....#.....#.......#.#...#...#...#...#...#...#.#...#
+#.#.#.#.###.#######.#####.#.#######.#####.#.#.###.#####.#############.###.#.#.###.###.###.#.#.#.###.#
+#.#.#.#.....#.#.....#.....#.#.....#.#...#.#...#...#...........#.#...#...#...#...#...#...#...#.#.#...#
+#.#.#$####$##.#$####$.###$#.#.$##.#$#.#.$####$#.##$####$###.$.#.#$#.##$.###$###.$##.#$#.##$##.#$#.#.#
+#.#.#...#.....#.....#...#.#.#.#.#.....#.#...#.#...........#.#.#...#...#.#...........#.#.....#...#.#.#
+#.#####.#.#.#.#####.#.#.#.#.#.#.#######.#.#.###.#########.#.#.#####.#.#.#############.#####.#####.###
+#.....#...#.#.....#.#.#.#...#.#.......#.#.#...#.#.......#.#.#.......#.#...........#.......#.....#...#
+#####.#.###.#.#######.#.###.#.#.#####.#.#.###.#.#.#####.#.#.#######.#####.#######.#.###.#.#####.#.#.#
+#...#$#...$.#.#$....$.#..$#.#.$....$#.#.$.#.#$..#.$...#$#...$....$#.#.$.#..$....$.#.#$..#.$...#$#.#.#
+###.#.###.#.###.###.#.###.###.#######.#.#.#.#####.#.###.#######.###.#.#.#######.#.###.#.###.#.#.###.#
+#...#.#...#...#...#.#...#...#.#.......#...#.....#.#.....#.......#...#.#.#.....#.#.#...#.#...#.#.#...#
+#.#.#.#.#####.###.#.###.###.#.#.#####.#######.###.#.#####.#####.#.###.#.#####.#.#.#.#####.###.#.#.###
+#.#.#.#.#...#.....#.....#.#...#.....#.........#...#...#.......#.#.#.#.#.....#...#.#.........#.#.#...#
+#.###$#.#.$.###$####$##.#$####$####$###.$####$#.##$##.#$####$.###$#.#.$####$#.##$.#.#$####$##.#$###.#
+#.....#...#.#.........#.....#.....#...#.#.......#...#.#.....#.......#.....#.#...#.#...#.....#...#...#
+#.#######.###.#.#####.#####.#.###.#.#.###.#######.#.#.###################.#.###.#.#####.###.###.#.#.#
+#...#...#.#...#.#...#.....#...#...#.#...#.......#.#.#.......#.......#.....#.#...#.....#.#.#...#...#.#
+###.###.#.#.#####.#.#####.#######.#####.#######.#.#.#######.#.#####.#.#####.#.#######.#.#.###.#######
+#.#..$#.#.$....$..#.$...#$....$.#..$#...$...#$..#.$....$#...$....$#...$....$#...$....$#.#.$.#.#$....#
+#.###.#.#.#########.#.#########.###.#.#.#####.###.#.#####.#######.#####.#####.###.#####.###.#.#.###.#
+#.....#.#...#...#...#...#.....#.#.....#.#.....#.#.#...............#...#...#...#...#.........#...#...#
+#.#####.###.###.#.###.#.#.#.###.#########.#####.#.###################.###.###.#.###.#######.#####.###
+#.#.......#.....#.#...#...#...#.#.......#.#...#...#.......#...........#.#...#.#.......#...#.....#...#
+#.###$###.$.###$#.#.$####$#.#.$.#.#$###.$.#.#$####$.###$#.#.$.###$###.$.###$#.##$####$#.#.$.###$#.#.#
+#.#...#...#.#.....#...#.....#.#...#...#.#.#.#.....#.....#.#.#.#...#.#...#...#...#...#...#.#.#...#.#.#
+#.#.#.#.###.#.#######.#.#####.#####.###.#.#.#####.#####.#.###.#.#.#.#.###.#####.#.###.###.#.#.#.###.#
+#...#.#.....#.#.....#...#...#.......#...#...#...#.....#.#...#.#.#.#...#...#...#.#...#.#.#.#.#.#.#...#
+#####.#.#####.#.###.#.###.#.#####.#.#.###.###.#.#.#.###.###.#.#.#.###.#.###.###.###.#.#.#.#.#.#.#.#.#
+#...#$#...$...#$..#.$.#..$#...$...#$#.#.$...#$#.#.$.#..$#.#.$...#$..#.$.#..$....$...#$#...$.#.#$..#.#
+#.###.###.#.###########.###########.#.#####.#.#.###.#.###.#.#.#####.###.#.#########.#.#.###.#.#####.#
+#...#...#.#.#...........#...#...#...#...#...#.#...#.#.....#.#.....#.....#.#...#.....#.#...#.#.#.#...#
+#.#.###.###.#.#.#########.#.#.#.#.#####.#####.###.#.###.###.#####.#######.#.#.#######.###.###.#.#.###
+#.#...#.....#.#.......#...#...#.#.#...#.......#...#...#.#...#...#...#.....#.#...#.....#.#...#.#...#.#
+#.###$####$##.#$####$.#.#$####$.#.#$#.##$####$#.##$.#.#$#.##$.###$#.##$####$###.$.###$#.##$.#.#$###.#
+#...#...#.#...#.....#...#.....#.#.............#.#.#.#...#.#...#...#...#.....#.#.#.....#...#...#...#.#
+#.###.#.#.#.###.#####.#######.#.#############.#.#.#.#####.#.###.#.###.#.#####.#.#####.#.#.#######.#.#
+#.#...#.#.#.#...#...#...#.....#.#...........#.#.#...#...#.#.....#...#...#...#.#.......#.#.......#.#.#
+###.###.#.#.#.#.#.#.###.#.###.#.#.###########.#.###.#.#.#.###.#####.###.#.#.#.#########.#######.#.#.#
+#...#$#.#.$.#.#$#.#.$...#$..#.$.#..$....$...#$#...$.#.#$#...$....$#...$...#$#...$....$....$....$#...#
+#.###.#.#.#.#.###.#.###.###.#.#.#########.#.#.###.###.#.###.#####.###.#####.###.#.#########.###.###.#
+#.#...#.#.#.#.#...#...#.....#.#.....#...#.#...#...#...#.....#.....#...#.......#.......#.....#.....#.#
+#.#.###.#.#.#.#.#####.#######.#####.#.#.#######.###.#########.#####.#########.#######.#.#####.#####.#
+#.#.....#.....#...#.........#.....#.#.#.......#.....#.........#.....#...#...#.......#.#.....#.#.....#
+#.###$####$##.#$#.##$####$#.##$##.#$#.##$####$####$####$####$##.#$###.$.#.#$####$##.#$#.##$.###$#####
+#...#.......#...#.......#.......#.#.#.#.....#.........#...#...#.......#...#.#.....#...#.#.#...#.#...#
+#.#.#######.#.#####.###.#.#####.###.#.###.#####.#####.#####.#.#######.#####.#####.###.#.#.###.#.#.#.#
+#.#.......#.#.#...#.#...#.#...#.....#...#.#.....#...#...#...#.#.....#.....#.#...#...#.#...#...#...#.#
+#.#######.#.#.#.#.###.#.###.#.#####.###.#.#.#######.###.#.###.#.###.#######.#.#.###.#.###.#.#.#####.#
+#...#$..#.$.#.#$#...$.#.#$..#.$....$#.#.$.#..$....$....$#.#.$.#..$#...$....$#.#.$.#..$#...$.#.#$....#
+###.###.#.#.#.#.###.#.###.###.###.###.#.#.#######.###.###.#.#.#.#.#####.#####.###.#.#######.###.#####
+#.....#.#.#.#.#...#.#.#...#.#...#.#...#.#...#...#...#.#...#...#.#.#...#.#.....#.#.#.......#...#.#...#
+#####.#.#.#.#.###.#.#.#.###.###.#.#.###.#.#.#.#.###.#.#.#.#.###.#.#.#.###.#####.#.#######.###.#.#.#.#
+#...#...#.#.#.#...#...#.#.....#.#.#...#...#.#.#.#...#.#.#.#...#.#...#...........#.......#.#...#.#.#.#
+#.#.#$###.$.###$####$.#.#$###.$.#.#$#.##$##.#$###.$##.#$#.##$.###$###.$####$####$##.#$#.#.$.#.#$#.#.#
+#.#.......#.....#.#...#.#.#...#.#.....#...#.#.#...#.......#...#.....#.#.#.....#...#.#...#...#.#.#.#.#
+#.#####.#########.#.###.###.#.#.###.###.#.#.#.#.###########.###.###.#.#.#.###.#.#.###.#######.#.#.#.#
+#.#...#.#...#...#...#.#.#...#.#.#...#...#...#.#.....#.....#...#.#...#...#.#.....#.#...#.......#...#.#
+#.#.#.###.#.#.#.#.###.#.#.###.#.###.#.#######.#####.#.#.#.###.#.###.###.#.#######.#.###.###########.#
+#.#.#$....$.#.#$#.#.$.#..$#...$...#$#.#.$....$#...$.#.#$#.#.$.#..$#...$.#..$#...$...#$#.#.$...#$....#
+#.#.#######.#.###.#.#.#####.#####.###.#.#.###.#.#.#.###.###.#####.###.#####.#########.#.#.###.#.#####
+#...#.......#.....#.#.#.....#...#.#...#.#.#.#...#.#...#...#.......#.........#...#.......#.#.#.#.....#
+#.###.###########.#.###.#######.#.#.#####.#.#####.###.#.#.#########.#########.#.#######.#.#.#.#####.#
+#.#.#.......#...#...#...#.....#.#.#.#.....#.#.....#.#.#.#...........#.........#.#.....#.#...#.....#.#
+#.#.#$####$.#.#$###.$.###$###.$.#.#$#.##$##.#$####$.#.#$####$##.#$###.$####$###.$.###$###.$##.#$###.#
+#.#.......#...#.#.#.#.#...#.....#.#.#.#...#...#.....#.........#...#.#.#...#.....#...#.....#...#.....#
+#.#.###.#######.#.#.#.###.#######.#.#.#.#.#.###.###.#########.###.#.#.###.#.#######.#######.#.#.#####
+#...#...#...#...#...#...#.#.....#.#...#.#.#...#.#.......#...#...#...#.#...#.#.......#.......#.#.....#
+###.#####.#.#.###.#####.#.#.###.#.#####.#####.#.#######.#.#.#.#.#####.#.###.#.#######.#############.#
+#...#$..#.$...#$....$...#$#.#.$...#$..#.$....$#...$.#..$#.#.$.#..$..#.$.#..$#.#.$...#$..#.$...#$....#
+#.###.#.#.#########.#.###.#.#######.#.#.#######.#.#.#.###.#.#######.###.#.###.#.###.###.#.###.#.#####
+#...#.#...#...#...#.#...#.#.#.......#...#.....#.#.#.#.#.#.#.........#...#...#.#...#.#.#.#.#...#.#...#
+###.#.#####.#.#.#.#####.#.#.#.###########.###.###.#.#.#.#.###########.#####.#.###.#.#.#.#.#.###.#.#.#
+#...#.......#...#.........#...............#.......#.....#.................#.......#...#...#.......#.#
+##################################################################################################### \ No newline at end of file
diff --git a/codingquest2024/src/day9/solution.gleam b/codingquest2024/src/day9/solution.gleam
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/codingquest2024/src/day9/solution.gleam
diff --git a/codingquest2024/src/utilities/memo.gleam b/codingquest2024/src/utilities/memo.gleam
new file mode 100644
index 0000000..b06d8fd
--- /dev/null
+++ b/codingquest2024/src/utilities/memo.gleam
@@ -0,0 +1,57 @@
+import gleam/dict.{type Dict}
+import gleam/otp/actor.{type Next, Continue, Stop}
+import gleam/erlang/process.{type Subject, Normal}
+import gleam/option.{None}
+
+const timeout = 1000
+
+type Message(k, v) {
+ Shutdown
+ Get(key: k, client: Subject(Result(v, Nil)))
+ Set(key: k, value: v)
+}
+
+type Server(k, v) =
+ Subject(Message(k, v))
+
+pub opaque type Cache(k, v) {
+ Cache(server: Server(k, v))
+}
+
+fn handle_message(
+ message: Message(k, v),
+ dict: Dict(k, v),
+) -> Next(Message(k, v), Dict(k, v)) {
+ case message {
+ Shutdown -> Stop(Normal)
+ Get(key, client) -> {
+ process.send(client, dict.get(dict, key))
+ Continue(dict, None)
+ }
+ Set(key, value) -> Continue(dict.insert(dict, key, value), None)
+ }
+}
+
+pub fn create(apply fun: fn(Cache(k, v)) -> t) -> t {
+ let assert Ok(server) = actor.start(dict.new(), handle_message)
+ let result = fun(Cache(server))
+ process.send(server, Shutdown)
+ result
+}
+
+pub fn set(in cache: Cache(k, v), for key: k, insert value: v) -> Nil {
+ process.send(cache.server, Set(key, value))
+}
+
+pub fn get(from cache: Cache(k, v), fetch key: k) -> Result(v, Nil) {
+ process.call(cache.server, fn(c) { Get(key, c) }, timeout)
+}
+
+pub fn memoize(with cache: Cache(k, v), this key: k, apply fun: fn() -> v) -> v {
+ let result = case get(from: cache, fetch: key) {
+ Ok(value) -> value
+ Error(Nil) -> fun()
+ }
+ set(in: cache, for: key, insert: result)
+ result
+}