Skip to content

Instantly share code, notes, and snippets.

@jmgimeno
Created March 17, 2012 18:59
Show Gist options
  • Save jmgimeno/2064173 to your computer and use it in GitHub Desktop.
Save jmgimeno/2064173 to your computer and use it in GitHub Desktop.
Rock, paper, scissors
;; Una de les formes de trobar bones solucions és trobar bones
;; estructures de dades de partida.
;; Aquí has de representar tres coses:
;; 1. Regles del joc (quina cosa guanya a què)
;; 2. Resultats d'una ronda
;; 3. Resulatats d'un torneig
;; Formes de representar 1.
;; Per les elecciones, poden usar keywords y dir que tenim :paper
;; :scissors i :rock (:lizard i :spock queda com exercici) i per
;; indicar qui guanya podem fer servi p.e. un conjunt de parelles:
(def rpsRules #{ [:paper :rock] [:rock :scissors] [:scissors :paper] })
;; Per a un resultat modem fer servir un maya entre jugador i elecció, per exemple:
(def result1 {:jugador1 :rock :jugador2 :paper})
;; Per a un torneig una llista de resultats (no valdría un conjunt
;; doncs podem tenor dos jugadors que en rondes diferents escullen el
;; mateix).
;; La funció aquesta retorna el jugador que ha guanyat o nil en cas
;; d'empat.
;; Una primera solució
(defn whoWins [result]
(let [[player1 player2] (keys result)
[choice1 choice2] (vals result)]
(cond
(rpsRules [choice1 choice2]) player1
(rpsRules [choice2 choice1]) player2
:else nil)))
;; Un refinament (bastant més funcional):
(defn whoWins [result]
(let [choices (vals result)]
(if (apply not= choices)
((if (rpsRules choices) first second) (keys result)))))
;; Ara poodem saber
(whoWins result1)
(def tournament [{:jugador1 :rock :jugador2 :paper}
{:jugador1 :paper :jugador2 :paper}
{:jugador1 :scissors :jugador2 :paper}
{:jugador1 :scissors :jugador2 :rock}
{:jugador1 :rock :jugador2 :paper}])
;; Com estem fent servir estructures estàndar, podem aplicar les
;; funcions predefinides per veure el resultat de totes les rondes:
(map whoWins tournament)
;; O comptabilitzar els resultats
(frequencies (map whoWins tournament))
;; O agafar els resultats que no han acabat en empat
(filter whoWins tournament)
;; O les victòries del :jugador1
(filter #(= :jugador1 (whoWins %)) tournament)
;; NOTA: La setmana vinent veurem tota aquesta sintaxi (espero).
;; Com whoWins depèn de les regles de joc, podem fer una funció que
;; rebi com a paràmetre les regles de joc i retorni una funció tal que
;; donat un resultat dihui qui guanya:
;; Forma 1:
(defn makeWhoWins [rules]
(fn [result]
(let [choices (vals result)]
(if (apply not= choices)
((if (rules choices) first second) (keys result))))))
(def rpsWhoWins (makeWhoWins rpsRules))
;; Forma 2:
(defn generalizedWhoWins [rules result]
(let [choices (vals result)]
(if (apply not= choices)
((if (rules choices) first second) (keys result)))))
(def rpsWhoWins (partial generalizedWhoWins rpsRules))
;; Una vegada generalitzades les coses, podem canviar de joc.
;; P.e. daus (guanya qui treu el dau més alt)
(def diceTournament [{:player1 3 :player2 3}
{:player1 1 :player2 4}
{:player1 6 :player2 1}
{:player1 3 :player2 2}])
(defn diceRules [[dice1 dice2]]
(> dice1 dice2))
(def diceWhoWins (makeWhoWins diceRules))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment