Advertisement
Guest User

Untitled

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