27
\$\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\$
6
  • 1
    \$\begingroup\$ Do quine rules apply? Are functions allowed? \$\endgroup\$
    – Arnauld
    Aug 18 '20 at 22:22
  • \$\begingroup\$ @Arnauld Yes and yes. \$\endgroup\$
    – Beefster
    Aug 18 '20 at 22:41
  • 1
    \$\begingroup\$ @Shaggy of course. \$\endgroup\$
    – Beefster
    Aug 19 '20 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 '20 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 '20 at 15:20

17 Answers 17

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

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Nice work going for the bounty! We'll have to see what competition you run into. \$\endgroup\$
    – Beefster
    Aug 23 '20 at 21:40
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
\$\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

\$\endgroup\$
7
  • 1
    \$\begingroup\$ *x=99-*x-i; saves 20 bytes per program, I think? \$\endgroup\$
    – Neil
    Aug 18 '20 at 23:27
  • 2
    \$\begingroup\$ 44 bytes per program using XOR. \$\endgroup\$
    – Bubbler
    Aug 19 '20 at 2:58
  • 1
    \$\begingroup\$ Maybe you can use a function instead for 28 bytes \$\endgroup\$
    – AZTECCO
    Aug 19 '20 at 16:37
  • 1
    \$\begingroup\$ I think 20 is also valid \$\endgroup\$
    – AZTECCO
    Aug 19 '20 at 20:34
  • 2
    \$\begingroup\$ @qwr That space is to use int* (instead of char*). \$\endgroup\$
    – DELETE_ME
    Aug 20 '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
\$\endgroup\$
3
  • \$\begingroup\$ How does it work? \$\endgroup\$
    – null
    Aug 20 '20 at 13:03
  • \$\begingroup\$ @HighlyRadioactive ^ \$\endgroup\$
    – DELETE_ME
    Aug 20 '20 at 13:18
  • \$\begingroup\$ Thank you! (That's probably the shortest explanation ever) \$\endgroup\$
    – null
    Aug 20 '20 at 13:19
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.

\$\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
\$\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!

\$\endgroup\$
1
  • \$\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 '20 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

\$\endgroup\$
2
\$\begingroup\$

Japt, 3*3 = 9 bytes

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

o^1

Try it

\$\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

\$\endgroup\$
2
  • \$\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 '20 at 6:10
  • 2
    \$\begingroup\$ Spoiler \$\endgroup\$
    – Bubbler
    Aug 20 '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.

\$\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
\$\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

\$\endgroup\$
4
  • 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 '20 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 '20 at 11:39
  • \$\begingroup\$ Yeah! Thanks for reminding me! :-p \$\endgroup\$
    – Arnauld
    Aug 19 '20 at 11:41
  • \$\begingroup\$ @Arnauld sorry, same for me obviously :D \$\endgroup\$
    – Kaddath
    Aug 19 '20 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

\$\endgroup\$
8
  • 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 '20 at 3:03
  • \$\begingroup\$ I fixed my answer \$\endgroup\$
    – aidan0626
    Aug 19 '20 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 '20 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 '20 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\$ Aug 20 '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
 
\$\endgroup\$
0
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

\$\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

\$\endgroup\$
2
  • \$\begingroup\$ Shouldn't it be 123 bytes? Separate programs don't need newlines. \$\endgroup\$ Aug 22 '20 at 10:19
  • \$\begingroup\$ @valsaysReinstateMonica right, i forgot to update it after copying from tio \$\endgroup\$ Aug 22 '20 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.