Last active
April 20, 2021 07:58
-
-
Save geoff-m/7ff37fae4efc6645fc42ed8f8f2dad2e to your computer and use it in GitHub Desktop.
How to tell who wins in rock paper scissors
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
enum RockPaperScissorsChoice | |
{ | |
Rock = 1, | |
Paper = 2, | |
Scissors = 4 | |
} | |
static string DescribeRockPaperScissorsResult(RockPaperScissorsChoice first, RockPaperScissorsChoice second) | |
{ | |
if (first == second) | |
return "Tie."; | |
if ((((int)first >> 1) | ((int)first << 2) & 5) == (int)second) | |
return $"{first} beats {second}."; | |
return $"{second} beats {first}."; | |
} | |
static void Test() { | |
Assert(RockPaperScissorsChoice.Rock, RockPaperScissorsChoice.Rock, "Tie."); | |
Assert(RockPaperScissorsChoice.Rock, RockPaperScissorsChoice.Paper, "Paper beats Rock."); | |
Assert(RockPaperScissorsChoice.Rock, RockPaperScissorsChoice.Scissors, "Rock beats Scissors."); | |
Assert(RockPaperScissorsChoice.Paper, RockPaperScissorsChoice.Rock, "Paper beats Rock."); | |
Assert(RockPaperScissorsChoice.Paper, RockPaperScissorsChoice.Paper, "Tie."); | |
Assert(RockPaperScissorsChoice.Paper, RockPaperScissorsChoice.Scissors, "Scissors beats Paper."); | |
Assert(RockPaperScissorsChoice.Scissors, RockPaperScissorsChoice.Rock, "Rock beats Scissors."); | |
Assert(RockPaperScissorsChoice.Scissors, RockPaperScissorsChoice.Paper, "Scissors beats Paper."); | |
Assert(RockPaperScissorsChoice.Scissors, RockPaperScissorsChoice.Scissors, "Tie."); | |
} | |
static void Assert(RockPaperScissorsChoice first, RockPaperScissorsChoice second, string expected) | |
{ | |
var actual = DescribeRockPaperScissorsResult(first, second); | |
if (actual == expected) | |
Debug.WriteLine($"PASS Expected: {expected} \tActual: {actual}"); | |
else | |
Debug.Fail($"FAIL Expected: {expected} \tActual: {actual}"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Theory of operation
As any schoolchild will tell you, the possible outcomes of a rock-paper-scissors game are described by a directed cyclic graph on three vertices, where each player choice is a vertex and the edges connect each choice to what it beats, or alternatively, to what beats it. Starting with such a graph, determining the winner between choices X and Y can then be done by following the edge from X and checking whether it takes you to Y. If it does, X wins (or X loses, depending on how you defined the graph). If X = Y, the outcome is a tie. If following the edge from X did not lead to Y and there was no tie, then Y must beat X (or X wins, depending on how you defined the graph). The funny idea that led to this code was to realize this traversal of the cycle using a bitwise rotation of a 3-bit integer. I submit it as a simultaneously obfuscated and succinct solution to this well-known toy problem.