aboutsummaryrefslogtreecommitdiff
path: root/aoc2023
diff options
context:
space:
mode:
authorHJ <thechairman@thechairman.info>2023-12-15 07:57:42 -0500
committerHJ <thechairman@thechairman.info>2023-12-15 07:57:42 -0500
commit7d7e1fca0fdb635cc6bfdf9e3cda3fe2b8e9a9c6 (patch)
tree005f5907b445e87a159c38b0f86741229e1cd8a1 /aoc2023
parentfcd6998f07bb9f44dafcb029156ae171ee4b0387 (diff)
downloadgleam_aoc-7d7e1fca0fdb635cc6bfdf9e3cda3fe2b8e9a9c6.tar.gz
gleam_aoc-7d7e1fca0fdb635cc6bfdf9e3cda3fe2b8e9a9c6.zip
day 15 gleam done
Diffstat (limited to 'aoc2023')
-rw-r--r--aoc2023/src/day15/.gitignore1
-rw-r--r--aoc2023/src/day15/solve.gleam104
-rw-r--r--aoc2023/test/day15/day15_test.gleam42
3 files changed, 147 insertions, 0 deletions
diff --git a/aoc2023/src/day15/.gitignore b/aoc2023/src/day15/.gitignore
new file mode 100644
index 0000000..ae40cea
--- /dev/null
+++ b/aoc2023/src/day15/.gitignore
@@ -0,0 +1 @@
+input.txt \ No newline at end of file
diff --git a/aoc2023/src/day15/solve.gleam b/aoc2023/src/day15/solve.gleam
new file mode 100644
index 0000000..2d863b5
--- /dev/null
+++ b/aoc2023/src/day15/solve.gleam
@@ -0,0 +1,104 @@
+import adglent.{First, Second}
+import gleam/io
+import gleam/string
+import gleam/list
+import gleam/int
+import gleam/dict.{type Dict}
+import gleam/option.{None, Some}
+
+fn split(input: String) -> List(String) {
+ input
+ |> string.split(",")
+}
+
+fn hash_algorithm(str: String) -> Int {
+ str
+ |> string.to_utf_codepoints()
+ |> list.map(string.utf_codepoint_to_int)
+ |> list.fold(0, fn(acc, c) {
+ let assert Ok(acc) = int.modulo({ acc + c } * 17, 256)
+ acc
+ })
+}
+
+pub fn part1(input: String) -> String {
+ input
+ |> split
+ |> list.fold(0, fn(acc, str) { acc + hash_algorithm(str) })
+ |> string.inspect
+}
+
+type Instruction {
+ Remove(label: String)
+ Insert(label: String, focal: Int)
+}
+
+fn read_instruction(str: String) -> Instruction {
+ case string.split(str, "=") {
+ [label, focal_str] -> {
+ let assert Ok(focal) = int.parse(focal_str)
+ Insert(label, focal)
+ }
+ _ -> Remove(string.drop_right(str, 1))
+ }
+}
+
+fn parse_instructions(insts: List(String)) -> Dict(Int, List(#(String, Int))) {
+ use acc, inst <- list.fold(insts, dict.new())
+ case read_instruction(inst) {
+ Remove(label) -> remove_lens(acc, label)
+ Insert(label, focal) -> insert_lens(acc, label, focal)
+ }
+}
+
+fn remove_lens(boxes, label) {
+ use v <- dict.update(boxes, hash_algorithm(label))
+ case v {
+ Some(lenses) ->
+ case list.key_pop(lenses, label) {
+ Ok(#(_, updated)) -> updated
+ Error(Nil) -> lenses
+ }
+ None -> []
+ }
+}
+
+fn insert_lens(boxes, label, focal) {
+ use v <- dict.update(boxes, hash_algorithm(label))
+ case v {
+ Some(lenses) -> list.key_set(lenses, label, focal)
+ None -> [#(label, focal)]
+ }
+}
+
+fn focusing_power(boxes: Dict(Int, List(#(String, Int)))) -> Int {
+ use acc, k, v <- dict.fold(boxes, 0)
+ let box_acc = {
+ use acc, lens, i <- list.index_fold(v, 0)
+ acc + lens.1 * { i + 1 }
+ }
+ acc + { k + 1 } * box_acc
+}
+
+pub fn part2(input: String) -> String {
+ input
+ |> split
+ |> parse_instructions
+ |> focusing_power
+ |> string.inspect
+}
+
+pub fn main() {
+ let assert Ok(part) = adglent.get_part()
+ let assert Ok(input) = adglent.get_input("15")
+ case part {
+ First ->
+ part1(input)
+ |> adglent.inspect
+ |> io.println
+ Second ->
+ part2(input)
+ |> adglent.inspect
+ |> io.println
+ }
+}
diff --git a/aoc2023/test/day15/day15_test.gleam b/aoc2023/test/day15/day15_test.gleam
new file mode 100644
index 0000000..83fadef
--- /dev/null
+++ b/aoc2023/test/day15/day15_test.gleam
@@ -0,0 +1,42 @@
+import gleam/list
+import showtime/tests/should
+import adglent.{type Example, Example}
+import day15/solve
+
+type Problem1AnswerType =
+ String
+
+type Problem2AnswerType =
+ String
+
+/// Add examples for part 1 here:
+/// ```gleam
+///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
+/// ```
+const part1_examples: List(Example(Problem1AnswerType)) = [
+ Example("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7", "1320"),
+]
+
+/// Add examples for part 2 here:
+/// ```gleam
+///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
+/// ```
+const part2_examples: List(Example(Problem2AnswerType)) = [
+ Example("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7", "145"),
+]
+
+pub fn part1_test() {
+ part1_examples
+ |> should.not_equal([])
+ use example <- list.map(part1_examples)
+ solve.part1(example.input)
+ |> should.equal(example.answer)
+}
+
+pub fn part2_test() {
+ part2_examples
+ |> should.not_equal([])
+ use example <- list.map(part2_examples)
+ solve.part2(example.input)
+ |> should.equal(example.answer)
+}