Last active
August 29, 2015 14:00
-
-
Save danneu/559875d801d1ca61776b to your computer and use it in GitHub Desktop.
Crazy vs. Psychic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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