# Score rock-paper-scissors

Given two string inputs of "Rock", "Paper", or "Scissors", determine the outcome of the RPS round. Output 1 if the first player wins, -1 if the second player wins, or 0 for a tie.

Rock Rock -> 0
Rock Paper -> -1
Rock Scissors -> 1
Paper Rock -> 1
Paper Paper -> 0
Paper Scissors -> -1
Scissors Rock -> -1
Scissors Paper -> 1
Scissors Scissors -> 0


You must use the exact strings "Rock", "Paper", and "Scissors" as inputs. You may choose whether the first players' choice is (consistently) given first or second. You may alternatively take them as a single input with a single-character or empty separator. The input is guaranteed one of the 9 possible pairings of the three choices in your input format.

The output should be a number 1, 0, or -1, or its string representation. Floats are fine. So are +1, +0, and -0.

Related: Coding an RPS game

var QUESTION_ID=106496,OVERRIDE_USER=20260;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/106496/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

• Does a single input with empty separator mean for example "rockpaper"? – Emigna Jan 11 '17 at 21:25
• @Emigna Yes, but capitalized as RockPaper. – xnor Jan 11 '17 at 21:26
• That was WAY more fun than I had anticipated, my lord there are some cool ways to do this. – Magic Octopus Urn Jan 11 '17 at 21:30
• Can the input be an array of the two strings? – Luis Mendo Jan 11 '17 at 22:33
• @LuisMendo Yes. – xnor Jan 11 '17 at 22:34

## Scala, 148 bytes

object R extends App{val t=Seq('R','P','S')
val(a,b)=(args(0)(0),args(1)(0))
print(if(a==b)0 else if(t.indexOf(a)%3==(t.indexOf(b)-1)%3)-1 else 1)}


Thankfully, since semicolons are required to separate multiple commands on the same line, Scala benefits from having formattable golf code!

In this golfing attempt I learned that you can replace

"somestring".charAt(index)


with

"somestring"(index)


because Scala lets you treat strings as arrays for the purpose of getting characters.

• This can be golfed immensely. For starters, you're allowed to do a function instead of a complete program in most challenges here, so instead of the whole object extends app thing and pulling from args, try something like: def g(a:Seq,b:Seq)=... – Ethan Jan 13 '17 at 19:54
• Additionally, you need not print the value. Returning it is sufficient, which is great when golfing Scala, since the return is free. And you can improve it even further by using the trick posted in the Groovy answer, which works almost identically in Scala. – Ethan Jan 13 '17 at 20:10

# C++, 98 bytes#

int main(int c,char*v[]){int a=v[2][0]-v[1][0];if(a%3==0)a=-a;if(a>1)a/=a;if(a<-1)a/=-a;return a;}


Could definitely be shortened, but I don't have that skill or knowledge. Enlightenment?

# GNU Sed, 39, 38 bytes

36 bytes code + 2 bytes for the "nr" flags

Golfed

/^(.+)\1/{a0
b}
/kP|rS|sR/{a-1
b}
a1


Test

>RPS() { echo "$1 => "sed -rnf rps.sed<<<$1; }

>RPS RockRock
RockRock => 0

>RPS RockPaper
RockPaper => -1

>RPS RockScissors
RockScissors => 1

>RPS PaperRock
PaperRock => 1

>RPS PaperPaper
PaperPaper => 0

>RPS PaperScissors
PaperScissors => -1

>RPS ScissorsRock
ScissorsRock => -1

>RPS ScissorsPaper
ScissorsPaper => 1



# ///, 87 bytes

/_/1\/\///Paper/p//Rock/r//Scissors/s// ///pr/_rs/_sp/_rp/-_sr/-_ps/-_pp/0//rr/0//ss/0/


Try it online!

## Ungolfed

/Paper/p//Rock/r//Scissors/s// //
/pr/1//rs/1//sp/1/
/rp/-1//sr/-1//ps/-1/
/pp/0//rr/0//ss/0/


## Clojure, 43 bytes

#(get[0 1 1](mod(-(count %)(count %2))6)-1)


Uses (length(arg_1) - length(arg_2)) % 6 as a lookup to [0 1 1] and returns -1 if it goes out of bounds.

# Clojure, 114 75 bytes

-39 bytes by accepting 2 parameters instead of parsing 1, and changing the "else" placeholder from :e to 0.

 (fn[[p][q]](let[d(-(int p)(int q))](cond(#{-1 -2 3}d)1(#{1 2 -3}d)-1 0 0)))


Ungolfed:

(defn rps-scorer [[p1] [p2]] ; Deconstruct out the first letters of each word
(let [d (- (int p1) (int p2))] ; And find the difference of their numeric values
(cond (#{-1 -2 3} d) 1 ; If it's a winning difference, return 1, else
(#{1 2 -3} d) -1 ; If it's a losing difference, return -1, else
:else 0))) ; return 0, because they're the same.


Totally naïve approach here. I found out if you subtract the ascii values of the first letter of each play, winning values will be -1, -2 and 3, and losing values will be 1, 2 and -3. I just check which set the plays fall into, then return based on membership.

# C#, 43 bytes

a=>b=>(a[0]-b[0])/3*2+Math.Sign(b[0]-a[0]);


C# treats characters like integers that you can add and subtract.

# SmileBASIC, 39 bytes

INPUT A$,B$?(67XOR LEN(A$*2+B$))MOD 3-1


A port of Dennis's algorithm. XOR and MOD are really long, I'm sure this could be made shorter.

# Perl 6,  63 54 40  39 bytes

{2>($_=[-] %(<Rock -1 Paper 0 Scissors 1>){@_})>-2??$_!!-.sign}


Try it

{3>($_=[R-] @_>>.substr(0,1)>>.ord)>-3??.sign!!-.sign}  Try it {3>($_=[R-] @_>>.ord)>-3??.sign!!-.sign}


Try it

{($_=[-](82 X<=>@_».ord)%3)>1??-1!!$_}


Try it

# C#, 28 bytes

(a,b)=>""[*a-*b+3]-2;


Contains unprintable characters, so here's a hex dump:

Turns out my solution is pretty similar to Dennis's Python 3 answer, but calculates the index differently. not anymore

This uses unsafe so the string inputs need to be put in char* first.

How it works:

// Delegate signature
unsafe delegate int Signature(char* c, char* z);

/*unsafe Signature Lambda = */ (a, b) =>
"\x1\x3\x3\x2\x1\x1\x3"               // The outcomes
[*a - *b + 3]                         // Index by subtracting value of first char of p2
// from p1, adding 3 so the result is >= 0
-2                                    // Subtract 2 to put in range [-1, 1]

• I think you ought to be including the unsafe term in your code, and so in the byte count. There is also a narrow consensus that 'untyped' lambdas are invalid, and you should include the types in the parameters, which C#ers should be aware of. – VisualMelon Jan 12 '17 at 13:03
• Based on that meta post, I don't think the types or unsafe are needed since both can be deduced. The problem clearly indicates the inputs are string types. The only string type in C# with the * prefix operator is char* which also implies unsafe. – milk Jan 12 '17 at 18:53
• The types can't be deduced by the compiler (or at least are not), and the compiler will just complain about a lack of unsafe context (which also requires a compiler argument, which is usually counted as well). – VisualMelon Jan 12 '17 at 19:20

# TI-Basic, 64 bytes

There is probably a shorter way but I'm not seeing it right now...

DelVar R1->P:2->S
Prompt Str1,Str2:1
If sum(not({~2,1}-sum(eval(sub(Str1,1,1)+"-"+sub(Str2,1,1
~1:Str1!=Str2


# TI-84 BASIC, 55 bytes

Prompt Str1,Str2
sub(Str1,1,1→Str3
sub(Str2,1,1
(Str3≠Ans)*(1-2not(inString("SPPRRS",Str3+Ans


I saved a byte by using Prompt instead of Input thanks to Timtech.

## Execution:

Input is given as two strings as prompted. The TI-84 does not have native lowercase letters.

prgmRPS
Str1=?"ROCK"
Str2=?"SCISSORS"

1


## C#, 48 bytes

(a,b)=>a==b?0:(a[0]>b[0])^(a[0]+b[0]==163)?-1:1;


## C 355 bytes

#define S strcmp f(char *a,char *b){*c[]={"Rock","Paper","Scissors"}; if((!S(a,c[0])&&!S(b,c[1]))||(!S(a,c[1])&&!S(b,c[2]))||(!S(a,c[2])&&!S(b,c[0]))==1 )puts("-1");if( (!S(a,c[0])&&!S(b,c[0]))||(!S(a,c[1])&&!S(b,c[1]))||(!S(a,c[2])&&!S(b,c[2]))==1 )puts("0");if( (!S(a,c[0])&&!S(b,c[2]))||(!S(a,c[1])&&!S(b,c[0]))||(!S(a,c[2])&&!S(b,c[1]))==1 )puts("1");}


Accept user inputs(argv[1],argv[2]) and pass it onto f(char *a, char *b); Here is the Ungolfed version:

 #define S strcmp
void f(char *a,char *b)
{
char *c[]={"Rock","Paper","Scissors"};
if( (!S(a,c[0])&&!S(b,c[1]))||(!S(a,c[1])&&!S(b,c[2]))||(!S(a,c[2])&&!S(b,c[0]))==1 )
puts("-1");
if( (!S(a,c[0])&&!S(b,c[0]))||(!S(a,c[1])&&!S(b,c[1]))||(!S(a,c[2])&&!S(b,c[2]))==1 )
puts("0");
if( (!S(a,c[0])&&!S(b,c[2]))||(!S(a,c[1])&&!S(b,c[0]))||(!S(a,c[2])&&!S(b,c[1]))==1 )
puts("1");
}


There must definitely be a way to shorten this! I don't know though.

@Timtech Hope i understood you right. This code works, but prints 0 even if the strings are not exact, not sure if that satisfies the specification.

#define S strcmp f(){printf("%d",(!S(a,c[0])&&!S(b,c[1])||!S(a,c[1])&&!S(b,c[2])||!S(a,c[2])&&!S(b,c[0]))?-1:(!S(a,c[0])&&!S(b,c[2])||!S(a,c[1])&&!S(b,c[0])||(!S(a,c[2])&&!S(b,c[1]) )?1:0));}

• Looks like there's lots of ways to golf this. Here's a tip, instead of having the if statements output -1, 0, or 1, have them store to var. Then initialize the var as 0 and drop the middle if statement, returning or outputting the value at the end. – Timtech Jan 12 '17 at 16:23

# Noodel, 21 bytes

1220200Ḷ2ėạȥḃ1€Ė⁻ạɲ⁻1


Try it:)

### How It Works

The first input is the first player:) It works by using the first character of both the string inputs then subtract them. Then using that result to index into an string to get the correct value.

The result from each game after subtracting the values of the first characters:

"Rock"     -> "Rock"     =  0
"Rock"     -> "Paper"    = -2
"Rock"     -> "Scissors" =  1
"Paper"    -> "Rock"     =  2
"Paper"    -> "Paper"    =  0
"Paper"    -> "Scissors" =  3
"Scissors" -> "Rock"     = -1
"Scissors" -> "Paper"    = -3
"Scissors" -> "Scissors" =  0


How each position in the string is used to correspond to which game:

[0] or [-7] = 1 => "Rock" -> "Rock", "Paper" -> "Paper", "Scissors" -> "Scissors"
[1] or [-6] = 2 => "Rock" -> "Scissors"
[2] or [-5] = 2 => "Paper" -> "Rock"
[3] or [-4] = 0 => "Paper" -> "Scissors"
[4] or [-3] = 2 => "Scissors" -> "Paper"
[5] or [-2] = 0 => "Rock" -> "Paper"
[6] or [-1] = 0 => "Scissors" -> "Rock"


Break down of the actual script:

1220200               # Pushes the string "1220200" onto the stack.

Ḷ2ėạȥḃ1€       # A loop that grabs the first character, turns it into a number, and then throws away the string.
Ḷ2             # Loop the following block two times.
ė            # Places what is on the top to the bottom (first loop is the string created before, second loop places the result of player two)
ạ           # Grabs the first element of the string.
ȥ          # Convert the string to a number as if it was a base 98 number.
ḃ1        # Remove the second item off of the stack.
€       # End of the loop.

Ė⁻     # Grabs what is at the bottom of the stack then subtracts what was on the top from that.
Ė      # Grabs what is at the bottom of the stack (which is the first number calculated (player two).
⁻     # Subtracts player one from player two producing the index into the string.

ạɲ⁻1 # Grabs an element from the string and decrements it by one to get the final result.
ạ    # Access the string based off of the number produced from the subtraction.
ɲ   # Turns that string into a number.
⁻1 # Subtracts one from that number.


# Common Lisp, 83 bytes

(setq c(- #1=(char-code(elt(read)0))#1#))(cond((= c 0)0)((member c'(1 2 -3))-1)(1))


Try it online!

The algorithm is ported from Carcigenicate’s answer.

# Zsh, 29 bytes

<<<${${:-{,,-,-}1}[#2-#1]:-0}


Try it online!

<<<${${:-{,,-,-}1}[#2-#1]:-0}
{,,-,-}1                # expands to the list (1 1 -1 -1)
${:- } # empty-fallback (anon parameter)${             [     ]   }    # index into list
#2-#1         # difference between each parameter's first character's codes
${ :-0} # if empty, substitute 0  This is similar to one of the CJam answers. However, since Zsh indexes from 0, we need the ${ :-0} empty fallback to handle the 'P' - 'P' => 0 case.

# C#, 151 bytes

public class P{public static void Main(string[]a){int v=(a[0][0]-a[1][0]);v=v==2?-1:v==-1?1:v==-2?1:v==0?0:v==1?-1:v==3?1:-1;System.Console.Write(v);}}


Try Online

# Rust, 110 107 bytes

fn r(a:&str,b:&str)->i8{let p=if a.as_bytes()[0]+b.as_bytes()[0]==163{(b,a)}else{(a,b)};p.1.cmp(&p.0)as i8}


Try it online!

# Ruby -n, 20 bytes

p\$_.to_i(30)/522%3-1
`

Try it online!

Take input in the form of "RockPaper", interpret it as a base 30 integer 18248834542947, divide by 522 rounding down to 34959453147, modulo 3 is 0, minus 1 is -1.