24 game: Difference between revisions

Content deleted Content added
Kazinator (talk | contribs)
Correction: the input is not an equation, but an arithmetic expression. An equation requires two sides joined by the = operator, which is explicitly disallowed.
Line 1,039: Line 1,039:
=={{header|Clojure}}==
=={{header|Clojure}}==
<lang Clojure>
<lang Clojure>
(ns rosettacode.24game)
(ns rosettacode.24game
; For printing lists, something that printf/format can't do AFAIK.

(:use [clojure.pprint :only (cl-format)]))
(defn gen-new-game-nums [amount] (repeatedly amount #(inc ( rand-int 9))))

(defn orderless-seq-eq? [seq1 seq2] (apply = (map frequencies (list seq1 seq2))))
(defn valid-input?
(defn valid-input?
"A rudimentary check for prefix-notation form."
"checks whether the expression is somewhat valid prefix notation
[in]
(+ 1 2 3 4) (+ 3 (+ 4 5) 6)
(->> in flatten pr-str (re-find #"^\(([0-9-+*/] )+[0-9]?\)$")))
this is done by making sure the only contents of the list are numbers operators and brackets

flatten gets rid of the brackets, so we just need to test for operators and integers after that"
[user-input]
(defn game-nums-&-input=
"Tests equality of the numbers entered with those generated by the game."
(if (re-find #"^\(([\d-+/*] )+\d?\)$" (pr-str (flatten user-input)))
[game-nums in]
true
(->> in flatten (filter integer?) set (= (set game-nums))))
false))


(def *luser* "you guessed wrong, or your input was not in prefix notation. eg: '(+ 1 2 3 4)'\n")
(defn game-numbers-and-user-input-same?
"input form: (+ 1 2 (+ 3 4))
tests to see if the numbers the user entered are the same as the ones given to them by the game"
[game-nums user-input]
(orderless-seq-eq? game-nums (filter integer? (flatten user-input))))


(def *start-prompt*
(defn win [] (println "you won the game!\n"))
"Your numbers are ~A. Your goal is ~D.
(defn lose [] (println "you guessed wrong, or your input was not in prefix notation. eg: '(+ 1 2 3 4)'\n"))
Use the numbers provided and the ops +,-,*,/ to reach ~:*~D.
(defn game-start [goal game-numbers] (do
Your input should be prefix notation: (- (+ 9 8 8) 1) or (* 3 (/ 2 3) 6).
(println "Your numbers are " game-numbers)
'q[enter]' to quit.")
(println "Your goal is " goal)
; ~A is for forms, ~D is for decimal integers, and ~:* jumps 1 back in the arguments
(println "Use the numbers and +*-/ to reach your goal\n")
(println "'q' to Quit\n")))


(defn play-game
(defn play-game
([] (play-game 24))
"typing in 'q' quits.
to play use (play-game) (play-game 24) or (play-game 24 '(1 2 3 4)"
([goal] (play-game goal (repeatedly 4 #(inc (rand-int 9)))))
([goal gns]
([] (play-game 24))
(cl-format true *start-prompt* goal gns)
([goal] (play-game goal (gen-new-game-nums 4)))
(let [input (read-line)
([goal game-numbers]
read (read-string input)]
(game-start goal game-numbers)
(let [input (read-line)
(if (and (valid-input? read)
input-as-code (read-string input)]
(game-nums-&-input= gns read)
(if (and (valid-input? input-as-code)
(try (= goal (eval input-read)) ; yes, eval is our friend
(catch Exception e (do (println *luser*) (play-game goal gns)))))
(game-numbers-and-user-input-same? game-numbers input-as-code)
(println "you won the game!\n")
(try (= goal (eval input-as-code)) (catch Exception e (do (lose) (play-game goal game-numbers)))))
(win)
(when (not= input "q")
(when (not (= input "q"))
(println *luser*)
(do (lose) (recur goal game-numbers)))))))
(recur goal gns))))))
</lang>
</lang>