Rock Paper Scissors (Sorta) Quine

9

1

Create three programs, which we'll call Rock, Paper, and Scissors.

Each program must be unique, and accept input.

If a program gets any input which is not one of the programs Rock, Paper or Scissors, it must print itself.

RPS style, the programs will each print one of the following four outputs:

  1. "win" if the running program beats the program that is being input
  2. "lose" if the running program loses against the program that is being input
  3. "tie" if the input is equal to the source code of the running program
  4. The source code of the running program itself for any other input (including an empty input)

General rules:

  • The three programs can be in any language. Rock can be in a different language from Paper: same for any other pair.
  • They are not restricted by size.
  • They must print through STDOUT or closest equivalent, and must print strings or closest equivalent. They must not print to STDERR.
  • They need not be full programs. They can be functions, if you wish to get rid of the stuff needed in a program, like C's #includes.

This is a challenge, where your score is determined by the sum of the programs' sizes. The person with the lowest score wins.
If two people have the same score, the person whose largest program by bytes out of the set Rock, Paper, Scissors is smaller wins.

Andrew

Posted 2019-11-27T19:30:12.497

Reputation: 2 067

5I recommend sum instead of average, no need to divide or include annoying thirds. Then, this could just be tagged [tag:code-golf] and [tag:quine] – Redwolf Programs – 2019-11-27T19:48:28.723

I thought the scores would get too boringly small with sums, but then again, that applies to thirds too, – Andrew – 2019-11-27T20:22:28.717

So far both answers have interpreted "If given any input other than what will be specified below, each prints itself" to mean they are allowed to output win/lose/tie for certain inputs that are not the other program. If you intend to keep this requirement I suggest you further reinforce it. – FryAmTheEggman – 2019-11-27T20:42:21.653

1I took the liberty of formatting the challenge description a bit, since it was a bit hard to read with all separated lines instead of paragraphs. If I accidentally removed or misinterpret something, feel free to change it again. And one question: you state the three programs can be in any language, does this mean the Rock program could be in a different language than the Paper program as well? Or you simply mean all languages are open to compete, but the Rock, Paper, and Scissor programs should still be in that same language? – Kevin Cruijssen – 2019-11-28T07:50:37.360

Is a full program mandatory, or could we also do a (lambda) function? Usually functions are allowed by default to get rid of all the fuss every program need mandatory (like interface M{static void main(String[]a){...}} for Java instead of v->{...} if it's a function. – Kevin Cruijssen – 2019-11-28T08:11:33.710

Answers

3

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).

Matthew Jensen

Posted 2019-11-27T19:30:12.497

Reputation: 713

I don't think this is valid - you are supposed to output your source no matter what the input is, unless it is the other programs: "If given any input other than what will be specified below, each prints itself". – FryAmTheEggman – 2019-11-27T20:40:24.423

Right, I see now. As long as the input doesn't contain 'ti' it'll print itself. – Matthew Jensen – 2019-11-27T21:00:25.933

@EmbodimentofIgnorance It's mentioned as "lose" the first time in the spec, then again as Lose (without quotations). Also it just feels a lot nicer as all lowercase :) – Matthew Jensen – 2019-11-27T21:07:00.943

The question is pretty hard to read, sorry about that. And I also agree it feels a lot nicer as all lowercase :) – Embodiment of Ignorance – 2019-11-27T21:14:09.160

Would removing spaces in your latest version's starting list provide a helpful -9? – Corsaka – 2019-11-28T09:25:48.193

@Corsaka I would if I could, but the quines generated include spaces due to Python's representation of a list, so I have to leave them in. – Matthew Jensen – 2019-11-28T19:36:47.053

2

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 explanation:

  • The var s contains the unformatted source code
  • %s is used to put this String into itself with s.format(...)
  • %c, %1$c, and 34 are used to format the double-quotes
  • s.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

Kevin Cruijssen

Posted 2019-11-27T19:30:12.497

Reputation: 67 575

1

05AB1E, 219 207 201 (three times 73 69 67) bytes

Rock program:

2"D34çý…·‡§ÍŽ°#sª¤¸YF¤₁DÀ‡ª}IQZ_ªÏ"D34çý…·‡§ÍŽ°#sª¤¸YF¤₁DÀ‡ª}IQZ_ªÏ

Paper program is similar, but with leading 5 instead of 2.
Scissor program is similar, but with leading 6 instead of 2.

Similar transliterate approach as my Java answer.

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 explanation:

Uses the default 14 bytes quine program of @OliverNi, since it's easy to modify (even though there is a shorter 05AB1E quine).

This quine will:

2               # Push a 2 (or 5 or 6 depending on the program used)
 "D34çý"        # Push the trailing part of the source-code as string
         D      # Duplicate this string on the stack
          34ç   # Push a 34 as ASCII character (a double quote '"')
             ý  # Join the three values on the stack by this
                # (and output the result implicitly)

Try it online.

Challenge part:

I've combined this with the following if-else construction:

…·‡§ÍŽ°         # Push dictionary string "tie lose win"
       #        # Split it on spaces: ["tie","lose","win"]
        sª      # Swap, and append the quine-string we created
¤               # Get the last item (the quine we added) of the list (without popping)
 ¸              # Wrap it into a list
  YF            # Loop 2 times (the default value of variable `Y` is 2):
    ¤           #  Get the last item of the list (without popping)
     ₁D         #  Push builtin 256 twice
       À        #  Rotate the digits once towards the left: 562
        ‡       #  Transliterate the 256 to 562 in the string
         ª      #  And append it to the list
  }IQ           # After the loop: check for each value if it's equal to the input
     Z          # Get the maximum (without popping) to check if any are truthy
      _         # Inverse this boolean (0 becomes 1; 1 becomes 0)
       ª        # Append it to the list of truthy/falsey values
        Ï       # Leave the strings of the earlier created list at the truthy positions

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why …·‡§ÍŽ° is "tie lose win".

Kevin Cruijssen

Posted 2019-11-27T19:30:12.497

Reputation: 67 575

0

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:

  1. Rock
  2. Scissors
  3. Paper

Nick Kennedy

Posted 2019-11-27T19:30:12.497

Reputation: 11 829