24 game/Solve: Difference between revisions
Content added Content deleted
No edit summary |
|||
Line 6: | Line 6: | ||
C.F: [[Arithmetic Evaluator]] |
C.F: [[Arithmetic Evaluator]] |
||
=={{header|Clojure}}== |
|||
The code: |
|||
<lang clojure>(use 'clojure.contrib.combinatorics) |
|||
(defn mult [a b] (if (and (number? a) (number? b)) (* a b) "NaN")) |
|||
(defn add [a b] (if (and (number? a) (number? b)) (+ a b) "NaN")) |
|||
(defn sub [a b] (if (and (number? a) (number? b)) (- a b) "NaN")) |
|||
(defn div [a b] (if (or (= b 0) (not (number? b)) (not (number? a))) "NaN" (/ (double a) (double b)))) |
|||
(defn nested-replace [l m] ;apply map 'm' to each element of seq. 'l' all the way down. |
|||
(cond |
|||
(= l '()) '() |
|||
(m (first l)) (concat (list (m (first l))) (nested-replace (rest l) m)) |
|||
(seq? (first l)) (concat (list (nested-replace (first l) m)) (nested-replace (rest l) m)) |
|||
true (concat (list (first l)) (nested-replace (rest l) m)))) |
|||
(defn format-solution [sol] ;change expressions to infix, return arithmetic symbols to normal |
|||
(let [rep-sym (fn [a] (cond (= a 'mult) '* (= a 'div) '/ (= a 'add) '+ (= a 'sub) '- true a))] |
|||
(cond |
|||
(number? sol) sol |
|||
(seq? sol) |
|||
(list (format-solution (second sol)) (rep-sym (first sol)) (format-solution (nth sol 2)))))) |
|||
(defn play24 [& digits] (count (map #(-> % format-solution println) |
|||
(let [operator-map-list (map (fn [a] {:op1 (nth a 0) :op2 (nth a 1) :op3 (nth a 2)}) |
|||
(selections '(mult add sub div) 3)) |
|||
digits-map-list |
|||
(map (fn [a] {:num1 (nth a 0) :num2 (nth a 1) :num3 (nth a 2) :num4 (nth a 3)}) |
|||
(permutations digits)) |
|||
patterns-list (list |
|||
'(:op1 (:op2 :num1 :num2) (:op3 :num3 :num4)) |
|||
'(:op1 :num1 (:op2 :num2 (:op3 :num3 :num4)))) |
|||
;Other patterns can be added here: (:op1 :num1 (:op2 (:op3 :num2 :num3) :num4)) |
|||
op-subbed (reduce concat '() ;flatten the list by one level |
|||
(map (fn [a] (map #(nested-replace a % ) operator-map-list)) patterns-list)) |
|||
full-subbed (reduce concat '() |
|||
(map (fn [a] (map #(nested-replace % a) op-subbed)) digits-map-list))] |
|||
(filter #(= (eval %) 24) full-subbed)))))</lang> |
|||
The first four functions are a bit of a silly hack to protect us from division by 0 (and preserve remainders in our division) in an exception-free manner. Their impact on performance is small. |
|||
The function <code>play24</code> works by substituting the given digits and the four operations into the two binary tree patterns (o (o n n) (o n n)) and (o n (o n (o n n))). The substitution is the 'hairy' part of the program: two pairs of nested maps (the function) are used to sub in first the operations and then the digits, which are matched into the tree patterns using maps (the datatype!) |
|||
Example use: |
|||
<pre>user=> (play24 '(5 6 7 8)) |
|||
((5 + 7) * (8 - 6)) |
|||
(6 * (5 + (7 - 8))) |
|||
(6 * (5 - (8 - 7))) |
|||
(6 * (7 + (5 - 8))) |
|||
(6 * (7 - (8 - 5))) |
|||
((6 * 8) / (7 - 5)) |
|||
(6 * (8 / (7 - 5))) |
|||
((7 + 5) * (8 - 6)) |
|||
((8 - 6) * (5 + 7)) |
|||
((8 - 6) * (7 + 5)) |
|||
((8 * 6) / (7 - 5)) |
|||
(8 * (6 / (7 - 5))) |
|||
12</pre> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |