This commit is contained in:
2021-12-03 19:06:37 +01:00
parent ffaf4acf1e
commit cb4da1e6ec
2 changed files with 1075 additions and 0 deletions

1000
day-3.input Normal file

File diff suppressed because it is too large Load Diff

75
day-3.scm Normal file
View File

@@ -0,0 +1,75 @@
(import (srfi :43))
; returns a vector of 12 elements where each one counts the number
; of times the n-th bit was zero in the input vector
(define (count-zeroes-for-each-bit numbers)
(let [(zeroes (make-vector 12 0))]
(vector-for-each
(lambda (index number)
(let iterate [(bit 0)]
(when (< bit 12)
(when (= 0 (bitwise-and number
(bitwise-arithmetic-shift-left 1 bit)))
(vector-set! zeroes bit
(+ 1 (vector-ref zeroes bit))))
(iterate (+ 1 bit)))))
numbers)
zeroes))
(define (part-1 numbers)
(let* [(zeroes (count-zeroes-for-each-bit numbers))]
(let iter-loop [(i 0) (gamma 0)]
(if (< i 12)
; We don't need to compute the number of ones
; as it is what's left when the zeroes are removed.
; So that's just the number of elements minus the number of zeroes.
(if (> (vector-ref zeroes i) (/ (vector-length numbers) 2))
(iter-loop (+ i 1) (+ gamma (bitwise-arithmetic-shift-left 1 i)))
(iter-loop (+ i 1) gamma))
(let [(epsilon (bitwise-xor gamma #b111111111111))]
(printf "part 1: ~% gamma: ~a~% epsilon: ~a~% power consumption: ~a~%"
gamma epsilon (* gamma epsilon)))))))
; recursively filters the numbers checking for the n-th bit with the comparator
; with <= as the comparator, it will check for bits that are set
; with the opposite > comparator, it will check for bits that are not
(define (determine-rating numbers comparator)
(let loop [(bit 11)
(numbers (vector-map (lambda (index number) number) numbers))]
(if (= 1 (vector-length numbers))
(vector-ref numbers 0)
(let* [(zeroes (count-zeroes-for-each-bit numbers))
(mask (bitwise-arithmetic-shift-left 1 bit))
(target
(if (apply comparator
(list (vector-ref zeroes bit) (/ (vector-length numbers) 2)))
0
mask))]
;(printf "dataset: ~a~% zeroes: ~a~% bit: ~a~% mask: (#b~b)~%" numbers zeroes bit mask)
(loop
(- bit 1)
(vector-fold
(lambda (index result number)
(if (= target (bitwise-and number mask))
(vector-append result (vector number))
result))
'#() numbers))))))
(define (part-2 numbers)
(let [(oxygen-gen (determine-rating numbers <=))
(co2-scrub (determine-rating numbers >))]
(printf "part 2:~% O2-gen rating: ~a~% CO2-scrub rating: ~a~% life support: ~a~%"
oxygen-gen co2-scrub (* oxygen-gen co2-scrub))))
(call-with-input-file
"day-3.input"
(lambda (file)
(let [(numbers '#())]
(let read-loop ()
(let [(line (get-line file))]
(when (not (eof-object? line))
(set! numbers
(vector-append numbers (vector (string->number line 2))))
(read-loop))))
(part-1 numbers)
(part-2 numbers))))