Last active
December 15, 2023 17:35
-
-
Save qookei/db816975257d4e02f6ced13e77bdc67c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(use-modules (ice-9 textual-ports) (srfi srfi-1) (srfi srfi-26) | |
(ice-9 format) (ice-9 match) (ice-9 pretty-print) | |
(srfi srfi-8) (ice-9 arrays)) | |
(define (%map-input-char c) | |
(match c | |
[#\. 0] | |
[#\O 1] | |
[#\# -1])) | |
(define (%read-input) | |
(let ([line (get-line (current-input-port))]) | |
(if (eof-object? line) | |
'() | |
(cons (map %map-input-char (string->list line)) | |
(%read-input))))) | |
(define (read-input) | |
(list->array 2 (%read-input))) | |
(define (break-on lst v) | |
(receive (before after) | |
(break (cut = v <>) lst) | |
(cond | |
[(null? after) (list before)] | |
[else (cons before | |
(cons (list (car after)) | |
(break-on (cdr after) v)))]))) | |
(define (%get-column-north input x) | |
(let ([y-range (second (array-shape input))]) | |
(make-shared-array | |
input | |
(λ (i) (list i x)) | |
y-range))) | |
(define (%get-column-south input x) | |
(let* ([y-range (second (array-shape input))] | |
[y-max (second y-range)]) | |
(make-shared-array | |
input | |
(λ (i) (list (- y-max i) x)) | |
y-range))) | |
(define (%get-row-west input y) | |
(let* ([x-range (first (array-shape input))] | |
[x-max (second x-range)]) | |
(make-shared-array | |
input | |
(λ (i) (list y (- x-max i))) | |
x-range))) | |
(define (%get-row-east input y) | |
(let ([x-range (first (array-shape input))]) | |
(make-shared-array | |
input | |
(λ (i) (list y i)) | |
x-range))) | |
(define (%shift-rocks line) | |
(array-copy! | |
(list->array | |
1 (apply append | |
(map (λ (lst) | |
(if (equal? lst '(-1)) | |
lst | |
(sort lst >))) | |
(break-on (array->list line) -1)))) | |
line)) | |
(define (%north-load input) | |
(let ([height (cadr (array-dimensions input))]) | |
(fold | |
(λ (x prev) | |
(+ prev | |
(fold | |
(λ (v i prev) | |
(+ prev | |
(if (> v 0) i 0))) | |
0 | |
(array->list (%get-column-north input x)) | |
(iota height height -1)))) | |
0 (iota height)))) | |
(define (part1 input) | |
(for-each | |
(λ (x) (%shift-rocks (%get-column-north input x))) | |
(iota (second (array-dimensions input)))) | |
(%north-load input)) | |
(define (%one-cycle input) | |
(for-each | |
(λ (x) (%shift-rocks (%get-column-north input x))) | |
(iota (second (array-dimensions input)))) | |
(for-each | |
(λ (y) (%shift-rocks (%get-row-east input y))) | |
(iota (first (array-dimensions input)))) | |
(for-each | |
(λ (x) (%shift-rocks (%get-column-south input x))) | |
(iota (second (array-dimensions input)))) | |
(for-each | |
(λ (y) (%shift-rocks (%get-row-west input y))) | |
(iota (first (array-dimensions input))))) | |
(define (%part2 input) | |
(let next ([i 0]) | |
(let ([load (%north-load input)]) | |
(if (= i 1000) | |
(list load) | |
(begin | |
(%one-cycle input) | |
(cons load (next (1+ i)))))))) | |
(let ([input (read-input)]) | |
(format #t "Part 1: ~a~%" (part1 (array-copy input))) | |
(format #t "Part 2: | |
Put the following numbers into a spreadsheet into column A. | |
Put numbers 1-1001 in column B. | |
Then set: | |
D3 to =MIN(A400:A1001) | |
D4 to =VLOOKUP(D3, A400:B1001,2,0) | |
D5 to =VLOOKUP(D3, A449:B1001,2,FALSE()) -- adjust 449 based on value in D4 | |
D6 to =D5-D4 | |
D7 to =D5+MOD(1000000000-D5,D6) -- may need +1? works without for sample | |
input, doesn't for my input | |
Then look at column A row (value of D7) for the answer. | |
~{~a~%~}" (%part2 (array-copy input)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment