Created
January 3, 2020 08:31
-
-
Save sotolf2/b0715cabd5b23cd3ebc911e7c2541ac9 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
#lang racket | |
(require threading) | |
(define (get-input) | |
(file->lines "day7.txt")) | |
(struct part (cmd a b to) #:transparent) | |
(define (string->param str) | |
(if str | |
(or (string->number str) str) | |
#f)) | |
(define (parse-line str) | |
(define parts (string-split str " -> ")) | |
(define to (second parts)) | |
(define from (string-split (first parts))) | |
(define cmd | |
(cond | |
[(string-contains? str "RSHIFT") 'rshift] | |
[(string-contains? str "LSHIFT") 'lshift] | |
[(string-contains? str "NOT") 'not] | |
[(string-contains? str "OR") 'or] | |
[(string-contains? str "AND") 'and] | |
[else 'store])) | |
(define a | |
(cond | |
[(= 1 (length from)) (first from)] | |
[(= 2 (length from)) (second from)] | |
[(= 3 (length from)) (first from)])) | |
(define b | |
(cond | |
[(= 1 (length from)) #f] | |
[(= 2 (length from)) #f] | |
[(= 3 (length from)) (third from)])) | |
(part cmd (string->param a) (string->param b) to)) | |
(define (parse strs) | |
(map parse-line strs)) | |
(define (requeue lst) | |
(append (cdr lst) (list (car lst)))) | |
(define (parts->signals parts) | |
(define (has-part-value val sigs) | |
(cond | |
[(false? val) #t] | |
[(number? val) #t] | |
[(hash-has-key? sigs val) #t] | |
[else #f])) | |
(define (getvalue val sigs) | |
(if (string? val) | |
(hash-ref sigs val) | |
val)) | |
(define (wrap num) | |
(modulo num 65536)) | |
(define (run prt sigs) | |
(define cmd (part-cmd prt)) | |
(define a (getvalue (part-a prt) sigs)) | |
(define b (getvalue (part-b prt) sigs)) | |
(cond | |
[(equal? cmd 'store) (hash-set sigs (part-to prt) a)] | |
[(equal? cmd 'rshift) (hash-set sigs (part-to prt) (wrap (arithmetic-shift a (- b))))] | |
[(equal? cmd 'lshift) (hash-set sigs (part-to prt) (wrap (arithmetic-shift a b)))] | |
[(equal? cmd 'not) (hash-set sigs (part-to prt) (wrap (bitwise-not a)))] | |
[(equal? cmd 'or) (hash-set sigs (part-to prt) (wrap (bitwise-ior a b)))] | |
[(equal? cmd 'and) (hash-set sigs (part-to prt) (wrap (bitwise-and a b)))])) | |
(define (parts-rec parts sigs) | |
(if (empty? parts) | |
sigs | |
(if (and (has-part-value (part-a (car parts)) sigs) (has-part-value (part-b (car parts)) sigs)) | |
(parts-rec (cdr parts) (run (car parts) sigs)) | |
(parts-rec (requeue parts) sigs)))) | |
(parts-rec parts #hash())) | |
(define (part1) | |
(~>> | |
(get-input) | |
(parse) | |
(parts->signals) | |
(hash-ref _ "a"))) | |
(define (prepare-p2 pts) | |
(define (prep-rec pts res) | |
(if (empty? pts) | |
res | |
(cond | |
[(and (equal? 'store (part-cmd (car pts))) (equal? "b" (part-to (car pts)))) | |
(prep-rec (cdr pts) (cons (part (part-cmd (car pts)) 3176 #f (part-to (car pts))) res))] | |
[else | |
(prep-rec (cdr pts) (cons (car pts) res))]))) | |
(prep-rec pts empty)) | |
(define (part2) | |
(~>> | |
(get-input) | |
(parse) | |
(prepare-p2) | |
(parts->signals) | |
(hash-ref _ "a"))) | |
(module+ test | |
(require rackunit) | |
(require rackunit/text-ui) | |
(define test-str "123 -> x | |
456 -> y | |
x AND y -> d | |
x OR y -> e | |
x LSHIFT 2 -> f | |
y RSHIFT 2 -> g | |
NOT x -> h | |
NOT y -> i") | |
(define test-parts (string-split test-str "\r\n")) | |
(define part-1 | |
(test-suite | |
"Part 1" | |
(check-equal? 1 1 "basic") | |
(check-equal? (parse-line "fo RSHIFT 2 -> fp") (part 'rshift "fo" 2 "fp") "parse fo RSHIFT 2 -> fp") | |
(check-equal? (parse-line "NOT hn -> ho") (part 'not "hn" #f "ho") "parse NOT hn -> ho") | |
(check-equal? (parse-line "44430 -> b") (part 'store 44430 #f "b") "parse 44430 -> b") | |
(check-equal? (requeue '(1 2 3 4)) '(2 3 4 1) "Test enqueue") | |
(check-equal? (part1) 3176 "Test part1 from input"))) | |
(define part-2 | |
(test-suite | |
"Part 2" | |
(check-equal? 1 1 "basic") | |
(check-equal? (part2) 14710 "Test part2 from input"))) | |
(run-tests part-1) | |
(run-tests part-2)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment