Skip to content

Instantly share code, notes, and snippets.

@sbenhaim
Last active December 16, 2015 03:41
Show Gist options
  • Save sbenhaim/892a11b39a5b7613c614 to your computer and use it in GitHub Desktop.
Save sbenhaim/892a11b39a5b7613c614 to your computer and use it in GitHub Desktop.
(ns advent.a7
(:require [clojure.string :as str]
[instaparse.core :as insta]
[clojure.core.match :refer [match]]))
(def MAX (int (dec (Math/pow 2 16))))
(defn unsign [i]
(cond (< i 0) (+ MAX (inc i))
(> i MAX) (- (dec i) MAX)
:else i))
(def sample "123 -> x
x AND y -> d
x OR y -> e
y RSHIFT 2 -> g
NOT x -> h
x LSHIFT 2 -> f
NOT y -> i
456 -> y")
(def op {"AND" bit-and
"OR" bit-or
"LSHIFT" bit-shift-left
"RSHIFT" bit-shift-right
"NOT" bit-not})
(def grammar "
instr = assign | binary | unary
assign = (wire|sig) arrow wire
binary = (wire|sig) gate (wire|sig) arrow wire
unary = gate (wire|sig) arrow wire
sig = #'\\d+'
wire = #'[a-z]+'
gate = #'[A-Z]+'
<arrow> = <'->'>
")
(def parser (insta/parser grammar :auto-whitespace :standard))
(defn parse [s] (second (parser s)))
(defn measure [[val-type val & args] env]
(unsign
(condp = val-type
:sig (Integer/parseInt val)
:wire (measure (env val) env)
:gate (apply (op val) (for [arg args] (measure arg env))))))
(def measure (memoize measure))
(defn eval [ptree env]
(match ptree
[:assign v1 [:wire v]]
(assoc env v v1)
[:unary [:gate op] v1 [:wire v]]
(assoc env v [:gate op v1])
[:binary v1 [:gate op] v2 [:wire v]]
(assoc env v [:gate op v1 v2])))
(defn wire [insts]
(reduce (fn [env inst] (eval (parse inst) env)) {} insts))
(let [kit (wire (str/split-lines (slurp "a7.txt")))
sig (measure [:wire "a"] kit)
kit (assoc kit "b" [:sig (str sig)])]
(measure [:wire "a"] kit))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment