Advertisement
Guest User

Untitled

a guest
May 7th, 2019
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Clojure 12.09 KB | None | 0 0
  1. ; <FROM LAST HW>
  2. (deftype Var [variable])
  3. (deftype ConstOpera [value])
  4. (deftype DivideOpera [arguments])
  5. (deftype AndOpera [arguments])
  6. (deftype OrOpera [arguments])
  7. (deftype XorOpera [arguments])
  8. (deftype UnaryOpera [name operation argument diff])
  9. (deftype BinaryOpera [name operation arguments diff])
  10. (declare Variable Constant Negate Add Subtract Multiply Divide)
  11.  
  12. (defmulti toString class)
  13. (defmulti toStringSuffix class)
  14. (defmulti toStringInfix class)
  15. (defmulti evaluate (fn [exp _] (class exp)))
  16. (defmulti diff (fn [exp _] (class exp)))
  17.  
  18. (defmethod toString Var [exp] (.-variable exp))
  19. (defmethod toStringSuffix Var [exp] (.-variable exp))
  20. (defmethod toStringInfix Var [exp] (.-variable exp))
  21. (defmethod evaluate Var [exp vars] ((comp vars clojure.string/lower-case str) (nth (.-variable exp) 0)))
  22. (defmethod diff Var [exp var] (if (= var ((comp clojure.string/lower-case str) (nth (.-variable exp) 0))) (Constant 1) (Constant 0)))
  23. (defmethod toString ConstOpera [exp]
  24.   (str (format "%.0f.0" (.-value exp))))
  25. (defmethod toStringSuffix ConstOpera [exp]
  26.   (str (format "%.0f.0" (.-value exp))))
  27. (defmethod toStringInfix ConstOpera [exp]
  28.   (str (format "%.0f.0" (.-value exp))))
  29. (defmethod evaluate ConstOpera [exp _]
  30.   (.-value exp))
  31. (defmethod diff ConstOpera [_ _] (Constant 0))
  32.  
  33. (defmethod toString UnaryOpera [exp] (str "(" (.-name exp) " " (toString (.-argument exp)) ")"))
  34. (defmethod toStringSuffix UnaryOpera [exp] (str "(" (toStringSuffix (.-argument exp)) " " (.-name exp) ")"))
  35. (defmethod toStringInfix UnaryOpera [exp] (str (.-name exp) "(" (toStringInfix (.-argument exp)) ")"))
  36. (defmethod evaluate UnaryOpera [exp vars] ((.-operation exp) (evaluate (.-argument exp) vars)))
  37. (defmethod diff UnaryOpera [exp var] ((.-diff exp) (.-argument exp) var))
  38. (defmethod toString DivideOpera [exp] (str "(/" (reduce #(str %1 " " (toString %2)) "" (.-arguments exp)) ")"))
  39. (defmethod toStringSuffix DivideOpera [exp] (str "(" (reduce #(str %1 (toStringSuffix %2) " ") "" (.-arguments exp)) "/)"))
  40. (defmethod toStringInfix DivideOpera [exp] (str "(" (reduce #(str %1 " / " (toStringInfix %2)) (toStringInfix (first (.-arguments exp))) (rest (.-arguments exp))) ")"))
  41. (defmethod evaluate DivideOpera [exp vars] (reduce #(/ (double %1) (double %2)) (map #(evaluate % vars) (.-arguments exp))))
  42. (defmethod diff DivideOpera [exp var] (let [d (rest (.-arguments exp))] (Divide (Subtract (Multiply (diff (first (.-arguments exp)) var) (apply Multiply d)) (Multiply (first (.-arguments exp)) (diff (apply Multiply d) var))) (apply Multiply (into d d)))))
  43.  
  44. (defmethod toString AndOpera [exp] (str "(&" (reduce #(str %1 " " (toString %2)) "" (.-arguments exp)) ")"))
  45. (defmethod toStringSuffix AndOpera [exp] (str "(" (reduce #(str %1 (toStringSuffix %2) " ") "" (.-arguments exp)) "&)"))
  46. (defmethod toStringInfix AndOpera [exp] (str "(" (reduce #(str %1 " & " (toStringInfix %2)) (toStringInfix (first (.-arguments exp))) (rest (.-arguments exp))) ")"))
  47. (defmethod evaluate AndOpera [exp vars] (reduce #(Double/longBitsToDouble (bit-and (Double/doubleToLongBits %1) (Double/doubleToLongBits %2))) (map #(evaluate % vars) (.-arguments exp))))
  48. (defmethod diff AndOpera [exp var] (let [d (rest (.-arguments exp))] (Divide (Subtract (Multiply (diff (first (.-arguments exp)) var) (apply Multiply d)) (Multiply (first (.-arguments exp)) (diff (apply Multiply d) var))) (apply Multiply (into d d)))))
  49.  
  50. (defmethod toString OrOpera [exp] (str "(|" (reduce #(str %1 " " (toString %2)) "" (.-arguments exp)) ")"))
  51. (defmethod toStringSuffix OrOpera [exp] (str "(" (reduce #(str %1 (toStringSuffix %2) " ") "" (.-arguments exp)) "|)"))
  52. (defmethod toStringInfix OrOpera [exp] (str "(" (reduce #(str %1 " | " (toStringInfix %2)) (toStringInfix (first (.-arguments exp))) (rest (.-arguments exp))) ")"))
  53. (defmethod evaluate OrOpera [exp vars] (reduce #(Double/longBitsToDouble (bit-or (Double/doubleToLongBits %1) (Double/doubleToLongBits %2))) (map #(evaluate % vars) (.-arguments exp))))
  54. (defmethod diff OrOpera [exp var] (let [d (rest (.-arguments exp))] (Divide (Subtract (Multiply (diff (first (.-arguments exp)) var) (apply Multiply d)) (Multiply (first (.-arguments exp)) (diff (apply Multiply d) var))) (apply Multiply (into d d)))))
  55.  
  56. (defmethod toString XorOpera [exp] (str "(^" (reduce #(str %1 " " (toString %2)) "" (.-arguments exp)) ")"))
  57. (defmethod toStringSuffix XorOpera [exp] (str "(" (reduce #(str %1 (toStringSuffix %2) " ") "" (.-arguments exp)) "^)"))
  58. (defmethod toStringInfix XorOpera [exp] (str "(" (reduce #(str %1 " ^ " (toStringInfix %2)) (toStringInfix (first (.-arguments exp))) (rest (.-arguments exp))) ")"))
  59. (defmethod evaluate XorOpera [exp vars] (reduce #(Double/longBitsToDouble (bit-xor (Double/doubleToLongBits %1) (Double/doubleToLongBits %2))) (map #(evaluate % vars) (.-arguments exp))))
  60. (defmethod diff XorOpera [exp var] (let [d (rest (.-arguments exp))] (Divide (Subtract (Multiply (diff (first (.-arguments exp)) var) (apply Multiply d)) (Multiply (first (.-arguments exp)) (diff (apply Multiply d) var))) (apply Multiply (into d d)))))
  61.  
  62. (defmethod toString BinaryOpera [exp] (str "(" (.-name exp) (reduce #(str %1 " " (toString %2)) "" (.-arguments exp)) ")"))
  63. (defmethod toStringSuffix BinaryOpera [exp] (str "(" (reduce #(str %1 (toStringSuffix %2) " ") "" (.-arguments exp)) (.-name exp) ")"))
  64. (defmethod toStringInfix BinaryOpera [exp] (str "(" (reduce #(str %1 " " (.-name exp) " " (toStringInfix %2)) (toStringInfix (first (.-arguments exp))) (rest (.-arguments exp))) ")"))
  65. (defmethod evaluate BinaryOpera [exp vars] (case (count (.-arguments exp)) 0 ((.-operation exp)) 1 ((.-operation exp) (evaluate (first (.-arguments exp)) vars)) (reduce (.-operation exp) (map #(evaluate % vars) (.-arguments exp)))))
  66. (defmethod diff BinaryOpera [exp var] ((.-diff exp) (.-arguments exp) var))
  67.  
  68. (defn Variable [var] (Var. var))
  69. (defn Constant [value] (ConstOpera. value))
  70. (defn Negate [argument] (UnaryOpera. "negate" - argument (fn [arg var] (Negate (diff arg var)))))
  71. (defn Divide [& arguments] (DivideOpera. arguments))
  72. (defn And [& arguments] (AndOpera. arguments))
  73. (defn Or [& arguments] (OrOpera. arguments))
  74. (defn Xor [& arguments] (XorOpera. arguments))
  75.  
  76. (defn Add [& arguments] (BinaryOpera. "+" + arguments (fn [args var] (apply Add (map #(diff % var) args)))))
  77. (defn Subtract [& arguments] (BinaryOpera. "-" - arguments (fn [args var] (apply Subtract (map #(diff % var) args)))))
  78. (defn Multiply [& arguments] (BinaryOpera. "*" * arguments (fn [args var] (Add (apply Multiply (diff (first args) var) (rest args)) (if (== (count args) 1) (Constant 0) (Multiply (first args) (diff (apply Multiply (rest args)) var)))))))
  79. (def operations {'+ Add,
  80.                  '- Subtract,
  81.                  '* Multiply,
  82.                  '/ Divide,
  83.                  '& And,
  84.                  (symbol "^") Xor,
  85.                  '| Or,
  86.                  'negate Negate
  87.                  })
  88.  
  89. (defn parseExpression [expr] (cond (number? expr) (Constant expr) (symbol? expr) (Variable (str expr)) :else (apply (operations (first expr)) (map parseExpression (rest expr)))))
  90.  
  91. (def parseObject (comp parseExpression read-string))
  92.  
  93. ; </FROM LAST HW>
  94.  
  95. ; <wrote GOSHA>
  96.  
  97. (defn -return [value tail] {:value value :tail tail})
  98. (def -valid? boolean)
  99. (def -value :value)
  100. (def -tail :tail)
  101.  
  102. (defn _show [result]
  103.   (if (-valid? result) (str "-> " (pr-str (-value result)) " | " (pr-str (apply str (-tail result))))
  104.                        "!"))
  105. (defn tabulate [parser inputs]
  106.   (println)
  107.   (run! (fn [input] (printf "    %-10s %s\n" input (_show (parser input)))) inputs))
  108.  
  109. (defn _empty [value] (partial -return value))
  110. (defn _char [p]
  111.   (fn [[c & cs]]
  112.     (if (and c (p c)) (-return c cs))))
  113. (defn _map [f]
  114.   (fn [result]
  115.     (if (-valid? result)
  116.       (-return (f (-value result)) (-tail result)))))
  117. (defn _combine [f a b]
  118.   (fn [str]
  119.     (let [ar ((force a) str)]
  120.       (if (-valid? ar)
  121.         ((_map (partial f (-value ar)))
  122.           ((force b) (-tail ar)))))))
  123. (defn _either [a b]
  124.   (fn [str]
  125.     (let [ar ((force a) str)]
  126.       (if (-valid? ar) ar ((force b) str)))))
  127. (defn _parser [p]
  128.   (fn [input]
  129.     (-value ((_combine (fn [v _] v) p (_char #{\u0000})) (str input \u0000)))))
  130.  
  131. (defn +char [chars] (_char (set chars)))
  132. (defn +char-not [chars] (_char (comp not (set chars))))
  133. (defn +map [f parser] (comp (_map f) parser))
  134. (def +parser _parser)
  135. (def +ignore (partial +map (constantly 'ignore)))
  136.  
  137. (defn iconj [coll value]
  138.   (if (= value 'ignore) coll (conj coll value)))
  139. (defn +seq [& ps]
  140.   (reduce (partial _combine iconj) (_empty []) ps))
  141. (defn +seqf [f & ps] (+map (partial apply f) (apply +seq ps)))
  142. (defn +seqn [n & ps] (apply +seqf (fn [& vs] (nth vs n)) ps))
  143.  
  144. (defn +or [p & ps]
  145.   (reduce (partial _either) p ps))
  146. (defn +opt [p]
  147.   (+or p (_empty nil)))
  148. (defn +star [p]
  149.   (letfn [(rec [] (+or (+seqf cons p (delay (rec))) (_empty ())))] (rec)))
  150. (defn +plus [p] (+seqf cons p (+star p)))
  151. (defn +str [p] (+map (partial apply str) p))
  152.  
  153. ;</wrote GOSHA>
  154.  
  155. (declare *valueSuffix)
  156. (def *all-chars (mapv char (range 0 256)))
  157. (def *digit (+char "0123456789"))
  158. (def *number (+map read-string (+str (+seqf #(into (vec (cons %1 %2)) (vec (cons %3 %4))) (+opt (+char "+-")) (+plus *digit) (+opt (+char ".")) (+opt (+plus *digit))))))
  159. (def *spaces (apply str (filter #(or (Character/isWhitespace %) (= \, %)) *all-chars)))
  160. (def *space (+char *spaces))
  161. (def *symbol (+map symbol (+str (+or (+map list (+char (str (symbol "^") "|&+-/*"))) (+seqf cons (+char-not (str *spaces \u0000 (symbol "^") "|&()+-/*.1234567890")) (+star (+char-not (str *spaces (symbol "^") "^|&()+-/*." \u0000))))))))
  162. (def *whitespaces (+ignore (+star *space)))
  163. (defn *seq [begin p end]
  164.   (+seqn 1 (+char begin) (+opt (+seqf cons *whitespaces p (+star (+seqn 0 *whitespaces p)))) *whitespaces (+char end)))
  165.  
  166. (defn *list [] (+map #(cons (last %) (drop-last %)) (*seq "(" (delay (*valueSuffix)) ")")))
  167. (defn *valueSuffix [] (+or *number *symbol (*list)))
  168.  
  169. (def parserObjectSuffix (+parser (+seqn 0 *whitespaces (*valueSuffix) *whitespaces)))
  170. (defn parseObjectSuffix [str] (parseExpression (parserObjectSuffix str)))
  171.  
  172. (declare *valueInfix)
  173. (defn *parse_many [p sign] (+map (partial reduce #(list (first %2) %1 (second %2))) (+seqf cons *whitespaces p (+star (+seq *whitespaces sign *whitespaces p)) *whitespaces)))
  174. (defn *Nsymbol [symbols] (fn [input] (if (not (symbols (-value (*symbol input)))) (*symbol input))))
  175. (defn *Esymbol [symbols] (fn [input] (if (symbols (-value (*symbol input))) (*symbol input))))
  176. (def *variables (+map symbol (+str (+plus (+char "XYZxyz")))))
  177. (def *plusOtherSymbol (*Esymbol #{'+ '-}))
  178. (def *divOtherSymbol (*Esymbol #{'* '/}))
  179. (def *AndSymbol (*Esymbol #{'&}))
  180. (def *XorSymbol (*Esymbol #{(symbol "^")}))
  181. (def *OrSymbol (*Esymbol #{'|}))
  182.  
  183. (def *FSymbol (+map symbol (+str (+seqf cons (+char-not (str *spaces \u0000 (symbol "^") "xyzXYZ|&+-/*().1234567890")) (+star (+char-not (str *spaces "() \u0000")))))))
  184. (defn *listInfix [] (+seqn 1 (+char "(") *whitespaces (delay (*valueInfix)) *whitespaces (+char ")")))
  185. (defn *F [] (+map #(list (first %) (second %)) (+seq *FSymbol *whitespaces (+or (delay (*listInfix)) (delay (*F)) (delay *number) (delay *variables)))))
  186. (defn *divOther [] (*parse_many (+or (delay (*listInfix)) (delay (*F)) (delay *number) (delay *variables)) *divOtherSymbol))
  187. (defn *addOther [] (*parse_many (+or (delay (*divOther)) (delay (*listInfix)) (delay (*F)) *number *variables) *plusOtherSymbol))
  188. (defn *and [] (*parse_many (+or (delay (*addOther)) (delay (*divOther)) (delay (*listInfix)) (delay (*F)) *number *variables) *AndSymbol))
  189. (defn *or [] (*parse_many (+or (delay (*and)) (delay (*addOther)) (delay (*divOther)) (delay (*listInfix)) (delay (*F)) *number *variables) *OrSymbol))
  190. (defn *xor [] (*parse_many (+or (delay (*or)) (delay (*and)) (delay (*addOther)) (delay (*divOther)) (delay (*listInfix)) (delay (*F)) *number *variables) *XorSymbol))
  191.  
  192. (defn *valueInfix [] (+or (delay (*xor)) (delay (*or)) (delay (*and))(delay (*addOther)) (delay (*divOther)) (delay (*listInfix)) (delay (*F)) *number *variables))
  193.  
  194. (def parserObjectInfix (+parser (+seqn 0 *whitespaces (*valueInfix) *whitespaces)))
  195. (defn parseObjectInfix [str] (parseExpression (parserObjectInfix str)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement