diff options
Diffstat (limited to 'aoc-2020-gleam/src/days/day23.gleam')
-rw-r--r-- | aoc-2020-gleam/src/days/day23.gleam | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/aoc-2020-gleam/src/days/day23.gleam b/aoc-2020-gleam/src/days/day23.gleam index 8b58fa7..72e6c4d 100644 --- a/aoc-2020-gleam/src/days/day23.gleam +++ b/aoc-2020-gleam/src/days/day23.gleam @@ -4,7 +4,7 @@ import gleam/bool import gleam/string as str import gleam/function as fun import gleam/iterator as iter -import gleam/map.{Map} +import gleam/dict.{type Dict} import gleam/list.{Continue, Stop} import ext/resultx as resx import ext/iteratorx as iterx @@ -15,7 +15,7 @@ fn parse_input(input: String) -> List(Int) { |> list.map(with: fun.compose(int.parse, resx.assert_unwrap)) } -fn play(input: String, bound: Int, moves: Int) -> Map(Int, Int) { +fn play(input: String, bound: Int, moves: Int) -> Dict(Int, Int) { let assert [first, ..tail] = parse_input(input) let assert Ok(second) = list.first(tail) @@ -24,24 +24,24 @@ fn play(input: String, bound: Int, moves: Int) -> Map(Int, Int) { True -> list.range(from: 10, to: bound) False -> [] }) - |> build_map(map.from_list([#(first, second)]), first) + |> build_dict(dict.from_list([#(first, second)]), first) |> move(first, moves, bound) } fn move( - cups: Map(Int, Int), + cups: Dict(Int, Int), current: Int, round: Int, bound: Int, -) -> Map(Int, Int) { +) -> Dict(Int, Int) { use <- bool.guard(when: round == 0, return: cups) // Remove nodes from source - let assert Ok(first) = map.get(cups, current) - let assert Ok(second) = map.get(cups, first) - let assert Ok(third) = map.get(cups, second) - let assert Ok(rest) = map.get(cups, third) - let cups = map.insert(into: cups, for: current, insert: rest) + let assert Ok(first) = dict.get(cups, current) + let assert Ok(second) = dict.get(cups, first) + let assert Ok(third) = dict.get(cups, second) + let assert Ok(rest) = dict.get(cups, third) + let cups = dict.insert(into: cups, for: current, insert: rest) // Insert nodes at destination let assert Ok(before) = @@ -50,46 +50,48 @@ fn move( |> iter.find(one_that: fn(key) { !list.contains([first, second, third], key) }) - let assert Ok(after) = map.get(cups, before) + let assert Ok(after) = dict.get(cups, before) let cups = cups - |> map.insert(for: before, insert: first) - |> map.insert(for: third, insert: after) + |> dict.insert(for: before, insert: first) + |> dict.insert(for: third, insert: after) cups |> move( cups - |> map.get(current) + |> dict.get(current) |> resx.assert_unwrap, - round - 1, + round + - 1, bound, ) } -fn build_map(list: List(Int), cups: Map(Int, Int), first: Int) -> Map(Int, Int) { +fn build_dict( + list: List(Int), + cups: Dict(Int, Int), + first: Int, +) -> Dict(Int, Int) { case list { - [] -> map.new() - [head] -> map.insert(into: cups, for: head, insert: first) + [] -> dict.new() + [head] -> dict.insert(into: cups, for: head, insert: first) [head, ..tail] -> { let assert Ok(second) = list.first(tail) - build_map(tail, map.insert(into: cups, for: head, insert: second), first) + build_dict(tail, dict.insert(into: cups, for: head, insert: second), first, + ) } } } -fn to_result_string(cups: Map(Int, Int)) -> String { - iterx.unfold_infinitely( - from: 1, - with: fn(key) { resx.assert_unwrap(map.get(cups, key)) }, - ) +fn to_result_string(cups: Dict(Int, Int)) -> String { + iterx.unfold_infinitely(from: 1, with: fn(key) { + resx.assert_unwrap(dict.get(cups, key)) + }) |> iter.drop(1) - |> iter.fold_until( - from: "", - with: fn(acc, key) { - use <- bool.guard(when: key == 1, return: Stop(acc)) - Continue(acc <> int.to_string(key)) - }, - ) + |> iter.fold_until(from: "", with: fn(acc, key) { + use <- bool.guard(when: key == 1, return: Stop(acc)) + Continue(acc <> int.to_string(key)) + }) } fn part1(input: String) -> String { @@ -100,15 +102,15 @@ fn part1(input: String) -> String { fn part2(input: String) -> Int { let finished = play(input, 1_000_000, 10_000_000) - let assert Ok(first) = map.get(finished, 1) - let assert Ok(second) = map.get(finished, first) + let assert Ok(first) = dict.get(finished, 1) + let assert Ok(second) = dict.get(finished, first) first * second } pub fn main() -> Nil { - let test = "389125467" - let assert "67384529" = part1(test) - let assert 149_245_887_792 = part2(test) + let testing = "389125467" + let assert "67384529" = part1(testing) + let assert 149_245_887_792 = part2(testing) let input = "925176834" io.println(part1(input)) |