Advertisement
IzhanVarsky

Untitled

Apr 29th, 2019
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.41 KB | None | 0 0
  1. (defn method [key] (fn [this & args] (apply (this key) (cons this args))))
  2.  
  3. (def evaluate (method :evaluate))
  4. (def toString (method :toString))
  5. (def diff (method :diff))
  6.  
  7. (defn Constant [value]
  8. {
  9. :evaluate (fn [_ _] value)
  10. :toString (fn [_] (format "%.1f" value))
  11. :diff (fn [_ _] (Constant 0))
  12. })
  13.  
  14. (defn Variable [name]
  15. {
  16. :evaluate (fn [_ map] (get map name))
  17. :toString (fn [_] (str name))
  18. :diff (fn [_ v] (if (= v name) (Constant 1) (Constant 0)))
  19. })
  20.  
  21. (defn OperationFactory [action symbol howToDiff]
  22. (fn [& args]
  23. {
  24. :evaluate (fn [this vars]
  25. (apply action (mapv #(evaluate % vars) args)))
  26. :toString (fn [this]
  27. (str "("
  28. symbol
  29. (apply str (mapv #(str " " (toString %)) args))
  30. ")"))
  31. :diff howToDiff
  32. :operands args}
  33. ))
  34.  
  35. (defn nth-among-operands [this x] (nth (this :operands) x))
  36. (def Add
  37. (OperationFactory
  38. +
  39. "+"
  40. (fn [this v]
  41. (Add (diff (nth-among-operands this 0) v)
  42. (diff (nth-among-operands this 1) v)))))
  43. (def Subtract
  44. (OperationFactory
  45. -
  46. "-"
  47. (fn [this v]
  48. (Subtract (diff (nth-among-operands this 0) v)
  49. (diff (nth-among-operands this 1) v)))))
  50. (def Negate
  51. (OperationFactory
  52. -
  53. "negate"
  54. (fn [this v]
  55. (Negate (diff (nth-among-operands this 0) v)))))
  56. (def Multiply
  57. (OperationFactory
  58. *
  59. "*"
  60. (fn [this v]
  61. (Add
  62. (Multiply (diff (nth-among-operands this 0) v) (nth-among-operands this 1))
  63. (Multiply (diff (nth-among-operands this 1) v) (nth-among-operands this 0)))
  64. )))
  65.  
  66. (def Divide
  67. (OperationFactory
  68. (fn rec
  69. ([a b] (/ (double a) b))
  70. ([a b & more] (apply rec (rec a b) more)))
  71. "/"
  72. (fn [this v]
  73. (Divide
  74. (Subtract
  75. (Multiply (diff (nth-among-operands this 0) v) (nth-among-operands this 1))
  76. (Multiply (diff (nth-among-operands this 1) v) (nth-among-operands this 0)))
  77. (Multiply (nth-among-operands this 1) (nth-among-operands this 1))))))
  78.  
  79. (def SqrtWithNegationIfNan
  80. (OperationFactory
  81. #(if (> % 0)
  82. (Math/sqrt (double %))
  83. (* (Math/sqrt (Math/abs (double %))) -1)
  84. )
  85. "sqrt"
  86. (fn [this v]
  87. (Divide (diff (nth-among-operands this 0) v)
  88. (Multiply (Constant 2) (SqrtWithNegationIfNan (nth-among-operands this 0))))
  89. )))
  90.  
  91. (def Sqrt
  92. (OperationFactory
  93. #(Math/sqrt (Math/abs (double %)))
  94. "sqrt"
  95. (fn [this v]
  96. (diff (SqrtWithNegationIfNan (nth-among-operands this 0)) v)
  97. )))
  98.  
  99. (def Square
  100. (OperationFactory
  101. #(* % %)
  102. "square"
  103. (fn [this v]
  104. (diff (Multiply (nth-among-operands this 0) (nth-among-operands this 0)) v)
  105. )))
  106.  
  107. (def obj-operations {'+ Add
  108. '- Subtract
  109. '* Multiply
  110. '/ Divide
  111. 'negate Negate
  112. 'sqrt Sqrt
  113. 'square Square
  114. })
  115.  
  116. (defn parseList [s]
  117. (if (list? s)
  118. (apply (get obj-operations (first s)) (map parseList (rest s)))
  119. (if (number? s)
  120. (Constant s)
  121. (Variable (str s)))))
  122. (def parseObject #(parseList (read-string %)))
  123.  
  124. ;(pr (evaluate (diff (Square (Subtract (Variable "x") (Variable "y"))) "x") {"z" 1.0, "x" 1.0, "y" 1.0}))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement