aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--codingquest2024/src/day6/solution.gleam86
1 files changed, 86 insertions, 0 deletions
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
+}