 (ns org.bytopia.foreclojure.logic
-  (:require clojure.walk)
+  (:require [clojure.string :as str]
+            clojure.walk)
   (:import [java.util.concurrent FutureTask TimeUnit TimeoutException]))
 
 (def ^:const timeout 3000)

     (if (empty? code)
       (assoc err-map i "Empty input is not allowed.")
       (try
         (let [code-form (binding [*read-eval* false]
                           (read-string (.replace test "__" code)))
               found-restricted (clojure.walk/postwalk
                                 (fn [f]
                                   (if (sequential? f)

(def ^:private forbidden-symbols
  #{'eval 'resolve 'read 'read-string 'throw 'ns 'in-ns 'require 'use 'refer})

(defn read-code
  "Safely read Clojure code from a string. Returns a sequence of read forms.
  Taken from 4clojure.com source."
  [^String code]
  (binding [*read-eval* false]
    (with-in-str code
      (let [end (Object.)]
        (doall (take-while (complement #{end})
                           (repeatedly #(read *in* false end))))))))

(defn check-suggested-solution
  "Evaluates user code against problem tests. Returns a map of test numbers to
  the errors (map is empty if all tests passed correctly). `restricted` is a set
