diff options
author | HJ <thechairman@thechairman.info> | 2023-12-15 07:57:42 -0500 |
---|---|---|
committer | HJ <thechairman@thechairman.info> | 2023-12-15 07:57:42 -0500 |
commit | 7d7e1fca0fdb635cc6bfdf9e3cda3fe2b8e9a9c6 (patch) | |
tree | 005f5907b445e87a159c38b0f86741229e1cd8a1 /aoc2023 | |
parent | fcd6998f07bb9f44dafcb029156ae171ee4b0387 (diff) | |
download | gleam_aoc-7d7e1fca0fdb635cc6bfdf9e3cda3fe2b8e9a9c6.tar.gz gleam_aoc-7d7e1fca0fdb635cc6bfdf9e3cda3fe2b8e9a9c6.zip |
day 15 gleam done
Diffstat (limited to 'aoc2023')
-rw-r--r-- | aoc2023/src/day15/.gitignore | 1 | ||||
-rw-r--r-- | aoc2023/src/day15/solve.gleam | 104 | ||||
-rw-r--r-- | aoc2023/test/day15/day15_test.gleam | 42 |
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) +} |