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}}==