aboutsummaryrefslogtreecommitdiff
path: root/aoc2023/src
diff options
context:
space:
mode:
authorJ.J <thechairman@thechairman.info>2023-12-04 00:56:43 -0500
committerJ.J <thechairman@thechairman.info>2023-12-04 00:56:43 -0500
commitaa4626c6d3feb825f43ae53f0bed09da249f873b (patch)
tree88140717cee083ab9afa0e6fdd3cdef1385d1e56 /aoc2023/src
parentcd893a2756ffcc73df737a154ea7b3e2119329fe (diff)
downloadgleam_aoc-aa4626c6d3feb825f43ae53f0bed09da249f873b.tar.gz
gleam_aoc-aa4626c6d3feb825f43ae53f0bed09da249f873b.zip
day 4 complete
Diffstat (limited to 'aoc2023/src')
-rw-r--r--aoc2023/src/aoc2023.gleam8
-rw-r--r--aoc2023/src/day4/.gitignore1
-rw-r--r--aoc2023/src/day4/solve.gleam129
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
+ }
+}