26
\$\begingroup\$

Write three different programs such that when any one program is provided as input to one of the other two, you get the source of the remaining program as output. More explicitly, given programs \$A\$, \$B\$, and \$C\$, where \$f(g)\$ denotes the output obtained from inputting the text of program \$g\$ into program \$f\$, all of the following must hold:

  • \$ A(B) = C \$
  • \$ A(C) = B \$
  • \$ B(A) = C \$
  • \$ B(C) = A \$
  • \$ C(A) = B \$
  • \$ C(B) = A \$

Rules and Scoring

  • This is , so the shortest program length total, in bytes wins.
  • Standard quine rules apply.
  • Each program must be at least one byte different from the other two
  • Each program can be in any language. Any number of them may share languages or each may use a different language.
  • Use any convenient IO format as long as each program uses a consistent convention.
    • Functions are allowed, as this counts as "any convenient IO".
  • The result of feeding a program its own source code is undefined
  • The result of feeding anything other than program text of either of the other two programs is undefined.
\$\endgroup\$
  • 1
    \$\begingroup\$ Do quine rules apply? Are functions allowed? \$\endgroup\$ – Arnauld Aug 18 at 22:22
  • \$\begingroup\$ @Arnauld Yes and yes. \$\endgroup\$ – Beefster Aug 18 at 22:41
  • 1
    \$\begingroup\$ @Shaggy of course. \$\endgroup\$ – Beefster Aug 19 at 15:21
  • 4
    \$\begingroup\$ Seeing the current answers, maybe I should have required that each program be in a different language... \$\endgroup\$ – Beefster Aug 19 at 15:22
  • 1
    \$\begingroup\$ I could have also required high Levenshtein distance, certain cases be reversed, and/or feeding the program itself outputting an empty string. It might also work as a form of code-bowling. \$\endgroup\$ – Beefster Aug 20 at 15:20

17 Answers 17

10
\$\begingroup\$

Pyth, 5 + 5 + 5 = 15 bytes

CxCz1
CxCz2
CxCx3

Try A(B), A(C), B(A), B(C), C(A), C(B) online!

Explanation

CxCz_
  Cz    # convert input from base-256 to int
 x  _   # xor 1, 2 or 3 based on program
C       # convert from int to base-256
| improve this answer | |
\$\endgroup\$
10
\$\begingroup\$

C, 243 240 180 132 57 bytes

f(int*v){ v[4]^=1;}
f(int*v){ v[4]^=2;}
f(int*v){ v[4]^=3;}

Try it online: A B C

The input program can be passed as a char* to the function f, and is implicitly converted to an int*.

-60 bytes thanks to @Neil
-48 bytes thanks to @Bubbler
-72 bytes thanks to @AZTECCO

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ *x=99-*x-i; saves 20 bytes per program, I think? \$\endgroup\$ – Neil Aug 18 at 23:27
  • 2
    \$\begingroup\$ 44 bytes per program using XOR. \$\endgroup\$ – Bubbler Aug 19 at 2:58
  • 1
    \$\begingroup\$ Maybe you can use a function instead for 28 bytes \$\endgroup\$ – AZTECCO Aug 19 at 16:37
  • 1
    \$\begingroup\$ I think 20 is also valid \$\endgroup\$ – AZTECCO Aug 19 at 20:34
  • 2
    \$\begingroup\$ @qwr That space is to use int* (instead of char*). \$\endgroup\$ – user202729 Aug 20 at 12:53
10
\$\begingroup\$

brainfuck, 33+34+35=102 bytes

Perhaps one of a few answers that has the length of the 3 programs not equal. (*)

+␀>>,<,[<+>,]<-----[+>>.<<].,[.,]
++␀>>,<,[<+>,]<-----[+>>.<<].,[.,]
+++␀>>,<,[<+>,]<-----[+>>.<<].,[.,]

Try it online!

The ␀ () represents a null character.

Alternatives:

  • +␀>,>,[<<+>>,]<<-----[+>.<].,[.,]
  • -␀>,>,[<<->>,]<<+++++[->.<].,[.,]

(*): The only one at the time of posting. BF is the only used language that doesn't have integer literal.


Explanation:

+             Set a cell (call this cell 1) to X (depends on the current program, may be 1, 2 or 3)
<NUL>         No operation
>,            Read the first byte of the input (must be a "+") and store it in cell 2
>,[<<+>>,]    Increment cell 1 by (-1+(the number of remaining "+" in the input until the <NUL>))
                (use cell 3 as temporary storage)
<<-----       Decrement cell 1 by 5
[+>.<]        Print (-(that many)) (cell 2) (must be +)
.             Print a NUL byte
,[.,]         Copies the rest of the input to the output
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ How does it work? \$\endgroup\$ – null Aug 20 at 13:03
  • \$\begingroup\$ @HighlyRadioactive ^ \$\endgroup\$ – user202729 Aug 20 at 13:18
  • \$\begingroup\$ Thank you! (That's probably the shortest explanation ever) \$\endgroup\$ – null Aug 20 at 13:19
9
+150
\$\begingroup\$

JavaScript + Python 3 + Bash, 938 bytes

JavaScript, 465 bytes

a=3-2-1//True;a=str(a);alert,eval,prompt=print,exec,input;String=JSON=__builtins__;JSON.stringify=repr;JSON.fromCharCode=chr
s=String.fromCharCode;j=JSON.stringify;r="t='tr '+s(48)+s(49)+' '+s(49)+s(48)";eval(r);d="alert([t,'a=3-2-'+a+'//True;a=str(a);alert,eval,prompt=print,exec,input;String=JSON=__builtins__;JSON.stringify=repr;JSON.fromCharCode=chr\\ns=String.fromCharCode;j=JSON.stringify;r='+j(r)+';eval(r);d='+j(d)+';eval(d)'][+(prompt()[2]<s(33))])";eval(d)

Python 3, 465 bytes

a=3-2-0//True;a=str(a);alert,eval,prompt=print,exec,input;String=JSON=__builtins__;JSON.stringify=repr;JSON.fromCharCode=chr
s=String.fromCharCode;j=JSON.stringify;r="t='tr '+s(48)+s(49)+' '+s(49)+s(48)";eval(r);d="alert([t,'a=3-2-'+a+'//True;a=str(a);alert,eval,prompt=print,exec,input;String=JSON=__builtins__;JSON.stringify=repr;JSON.fromCharCode=chr\\ns=String.fromCharCode;j=JSON.stringify;r='+j(r)+';eval(r);d='+j(d)+';eval(d)'][+(prompt()[2]<s(33))])";eval(d)

Bash, 8 bytes

tr 01 10

TIO links

Javascript(Bash)

Javascript(Python)

Python(Bash)

Python(Javascript)

Bash(Javascript)

Bash(Python)

For some reason, TIO doesn't understand Javascript's alert function, but you can try it in your browser console.

Explanation:

The JavaScript and Python codes are 1 byte apart. The only difference is that the JS code starts with a=3-2-1 where the Python code has a=3-2-0. This is a polyglot pseudo-quine. The output is almost identical to the source code, but if the source code has a 1 in that statement, the output has a 0, and vice versa. This is because the pseudo-quine puts the current value of a into the string that describes how a is initialized.

In other words, the JavaScript code constructs the Python code and vice versa, and it's completely arbitrary which one is considered JavaScript and which is considered Python. Both programs are valid in either language.

Here's the JS/Python code without the quine construction, and with spaces and line breaks to make it more readable:

a=3-2-1//True; a=str(a); alert,eval,prompt=print,exec,input; String=JSON=__builtins__; JSON.stringify=repr; JSON.fromCharCode=chr
s=String.fromCharCode; 
j=JSON.stringify; 
r="t='tr '+s(48)+s(49)+' '+s(49)+s(48)"; 
eval(r); 
d="alert([t, <pseudo-quine>][+(prompt()[2]<s(33))])";
eval(d)

The JavaScript version ignores all the redefinitions after // on the top line, and redefines the verbose String.fromCharCode and JSON.stringify functions to single characters. It then constructs the string tr 01 10 and the pseudo-quine and puts both in a list. To access the list, it checks whether the third character in the input is less than ! and casts the result to an integer with +(bool). If the input is tr 01 10 (or anything else with a space as the third character), this check is true and it prints the pseudo-quine. If the input is the Python code, this condition is false, and it prints tr 01 10.

The Python logic is identical, but it renames some functions and creates dummy JSON and String namespaces for compatibility with JavaScript. It also casts a to a string so Python won't complain about concatenation. The redefinitions are possible because // is a comment in JavaScript, but floor division in Python. a//True is the same as a//1, but I'm avoiding the use of 1 and 0 everywhere except the first statement.

Finally, tr 01 10 simply changes 0 to 1 and vice versa. This has the same effect as running the JS/Python code with the other version as input.

I initially chose Python and Javascript because they have a lot of overlapping syntax and // made it easy to add compatibility logic, but I ended up having to redefine more functions than I expected. There's probably a better pair of languages for this approach (maybe Python and Ruby?). I guess I could have cheated by using Python 2 and 3 as my "different languages", but that's hardly the most interesting approach :)

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ Nice work going for the bounty! We'll have to see what competition you run into. \$\endgroup\$ – Beefster Aug 23 at 21:40
3
\$\begingroup\$

Charcoal, 42 bytes

≔0η⭆θ⎇⊖κι⁻⁻³ηι
≔1η⭆θ⎇⊖κι⁻⁻³ηι
≔2η⭆θ⎇⊖κι⁻⁻³ηι

Try it online! Link shows A passed B and printing C. Explanation:

≔0η

Store either 0, 1 or 2 in a variable as appropriate.

⭆θ

Map over the parameter.

⎇⊖κι

Leave all characters except the second unchanged.

⁻⁻³ηι

Subtract the variable and the second character from 3.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Unicode), 30 bytes

(⍕3-0+⍎)@5
(⍕3-1+⍎)@5
(⍕3-2+⍎)@5

Try it online!

Three functions that change the 5th character (from the left, 1-based) from the input string. Link shows that all six requirements (f(g)≡h etc.) are satisfied.

(⍕3-n+⍎)@5  ⍝ All functions share the same format
(      )@5  ⍝ Apply to the 5th character only...
      ⍎       ⍝ Eval the character; m←0 or 1 or 2
  3-n+        ⍝ 3-(n+m)
 ⍕            ⍝ Stringify the above
| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 75 bytes (3 x 25)

Uses the same approach as most other answers.

// f1
s=>s.replace(/\d/,x=>x^1)

// f2
s=>s.replace(/\d/,x=>x^2)

// f3
s=>s.replace(/\d/,x=>x^3)

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ At time of writing the XOR approach seems to be in the minority; subtracting from 3 is currently slightly more popular. \$\endgroup\$ – Neil Aug 19 at 9:17
3
\$\begingroup\$

Python 3, 3*51 = 153 bytes Try it online!

x=input();print(x.replace(x[-4],str(int(x[-4])^1)))
x=input();print(x.replace(x[-4],str(int(x[-4])^2)))
x=input();print(x.replace(x[-4],str(int(x[-4])^3)))

Adapted @aidan0626 answer, got the same length


Although, this would return the actual function if in/out would be functions instead of programs.

def a(x):return b if x==c else c
def b(x):return c if x==a else a
def c(x):return a if x==b else b

works for inputs like c(c(c(b(a(c(a)))))) -> b

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Japt, 3*3 = 9 bytes

Uses the convenient I/O format of an array of characters.

o^1

Try it

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

J, 72 51 bytes

0&(3-+)&.".@{.,}.
1&(3-+)&.".@{.,}.
2&(3-+)&.".@{.,}.

Try it online!

-21 bytes thanks to Bubbler!

original

J, 72 bytes

a=.(0{3":@-0+8".@{])`8:`]}~
b=.(0{3":@-1+8".@{])`8:`]}~
c=.(0{3":@-2+8".@{])`8:`]}~

Try it online!

Heavily inspired by Bubbler's clever answer.

Note: -11 off stated TIO score for the a=., b=., c=. pieces, and line breaks

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ You don't need to count 2 newlines either, so your score is 72 bytes. Btw, I have 51 bytes answer by putting the 0/1/2 at the front of the code. Can you find it? \$\endgroup\$ – Bubbler Aug 19 at 6:10
  • 2
    \$\begingroup\$ Spoiler \$\endgroup\$ – Bubbler Aug 20 at 0:54
2
\$\begingroup\$

Raku, 11+11+11=45 33 bytes

{S{\d}+^=1}
{S{\d}+^=2}
{S{\d}+^=3}

Try it online!

Xors the first digit in the input with the current program's index.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Japt v2.0a0, 6 + 6 + 6 = 18 bytes

d\d_^1
d\d_^2
d\d_^3

Try it

Explanation

d\d_^?
d       // Replace occurrences
 \d     // of a digit
   _^?  // with the digit xor 1, 2 or 3 based on program
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

PHP, 30 * 3 = 90 bytes

$argn[9]=1^$argn[9];echo$argn;
$argn[9]=2^$argn[9];echo$argn;
$argn[9]=3^$argn[9];echo$argn;

Try it online!

Uses the XOR approach, because he's the space sheriff

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ I think only French people can get the joke. :-) I don't think Space Sheriff Gavan was named X-OR in any other country. \$\endgroup\$ – Arnauld Aug 19 at 11:30
  • 1
    \$\begingroup\$ @Arnauld I know but I couldn't resist, already quite old french people, I would add :D \$\endgroup\$ – Kaddath Aug 19 at 11:39
  • \$\begingroup\$ Yeah! Thanks for reminding me! :-p \$\endgroup\$ – Arnauld Aug 19 at 11:41
  • \$\begingroup\$ @Arnauld sorry, same for me obviously :D \$\endgroup\$ – Kaddath Aug 19 at 11:51
1
\$\begingroup\$

Python 2, 186 153 bytes

-33 bytes thanks to @Neil

x=raw_input();print x.replace(x[48],`int(x[48])^1`)
x=raw_input();print x.replace(x[48],`int(x[48])^2`)
x=raw_input();print x.replace(x[48],`int(x[48])^3`)

Example

Takes input from the user using raw_input() and changes the number after the ^ symbol and prints it out

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ The "standard quine rule" means you cannot read your own source code. But the challenge does not prevent you from reusing most of the code provided from the input. \$\endgroup\$ – Bubbler Aug 19 at 3:03
  • \$\begingroup\$ I fixed my answer \$\endgroup\$ – aidan0626 Aug 19 at 3:22
  • \$\begingroup\$ x=raw_input();print x.replace(x[-3],`3-int(x[-3])-0`) saves 9 bytes per program. \$\endgroup\$ – Neil Aug 19 at 9:09
  • \$\begingroup\$ Even better, using @Bubbler's other approach with 1, 2, 3 numbering: x=raw_input();print x.replace(x[-3],`int(x[-3])^1`) saves 11 bytes per program. \$\endgroup\$ – Neil Aug 19 at 9:13
  • 1
    \$\begingroup\$ it outputs x=raw_input();print x.replace(x[-2],`int(x[-2])^2`) but should output x=raw_input();print x.replace(x[-3],`int(x[-3])^2`). it outputs with index being -2 instead of -3 \$\endgroup\$ – Mukundan314 Aug 20 at 14:50
1
\$\begingroup\$

Befunge-98, 3 * 15 14 = 45 42 bytes

-1 * 3 bytes thanks to @Jo King!

0'c\~+-#;,#@~;
1'c\~+-#;,#@~;
2'c\~+-#;,#@~;

Try it online!

Uses the subtraction method.

Explanation

X'c\~+-#;,#@~;
X               # Push X (the number of the program, either 0, 1, or 2)
 'c             # Push 99
   \            # Swap 99 and X
    ~           # Get the first character of the input (which is 48+Y, where Y is the number of the second program)
     +          # Add (the stack now looks like [99, 48+X+Y])
      -         # Subtract 48+X+Y from 99, leaving 51-X-Y
       #;       # (skipped)
                # (begin loop)
         ,      # First iteration: Output 51-X-Y, the first character of the third program
          #@    # (skipped)
            ~   # Get the next character of the input
        ;    ;  # Jump to the start of the loop
         ,      # Output the character unchanged
                # (repeat)
            ~   # On EOF, reverse direction
           @    # End the program
 
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Lua, 64*3=192 bytes

print(((...):gsub('%d',load"return ('').char((...):byte()~1)")))

Try it online! (includes test cases)

Other two programs:

print(((...):gsub('%d',load"return ('').char((...):byte()~2)")))
print(((...):gsub('%d',load"return ('').char((...):byte()~3)")))

Use xor like many other programs

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Python 2, 123 bytes

lambda x:x.replace(x[-4],`int(x[-4])^1`)#
lambda x:x.replace(x[-4],`int(x[-4])^2`)#
lambda x:x.replace(x[-4],`int(x[-4])^3`)#

Try it online!

Note that the comment at the end is required since otherwise the index will have to be either -3 or 37 instead of -4 which will mess things up when replacing 3

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Shouldn't it be 123 bytes? Separate programs don't need newlines. \$\endgroup\$ – val says Reinstate Monica Aug 22 at 10:19
  • \$\begingroup\$ @valsaysReinstateMonica right, i forgot to update it after copying from tio \$\endgroup\$ – Mukundan314 Aug 22 at 13:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.