Skip to content

Instantly share code, notes, and snippets.

@madstap
Last active April 16, 2017 04:34
Show Gist options
  • Save madstap/e9ecaa37db3637f9ac8132d58ce0e191 to your computer and use it in GitHub Desktop.
Save madstap/e9ecaa37db3637f9ac8132d58ce0e191 to your computer and use it in GitHub Desktop.
Code golfer as a macro
(ns golf.code-golfer)
(def ^:private safe-neighbors
"The characters that indicate neighboring spaces are safe to remove."
(set "(){}[]\""))
(defn- whitespace? [x]
{:pre [(char? x)]}
(Character/isWhitespace x))
(def ^:private safe-or-nil?
(some-fn safe-neighbors nil?))
(defn one? [x] (== 1 x))
(defn- split-into-neighbors [s]
(if (one? (count s))
[[nil (first s) nil]]
(let [[[a b c] :as xs] (butlast (partition-all 3 1 s))]
(conj xs [nil a b]))))
(defn- minimize-fn [code-str]
(first
(reduce (fn [[acc inside-str?] [a x b]]
(cond
inside-str? (if (= \" x)
[(str acc x) false]
[(str acc x) inside-str?])
(= \" x)
[(str acc x) true]
(and x (Character/isWhitespace x) (or (safe-or-nil? a)
(safe-or-nil? b)))
[acc inside-str?]
:else [(str acc x) inside-str?]))
["" false]
(split-into-neighbors code-str))))
(defmacro golf [& body]
(->> body (map pr-str) (interpose " ") (apply str) minimize-fn))
(comment
(= "" (golf))
(= "1" (golf 1))
(= "foo bar" (golf foo bar))
(= "foo[1 2[baz]]3" (golf foo [1 2 [baz]] 3))
(= "foo\"[] []\"" (golf foo "[] []"))
(= "(defn f[x](inc x))"
(golf (defn f [x]
;; Increments x
(inc x))))
(= "(foo)" (golf (foo #_bar)))
;; TODO: Ideally this would return "'(1 2 3)"
(= "(quote(1 2 3))" (golf '(1 2 3)))
;; Quotes inside strings will trip it up
(= "[\"\\\"\"[]]" (golf ["\"" []])) ;=> false
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment