Skip to content

Instantly share code, notes, and snippets.

@danneu
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danneu/559875d801d1ca61776b to your computer and use it in GitHub Desktop.
Save danneu/559875d801d1ca61776b to your computer and use it in GitHub Desktop.
Crazy vs. Psychic
(ns casino.core)
;; Strategies ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; A strategy is a function applied to a sequence of turns.
(defn crazy-strat1
"Random pick."
[_]
(rand-nth [true false]))
(defn psychic-strat1
"Do nothing."
[_]
nil)
;; Schema ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; - CrazyPick: true | false
;; - PsychicPick: nil | true | false
;; - Turn: [CrazyPick, PsychicPick]
;; - Game: Sequence of 10 Turns
;; - Winner: :crazy | :psychic
;; Returns nil | :crazy | :psychic
(defn get-winner [turns]
(when-let [last-turn (last turns)]
(let [[crazy-pick psychic-pick] last-turn]
(cond
;; Psychic guesses Crazy's pick.
(= crazy-pick psychic-pick)
:psychic
;; Psychic guesses wrong
(and (not (nil? psychic-pick)) (not= crazy-pick psychic-pick))
:crazy
;; Crazy has 4 in a row
(let [last-four-crazy-picks (map first (take-last 4 turns))]
(when (= 4 (count last-four-crazy-picks))
(every? #(= % (first last-four-crazy-picks)) last-four-crazy-picks)))
:crazy
;; 10 turns have passed and crazy hasn't won
(= 10 (count turns))
:psychic
;; Psychic doesn't pick and Crazy doesn't have 4 in a row
true
nil
))))
;; Tests ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(assert (nil? (get-winner [[true nil]])))
(assert (= :psychic (get-winner [[true true]])))
(assert (= :crazy (get-winner [[true false]])))
(assert (= :crazy (get-winner [[true nil] [true nil] [true nil] [true nil]])))
(assert (= :psychic
(get-winner [[true nil] [true nil] [false nil] [true nil] [false nil]
[true nil] [true nil] [false nil] [true nil] [false nil]])))
;; Simulation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn simulate-game [crazy-strat psychic-strat]
(loop [turns []]
(let [crazy-pick (crazy-strat turns)
psychic-pick (psychic-strat turns)
turn [crazy-pick psychic-pick]
turns (conj turns turn)]
(if-let [winner (get-winner turns)]
winner
(recur turns)))))
;; Winner is :crazy | :psychic
(defn get-reward
"Returns [CrazyReward, PsychicReward]"
[winner]
(if (= :crazy winner)
[1 -1]
[-1 0.98]))
(let [num-games 1000000]
(let [winners (repeatedly num-games #(simulate-game crazy-strat1 psychic-strat1))
outcomes (frequencies winners)
;; Rewards and Expected Return
[crazy-reward psychic-reward] (->> (map get-reward winners)
(apply map +))
crazy-return (+ 1 (double (/ crazy-reward num-games)))
psychic-return (+ 1 (double (/ psychic-reward num-games)))
]
{:total-games num-games
:crazy-games (double (/ (:crazy outcomes) num-games))
:psychic-games (double (/ (:psychic outcomes) num-games))
:crazy-return crazy-return
:psychic-return psychic-return}))
;; Outcomes where Crazy picks randomly and Psychic always passses:
;;
;;=> {:total-games 1000000,
;; :crazy-games 0.465025,
;; :psychic-games 0.534975,
;; :crazy-return 0.93005,
;; :psychic-return 1.059250500000658}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment