Skip to content

Instantly share code, notes, and snippets.

@sotolf2
Created January 3, 2020 08:31
Show Gist options
  • Save sotolf2/b0715cabd5b23cd3ebc911e7c2541ac9 to your computer and use it in GitHub Desktop.
Save sotolf2/b0715cabd5b23cd3ebc911e7c2541ac9 to your computer and use it in GitHub Desktop.
#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