Created
June 25, 2013 22:43
-
-
Save sortega/5863141 to your computer and use it in GitHub Desktop.
Rock, paper, scissors in Scala (and extended to Spock and frieds FTW)
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
package pogame | |
object ExtendedGame extends POGame { | |
sealed trait ExtendedHand extends POrdered[ExtendedHand] { | |
val weaknesses: Seq[ExtendedHand] | |
def defeatedBy(other: POrdered[ExtendedHand]): Boolean = weaknesses.contains(other) | |
} | |
case object Rock extends ExtendedHand { val weaknesses = Seq[ExtendedHand](Paper, Spock) } | |
case object Paper extends ExtendedHand { val weaknesses = Seq[ExtendedHand](Scissors, Lizard) } | |
case object Scissors extends ExtendedHand { val weaknesses = Seq[ExtendedHand](Rock, Spock) } | |
case object Spock extends ExtendedHand { val weaknesses = Seq[ExtendedHand](Paper, Lizard) } | |
case object Lizard extends ExtendedHand { val weaknesses = Seq[ExtendedHand](Rock, Scissors) } | |
type Hand = ExtendedHand | |
} |
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
package pogame | |
import org.scalatest.FlatSpec | |
import org.scalatest.matchers.MustMatchers | |
import pogame.ExtendedGame._ | |
class ExtendedGameTest extends FlatSpec with MustMatchers { | |
"Extended game" must "honor Spock powers" in { | |
ExtendedGame.round(1.0, "Sheldon" -> Spock, "Leonard" -> Scissors, "Howard" -> Rock) must be (Map( | |
"Sheldon" -> 1.0, | |
"Leonard" -> 0.0, | |
"Howard" -> 0.0 | |
)) | |
} | |
} |
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
package pogame | |
import scala.collection.immutable | |
/** | |
* Hands have a partial order defined by the defeatedBy function. | |
*/ | |
trait POrdered[T] { | |
def defeatedBy(other: POrdered[T]): Boolean | |
} | |
/** | |
* Partial ordered game (rock-paper-scissors like). | |
*/ | |
abstract class POGame { | |
type Hand <: POrdered[Hand] | |
/** | |
* Given the hands of the players distribute a price | |
* @param amount Amount to distribute between the winners | |
* @param hands Player hands | |
* @return What get every player | |
*/ | |
def round(amount: Double, hands: Map[Any, Hand]): Map[Any, Double] = { | |
def isNotDefeated(hand: Hand) = !hands.values.exists(hand.defeatedBy(_)) | |
val undefeated = hands.collect { case (player, hand) if isNotDefeated(hand) => player } | |
val winners = if (undefeated.isEmpty) hands.keySet else undefeated | |
uniformDistribution(hands.keySet, 0) ++ uniformDistribution(winners, amount) | |
} | |
def round(amount: Double, hands: (Any, Hand)*): Map[Any, Double] = round(amount, hands.toMap) | |
private def uniformDistribution(keys: Iterable[Any], amount: Double) = { | |
val share = amount / keys.size | |
keys.map(key => (key, share)).toMap | |
} | |
} |
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
package pogame | |
object SimpleGame extends POGame { | |
type Hand = SimpleHand | |
sealed abstract class SimpleHand extends POrdered[SimpleHand] { | |
val weakness: SimpleHand | |
def defeatedBy(other: POrdered[SimpleHand]): Boolean = weakness == other | |
} | |
case object Rock extends SimpleHand { val weakness = Paper } | |
case object Paper extends SimpleHand { val weakness = Scissors } | |
case object Scissors extends SimpleHand { val weakness = Rock } | |
} |
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
package pogame | |
import org.scalatest.FlatSpec | |
import org.scalatest.matchers.MustMatchers | |
import pogame.SimpleGame._ | |
class SimpleGameTest extends FlatSpec with MustMatchers { | |
"A simple game round" must "be won by a non defeated hand" in { | |
SimpleGame.round(1.0, "winner" -> Rock, "loser" -> Scissors) must be (Map( | |
"winner" -> 1.0, | |
"loser" -> 0.0 | |
)) | |
} | |
it must "distribute the price among winners" in { | |
SimpleGame.round(1.0, "winner1" -> Paper, "winner2" -> Paper, "loser" -> Rock) must be (Map( | |
"winner1" -> 0.5, | |
"winner2" -> 0.5, | |
"loser" -> 0.0 | |
)) | |
} | |
it must "distribute the price in a tie" in { | |
SimpleGame.round(3.0, "p1" -> Rock, "p2" -> Paper, "p3" -> Scissors) must be (Map( | |
"p1" -> 1.0, | |
"p2" -> 1.0, | |
"p3" -> 1.0 | |
)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment