Rock Paper Scissors (Sorta) Quine
Python 3, 273, 489, 429 bytes
Rock:
r=['tie', 'lose', 'win'];s="i=input();t=[f'r={r[n:]+r[:n]};s={s!r};exec(s)'for n in[0,1,2]];print(i in t and r[i.find('t')//7]or t[0])";exec(s)
Try it online against itself!
Try it online against Paper!
Try it online against Scissors!
Try it online against rubbish!
Paper:
r=['win', 'tie', 'lose'];s="i=input();t=[f'r={r[n:]+r[:n]};s={s!r};exec(s)'for n in[0,1,2]];print(i in t and r[i.find('t')//7]or t[0])";exec(s)
Try it online against itself!
Try it online against Scissors!
Try it online against Rock!
Try it online against garbage!
Scissors:
r=['lose', 'win', 'tie'];s="i=input();t=[f'r={r[n:]+r[:n]};s={s!r};exec(s)'for n in[0,1,2]];print(i in t and r[i.find('t')//7]or t[0])";exec(s)
Try it online against itself!
Try it online against Rock!
Try it online against Paper!
Try it online against trash!
The same as the previous version, but check that the input exactly matches the source code of one of the programs.
Try it online (together)!
Old (invalid) version
Rock:
s="print(['tie','lose','win','s='+repr(s)+';exec(s)',''][input().find('ti')//7-1])";exec(s)
Paper:
s="print(['win','tie','lose','s='+repr(s)+';exec(s)',''][input().find('ti')//7-1])";exec(s)
Scissors:
s="print(['lose','win','tie','s='+repr(s)+';exec(s)',''][input().find('ti')//7-1])";exec(s)
Try it online!
Three almost identical programs (all with 91 bytes), the only difference is the order of the win/tie/lose, which each program uses the position of the 'tie'
to determine the result from it's own ordering.
As pointed out, these programs are invalid, as they will only print out themselves if the input doesn't contain 'ti' (or the 'ti' is in a certain place).
Java 10, 1716 (three time 572) bytes
Rock program:
interface R{static void main(String[]a){var s="interface R{static void main(String[]a){var s=%c%s%1$c;System.out.print((s=s.format(s,34,s)).equals(a[0])?%1$ctie%1$c:t(s).equals(a[0])?%1$close%1$c:t(t(s)).equals(a[0])?%1$cwin%1$c:s);}static String t(String s){var r=%1$c%1$c;for(int b:s.getBytes())r+=(char)(b==82?80:b==80?90:b==90?82:b);return r;}}";System.out.print((s=s.format(s,34,s)).equals(a[0])?"tie":t(s).equals(a[0])?"lose":t(t(s)).equals(a[0])?"win":s);}static String t(String s){var r="";for(int b:s.getBytes())r+=(char)(b==82?80:b==80?90:b==90?82:b);return r;}}
The Paper program is similar, except with both R
replaced with P
.
The Scissor program is similar, except with both R
replaced with Z
(since S
is already used in String
).
Rock program:
- Try it online with itself as input.
- Try it online with the Paper program as input.
- Try it online with the Scissor program as input.
- Try it online with rubbish input.
Paper program:
- Try it online with itself as input.
- Try it online with the Scissor program as input.
- Try it online with the Rock program as input.
- Try it online with rubbish input.
Scizzor program:
- Try it online with itself as input.
- Try it online with the Rock program as input.
- Try it online with the Paper program as input.
- Try it online with rubbish input.
Explanation:
General quine explanation:
- The
var s
contains the unformatted source code %s
is used to put this String into itself withs.format(...)
%c
,%1$c
, and34
are used to format the double-quotess.format(s,34,s)
puts it all together
Challenge part:
I've added a separated method t
which will transliterate the characters RPZ
once clockwise in all three programs:
static String t(String s){ // Method with String as both parameter and return-type:
var r=""; // Result-String, starting empty
for(int b:s.getBytes()) // Loop over the characters of the input-String:
r+= // Append to the result-String:
(char)( // A character with codepoint:
b==82? // If the character is 'R':
80 // Change it to 'P' (codepoint 80)
:b==80? // Else-if the character is 'P':
90 // Change it to 'Z' (codepoint 90)
:b==90? // Else-if the character is 'Z':
82 // Change it to 'R' (codepoint 82)
: // Else:
b); // Leave the character unchanged
return r;} // Return the resulting String
When we're printing, it will do the following checks:
s.equals(a[0])? // If the program equals the input:
"tie" // Print "tie"
:t(s).equals(a[0])? // Else-if the program transliterated once equals the input:
"lose" // Print "lose"
:t(t(s)).equals(a[0])? // Else-if the program transliterated twice equals the input:
"win" // Print "win"
: // Else:
s // Print the source code-String itself
Jelly, 67 59 bytes × 3 = score of 177
“3ṛṾ;Ṫ,ɠ;µḣ2O_/2ị%3+1×ḣ2a2¦Ɱ3Ṿ€¤ċɗ/$ịṚ“win“lose“tie“1ịv”1ịv
Try it online!
A full program that reads a line from STDIN and returns tie
if given the same program, win
if given a program against which it can win and lose
if a program against which it loses. If provided with anything except one of the rock, paper or scissors programs it prints itself.
The digit in second position in the program indicates which it is:
- Rock
- Scissors
- Paper