diff options
author | H.J <thechairman@thechairman.info> | 2024-06-17 16:56:25 -0400 |
---|---|---|
committer | H.J <thechairman@thechairman.info> | 2024-06-17 16:56:25 -0400 |
commit | c0b58af106690cadd1b58bf84481748a717b4dfc (patch) | |
tree | ed35f21b8ddc47666beffa97fb3cd8b1f5fa5eac | |
parent | a05e1e203d2a9fdce1c4b71436924bf90c05a0e3 (diff) | |
download | gleam_aoc-c0b58af106690cadd1b58bf84481748a717b4dfc.tar.gz gleam_aoc-c0b58af106690cadd1b58bf84481748a717b4dfc.zip |
gleam 2017 day 16 complete
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_16.gleam | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/aoc2017-gleam/src/aoc_2017/day_16.gleam b/aoc2017-gleam/src/aoc_2017/day_16.gleam new file mode 100644 index 0000000..9a5110e --- /dev/null +++ b/aoc2017-gleam/src/aoc_2017/day_16.gleam @@ -0,0 +1,104 @@ +import gleam/dict.{type Dict} +import gleam/int +import gleam/list +import gleam/string + +pub type DanceMove { + Spin(moving: Int) + Exchange(first: Int, second: Int) + Partner(first: String, second: String) +} + +const initial_lineup = "abcdefghijklmnop" + +const dancer_count = 16 + +const end_state = 1_000_000_000 + +pub fn parse(input: String) { + string.split(input, ",") +} + +fn do_spin(dancers: List(String), moving: Int) { + let #(front, back) = list.split(dancers, dancer_count - moving) + list.append(back, front) +} + +fn do_exchange(dancers: List(String), first: Int, second: Int) { + let indexed = list.index_map(dancers, fn(d, i) { #(i, d) }) + + let assert Ok(first_dancer) = list.key_find(indexed, first) + let assert Ok(second_dancer) = list.key_find(indexed, second) + + indexed + |> list.key_set(first, second_dancer) + |> list.key_set(second, first_dancer) + |> list.map(fn(tup) { tup.1 }) +} + +fn do_partner(dancers: List(String), first: String, second: String) { + use dancer <- list.map(dancers) + case dancer { + d if d == first -> second + d if d == second -> first + d -> d + } +} + +pub fn pt_1(input: List(String)) { + initial_lineup + |> string.to_graphemes() + |> next_move(input) + |> string.concat() +} + +fn next_move(dancers, raw_moves) { + case raw_moves { + [] -> dancers + ["s" <> size, ..rest] -> dancers |> do_spin(int(size)) |> next_move(rest) + ["x" <> swap, ..rest] -> { + let assert Ok(#(first, second)) = string.split_once(swap, "/") + dancers |> do_exchange(int(first), int(second)) |> next_move(rest) + } + ["p" <> swap, ..rest] -> { + let assert Ok(#(first, second)) = string.split_once(swap, "/") + dancers |> do_partner(first, second) |> next_move(rest) + } + _ -> panic as "bad dance move" + } +} + +pub fn pt_2(input: List(String)) { + initial_lineup + |> string.to_graphemes() + |> find_cycle(caching_in: dict.new(), cycle: 0, dancing_to: input) +} + +fn find_cycle( + moving_to dance_position: List(String), + caching_in cache: Dict(String, Int), + cycle cycle: Int, + dancing_to dance_moves: List(String), +) { + let dance_hash = string.concat(dance_position) + case dict.get(cache, dance_hash) { + Ok(c) -> { + let offset = end_state % { cycle - c } - c + let assert [#(final, _)] = + dict.filter(cache, fn(_, v) { v == offset }) |> dict.to_list() + final + } + _err -> + find_cycle( + moving_to: next_move(dance_position, dance_moves), + caching_in: dict.insert(cache, dance_hash, cycle), + cycle: cycle + 1, + dancing_to: dance_moves, + ) + } +} + +fn int(n) { + let assert Ok(n) = int.parse(n) + n +} |