diff options
author | HJ <thechairman@thechairman.info> | 2023-12-04 09:05:29 -0500 |
---|---|---|
committer | HJ <thechairman@thechairman.info> | 2023-12-04 09:05:29 -0500 |
commit | 0d12017453583343520d6faa636ff3cd651d3957 (patch) | |
tree | 2ff95d1516f67bb31559897e78563cd1f65dd375 /aoc2023 | |
parent | f7b0d5c650d095bcb8f88c5f7e288d6fe5671df4 (diff) | |
download | gleam_aoc-0d12017453583343520d6faa636ff3cd651d3957.tar.gz gleam_aoc-0d12017453583343520d6faa636ff3cd651d3957.zip |
day 4 racket complete
Diffstat (limited to 'aoc2023')
-rw-r--r-- | aoc2023/src/day4/solve.gleam | 91 |
1 files changed, 37 insertions, 54 deletions
diff --git a/aoc2023/src/day4/solve.gleam b/aoc2023/src/day4/solve.gleam index eab700b..d0da835 100644 --- a/aoc2023/src/day4/solve.gleam +++ b/aoc2023/src/day4/solve.gleam @@ -1,103 +1,86 @@ import adglent.{First, Second} -import gleam/io -import gleam/string +import gleam/bool +import gleam/dict.{type Dict} import gleam/int +import gleam/io import gleam/list -import gleam/dict -import gleam/result import gleam/option.{None, Some} +import gleam/result +import gleam/set.{type Set} +import gleam/string type Card { - Card(number: Int, winning: List(Int), has: List(Int)) + Card(number: Int, winners: Int) } -fn numbers_to_list(str: String) -> List(Int) { +fn numbers_to_set(str: String) -> Set(Int) { str |> string.split(" ") |> list.map(int.parse) |> result.values() + |> set.from_list() } fn parse_card(card: String) -> Card { let assert Ok(#("Card" <> n_str, rest)) = string.split_once(card, ": ") let assert Ok(#(winning_str, has_str)) = string.split_once(rest, " | ") - let assert Ok(n) = - n_str - |> string.trim - |> int.parse + let assert Ok(n) = int.parse(string.trim(n_str)) - let winning = numbers_to_list(winning_str) - let has = numbers_to_list(has_str) + let winning = numbers_to_set(winning_str) + let has = numbers_to_set(has_str) + let winners = set.size(set.intersection(winning, has)) - Card(number: n, winning: winning, has: has) + Card(number: n, winners: winners) } -fn win_points(n) { - case n { - 0 -> 0 - 1 -> 1 - n -> 2 * win_points(n - 1) - } -} - -fn count_wins(card: Card) { - use acc, c <- list.fold(card.has, 0) - case list.contains(card.winning, c) { - True -> acc + 1 - False -> acc - } +fn win_points(n: Int) { + bool.guard(n < 2, n, fn() { 2 * win_points(n - 1) }) } pub fn part1(input: String) { use acc, c <- list.fold(string.split(input, "\n"), 0) c |> parse_card - |> count_wins - |> win_points + |> fn(c: Card) { win_points(c.winners) } |> int.add(acc) } -fn win_more_cards(cards: List(String), card_count: dict.Dict(Int, Int)) { +fn win_more_cards(cards: List(String), count: Dict(Int, Int)) { case cards { [] -> - card_count + count + |> io.debug |> dict.values |> int.sum [raw_card, ..rest] -> { let card = parse_card(raw_card) - let wins = count_wins(card) - case wins { - 0 -> win_more_cards(rest, card_count) - n -> { - let assert Ok(bonus) = dict.get(card_count, card.number) - let won_cards = list.range(card.number + 1, card.number + n) - { - use acc, n <- list.fold(won_cards, card_count) - use c <- dict.update(acc, n) - case c { - Some(i) -> i + bonus - None -> panic as "won a card that doesn't exist in the card pile" - } - } - |> win_more_cards(rest, _) - } + case card.winners { + 0 -> win_more_cards(rest, count) + n -> win_more_cards(rest, update_counts(n, card, count)) } } } } +fn update_counts(n: Int, card: Card, count: Dict(Int, Int)) -> Dict(Int, Int) { + let assert Ok(bonus) = dict.get(count, card.number) + use acc, n <- list.fold(list.range(card.number + 1, card.number + n), count) + use c <- dict.update(acc, n) + case c { + Some(i) -> i + bonus + None -> panic as "won a card that doesn't exist in the card pile" + } +} + pub fn part2(input: String) { - let raw_cards = - input - |> string.split("\n") + let cards = string.split(input, "\n") - let card_count = - list.range(1, list.length(raw_cards)) + let count = + list.range(1, list.length(cards)) |> list.map(fn(n) { #(n, 1) }) |> dict.from_list() - raw_cards - |> win_more_cards(card_count) + win_more_cards(cards, count) } pub fn main() { |