diff options
author | J.J <thechairman@thechairman.info> | 2023-12-04 00:56:43 -0500 |
---|---|---|
committer | J.J <thechairman@thechairman.info> | 2023-12-04 00:56:43 -0500 |
commit | aa4626c6d3feb825f43ae53f0bed09da249f873b (patch) | |
tree | 88140717cee083ab9afa0e6fdd3cdef1385d1e56 /aoc2023/src | |
parent | cd893a2756ffcc73df737a154ea7b3e2119329fe (diff) | |
download | gleam_aoc-aa4626c6d3feb825f43ae53f0bed09da249f873b.tar.gz gleam_aoc-aa4626c6d3feb825f43ae53f0bed09da249f873b.zip |
day 4 complete
Diffstat (limited to 'aoc2023/src')
-rw-r--r-- | aoc2023/src/aoc2023.gleam | 8 | ||||
-rw-r--r-- | aoc2023/src/day4/.gitignore | 1 | ||||
-rw-r--r-- | aoc2023/src/day4/solve.gleam | 129 |
3 files changed, 137 insertions, 1 deletions
diff --git a/aoc2023/src/aoc2023.gleam b/aoc2023/src/aoc2023.gleam index ea5c211..30335ee 100644 --- a/aoc2023/src/aoc2023.gleam +++ b/aoc2023/src/aoc2023.gleam @@ -1,5 +1,11 @@ import gleam/io +import gleam/bit_array + +const str = "abcdefgh +abcdefgh" pub fn main() { - io.println("Hello from aoc2023!") + let trim = 8 + let <<_:bytes-size(trim), "\n":utf8, rest:bytes>> = bit_array.from_string(str) + io.debug(rest) } diff --git a/aoc2023/src/day4/.gitignore b/aoc2023/src/day4/.gitignore new file mode 100644 index 0000000..ae40cea --- /dev/null +++ b/aoc2023/src/day4/.gitignore @@ -0,0 +1 @@ +input.txt
\ No newline at end of file diff --git a/aoc2023/src/day4/solve.gleam b/aoc2023/src/day4/solve.gleam new file mode 100644 index 0000000..426922c --- /dev/null +++ b/aoc2023/src/day4/solve.gleam @@ -0,0 +1,129 @@ +import adglent.{First, Second} +import gleam/io +import gleam/string +import gleam/int +import gleam/list +import gleam/dict +import gleam/result +import gleam/option.{None, Some} + +type Card { + Card(number: Int, winning: List(Int), has: List(Int)) +} + +fn numbers_to_list(str: String) -> List(Int) { + str + |> string.split(" ") + |> list.map(int.parse) + |> result.values() +} + +fn parse_card(card: String) { + 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 winning = numbers_to_list(winning_str) + let has = numbers_to_list(has_str) + + Card(number: n, winning: winning, has: has) +} + +fn double_up(n) { + case n { + 0 -> 0 + 1 -> 1 + n -> 2 * double_up(n - 1) + } +} + +fn count_wins(card: Card) { + list.fold( + card.has, + 0, + fn(acc, c) { + case list.contains(card.winning, c) { + True -> acc + 1 + False -> acc + } + }, + ) +} + +pub fn part1(input: String) { + input + |> string.split("\n") + |> list.fold( + 0, + fn(acc, c) { + c + |> parse_card + |> count_wins + |> double_up + |> int.add(acc) + }, + ) + |> string.inspect +} + +fn win_more_cards(cards: List(Card), card_count: dict.Dict(Int, Int)) { + case cards { + [] -> + card_count + |> dict.values + |> int.sum + [card, ..rest] -> { + 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, _) + } + } + } + } +} + +pub fn part2(input: String) { + let raw_cards = + input + |> string.split("\n") + + let card_count = + list.range(1, list.length(raw_cards)) + |> list.map(fn(n) { #(n, 1) }) + |> dict.from_list() + + raw_cards + |> list.map(parse_card) + |> win_more_cards(card_count) + |> string.inspect +} + +pub fn main() { + let assert Ok(part) = adglent.get_part() + let assert Ok(input) = adglent.get_input("4") + case part { + First -> + part1(input) + |> adglent.inspect + |> io.println + Second -> + part2(input) + |> adglent.inspect + |> io.println + } +} |