diff options
-rw-r--r-- | aoc2023-other/day-14/day-14.rkt | 43 | ||||
-rw-r--r-- | aoc2023/src/day14/solve.gleam | 63 | ||||
-rw-r--r-- | jj-aoc.rkt | 20 |
3 files changed, 94 insertions, 32 deletions
diff --git a/aoc2023-other/day-14/day-14.rkt b/aoc2023-other/day-14/day-14.rkt new file mode 100644 index 0000000..e90feba --- /dev/null +++ b/aoc2023-other/day-14/day-14.rkt @@ -0,0 +1,43 @@ +#lang racket + +(require advent-of-code + threading + "../../jj-aoc.rkt") + +(define input + (~> (fetch-aoc-input (find-session) 2023 14 #:cache #true) + string-split + (map string->list _) + transpose)) + +(define (roll-boulders board) + (for/list ([col (in-list board)]) + (~> col (chunks-by (curry equal? #\#)) (append-map (curryr sort char>?) _)))) + +(define (score board) + (for*/sum ([col (in-list board)] [(row n) (in-indexed (reverse col))] #:when (equal? row #\O)) + (add1 n))) + +;; part 1 +(~> input roll-boulders score) + +;; part 2 +(define (rotate-board xss) + (~> xss (map reverse _) transpose)) + +(define (full-cycle board) + (foldl (λ (_ acc) (~> acc roll-boulders rotate-board)) board (range 4))) + +(define (spin-to-win board) + (define cache (make-hash)) + (define (do-spin board n) + (match (hash-ref cache board 'not-found) + ['not-found + (hash-set! cache board n) + (do-spin (full-cycle board) (sub1 n))] + [seen + (define to-end (modulo n (- seen n))) + (score (foldl (λ (_ acc) (full-cycle acc)) board (range to-end)))])) + (do-spin board 1000000000)) + +(~> input spin-to-win) diff --git a/aoc2023/src/day14/solve.gleam b/aoc2023/src/day14/solve.gleam index 3113d91..1ad1a18 100644 --- a/aoc2023/src/day14/solve.gleam +++ b/aoc2023/src/day14/solve.gleam @@ -1,12 +1,10 @@ import adglent.{First, Second} +import gleam/dict +import gleam/int import gleam/io -import gleam/string import gleam/list import gleam/order -import gleam/int -import gleam/iterator -import gleam/result -import utilities/memo.{type Cache} +import gleam/string fn parse(input) { input @@ -23,30 +21,22 @@ fn roll_boulders(strs: List(String)) { |> list.flatten } -fn score(matrix, cache) { - use <- memo.memoize(cache, matrix) - { - use col <- list.map(matrix) - list.index_map(list.reverse(col), fn(i, c) { #(i + 1, c) }) - |> list.fold( - 0, - fn(acc, tup) { - case tup { - #(n, "O") -> acc + n - _ -> acc - } - }, - ) +fn score(matrix) { + use acc, col <- list.fold(matrix, 0) + acc + { + use col_acc, char, n <- list.index_fold(list.reverse(col), 0) + case char { + "O" -> col_acc + n + 1 + _ -> col_acc + } } - |> int.sum } pub fn part1(input: String) { - use cache: Cache(List(List(String)), Int) <- memo.create() input |> parse |> list.map(roll_boulders) - |> score(cache) + |> score() |> string.inspect } @@ -56,21 +46,34 @@ fn rotate(matrix) { |> list.transpose } -fn spin_the_board(matrix, cache) { - use <- memo.memoize(cache, matrix) - matrix +fn spin(matrix) { + use acc, _ <- list.fold(list.range(1, 4), matrix) + acc |> list.map(roll_boulders) |> rotate } +fn spin_cycle(matrix) { + let cache = dict.new() + check_if_seen(matrix, cache, 1_000_000_000) +} + +fn check_if_seen(matrix, cache, count) { + case dict.get(cache, matrix) { + Error(Nil) -> + check_if_seen(spin(matrix), dict.insert(cache, matrix, count), count - 1) + Ok(n) -> { + let assert Ok(extra) = int.modulo(count, n - count) + list.fold(list.range(1, extra), matrix, fn(acc, _) { spin(acc) }) + |> score + } + } +} + pub fn part2(input: String) { - use cache: Cache(List(List(String)), List(List(String))) <- memo.create() - use score_cache: Cache(List(List(String)), Int) <- memo.create() input |> parse - |> iterator.iterate(spin_the_board(_, cache)) - |> iterator.map(score(_, score_cache)) - |> iterator.at(10000) + |> spin_cycle |> string.inspect } @@ -1,6 +1,22 @@ #lang racket (require advent-of-code) -(provide open-day) +(provide open-day + transpose + chunks-by) (define (open-day n [year 2021]) - (open-aoc-input (find-session) year n #:cache (string->path "./cache")))
\ No newline at end of file + (open-aoc-input (find-session) year n #:cache (string->path "./cache"))) + +(define (transpose xss) + (apply map list xss)) + +(define (chunks-by xs [by identity]) + (define (do-chunks-by xs by group result) + (match* (xs group) + [('() _) (reverse (cons group result))] + [((list* h t) '()) (do-chunks-by t by (cons h group) result)] + [((list* h t) (list* g _)) + #:when (equal? (by h) (by g)) + (do-chunks-by t by (cons h group) result)] + [((list* h t) _) (do-chunks-by t by (list h) (cons group result))])) + (do-chunks-by xs by '() '())) |