aboutsummaryrefslogtreecommitdiff
path: root/aoc2023
diff options
context:
space:
mode:
authorHJ <thechairman@thechairman.info>2023-12-04 09:05:29 -0500
committerHJ <thechairman@thechairman.info>2023-12-04 09:05:29 -0500
commit0d12017453583343520d6faa636ff3cd651d3957 (patch)
tree2ff95d1516f67bb31559897e78563cd1f65dd375 /aoc2023
parentf7b0d5c650d095bcb8f88c5f7e288d6fe5671df4 (diff)
downloadgleam_aoc-0d12017453583343520d6faa636ff3cd651d3957.tar.gz
gleam_aoc-0d12017453583343520d6faa636ff3cd651d3957.zip
day 4 racket complete
Diffstat (limited to 'aoc2023')
-rw-r--r--aoc2023/src/day4/solve.gleam91
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() {