31
\$\begingroup\$

Program A outputs program B's code when run, and B outputs A's source.

Requirements:

  • Only one language across both programs
  • Programs are different. One program that outputs itself does not qualify.
  • Both programs are non-empty, or at least 1 byte in length. Trailing newlines in both source and output are ignored
  • stdin is closed. Do not read anything (so you can't read the source and manipulate it). Output goes to stdout.
    Edit: stdin is connected to /dev/null. You can order it be closed if clarified.
  • Do not use random functions.

Additional:

  • Give explanations if possible

Score is total length. Trailing newline does not count if it doesn't affect the program.

\$\endgroup\$
4
  • 8
    \$\begingroup\$ Related. \$\endgroup\$ Jul 4, 2017 at 11:42
  • 6
    \$\begingroup\$ "Do not use random functions."? What do you mean? Functions that output a random number? \$\endgroup\$
    – Mr. Xcoder
    Jul 4, 2017 at 13:00
  • 3
    \$\begingroup\$ Related Folklore \$\endgroup\$
    – Ray
    Jul 4, 2017 at 22:53
  • \$\begingroup\$ I'm pretty sure you don't really mean stdin is closed. This blows up some environments as stdin becomes a duplicate of the first opened file. Anyway, if you don't fix it I will abuse it. \$\endgroup\$
    – Joshua
    Jul 5, 2017 at 21:04

21 Answers 21

19
\$\begingroup\$

CJam, 13 + 13 = 26 bytes

{sYZe\"_~"}_~

Try it online!

Outputs

{sZYe\"_~"}_~

Explanation

{       e# Standard quine framework, leaves a copy of the block on the stack
        e# for the block itself to process.
  s     e# Stringify the block.
  YZe\  e# Swap the characters at indices 2 and 3, which are Y and Z themselves.
  "_~"  e# Push the "_~" to complete the quine.
}_~

Since e\ is commutative in its second and third operand, the other program does exactly the same, swapping Z and Y back into their original order.

\$\endgroup\$
17
\$\begingroup\$

CJam, 11 + 13 = 24 11 + 12 = 23 bytes

"N^_p"
N^_p

Try it online!

Outputs:

"N^_p
"
N^_p

The output has 13 bytes, but:

Trailing newline does not count if it doesn't affect the program.

So I changed the space to a newline to take advantage of that.

It is based on the shortest CJam proper quine:

"_p"
_p

And N^ is to xor the string with a newline, which adds a newline if there isn't a newline, and remove it if there is, for a string that each character is unique.

I think I have seen that quine in the quine question, but I couldn't find it.

\$\endgroup\$
3
  • \$\begingroup\$ +1 for having two different sized programs, unlike all other answers so far. Edit: as soon as I can vote again.. reached the limit last vote >.> \$\endgroup\$ Jul 4, 2017 at 22:12
  • \$\begingroup\$ Good for being different in length. \$\endgroup\$
    – iBug
    Jul 5, 2017 at 0:27
  • \$\begingroup\$ "I think I have seen that quine in the quine question, but I couldn't find it." It's only mentioned in the GolfScript answer. \$\endgroup\$ Jul 6, 2017 at 9:31
12
\$\begingroup\$

RProgN 2, 3 + 3 = 6 bytes

First program:

0
1

Try it online!

Second program:

1
0

Try it online!

-2 thanks to Martin Ender.

\$\endgroup\$
5
  • 7
    \$\begingroup\$ You can save two bytes by switching languages: tio.run/##Kyooyk/P0zX6/9@Ay/D/fwA \$\endgroup\$ Jul 4, 2017 at 13:00
  • \$\begingroup\$ @MartinEnder Ooh right I forgot RProgN 2 exhibits such behavior...btw I dunno if it's still that buggy. \$\endgroup\$ Jul 4, 2017 at 13:03
  • 11
    \$\begingroup\$ I don't know anything about RProgN except that this behaviour exists. \$\endgroup\$ Jul 4, 2017 at 13:04
  • \$\begingroup\$ @MartinEnder Author of RProgN here, just ask if you need anything clarified! \$\endgroup\$
    – ATaco
    Jul 6, 2017 at 0:14
  • \$\begingroup\$ @ATaco Well, I'd have asked you to clarify the downvote but I don't think you can... \$\endgroup\$ Jul 6, 2017 at 9:42
6
\$\begingroup\$

C, 95 + 95 = 190 bytes

Thanks to @immibis for saving 16*2 bytes!

char*s="char*s=%c%s%c;main(i){i=%d^1;printf(s,34,s,34,i);}";main(i){i=1^1;printf(s,34,s,34,i);}

Try it online!

Outputs:

char*s="char*s=%c%s%c;main(i){i=%d^1;printf(s,34,s,34,i);}";main(i){i=0^1;printf(s,34,s,34,i);}

Try it online!

Which outputs:

char*s="char*s=%c%s%c;main(i){i=%d^1;printf(s,34,s,34,i);}";main(i){i=1^1;printf(s,34,s,34,i);}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Why not just call it C always, and rely on i changing to make the program different? C is shorter than %c \$\endgroup\$
    – user253751
    Jul 5, 2017 at 1:34
  • \$\begingroup\$ @immibis Yes, you are right, that suffices perfectly. \$\endgroup\$
    – Steadybox
    Jul 6, 2017 at 21:18
6
\$\begingroup\$

Javascript, 67+67=134 bytes

1st program:

alert(eval(c="`alert(eval(c=${JSON.stringify(c)},n=${+!n}))`",n=0))

2nd program:

alert(eval(c="`alert(eval(c=${JSON.stringify(c)},n=${+!n}))`",n=1))

This is based on Herman Lauenstein's answer to Tri-interquine

Javascript (Invalid - reads source code), 75+75=150 61+61=122 58+58=116 50+50=100 bytes

saved 20 bytes thanks to Tushar, 6 bytes thanks to Craig Ayre, and saved 16 bytes thanks to kamoroso94

1st program:

f=_=>alert(("f="+f).replace(0,a=>+!+a)+";f()");f()

2nd program:

f=_=>alert(("f="+f).replace(1,a=>+!+a)+";f()");f()

Swaps the 1s with the 0s and vice versa. They both do the same thing, just producing different output because of their source code.

\$\endgroup\$
8
  • 1
    \$\begingroup\$ Let's save few bytes. f.toString() => (''+f), (0|1) => 0|1, (a,b) => a resulting in f=()=>("f="+(''+f).replace(/0|1/g,a=>a==0?1:0)+";f()");f() \$\endgroup\$
    – Tushar
    Jul 5, 2017 at 11:38
  • \$\begingroup\$ You can use an unused parameter to save a couple of bytes f=_=> and remove parens from the replace callback as @Tushar suggested: a=>+!+a \$\endgroup\$
    – Craig Ayre
    Jul 5, 2017 at 14:17
  • \$\begingroup\$ Replace "f="+(f+"") with ("f="+f) for -3 bytes. \$\endgroup\$
    – kamoroso94
    Jul 6, 2017 at 17:36
  • \$\begingroup\$ Replace /0|1/g and /1|0/g with 0 and 1 respectively for -5 bytes. \$\endgroup\$
    – kamoroso94
    Jul 6, 2017 at 17:43
  • \$\begingroup\$ Did you run it? It works like this f=_=>alert(("f="+f).replace(0,a=>+!+a)+";f()");f(). \$\endgroup\$
    – kamoroso94
    Jul 6, 2017 at 17:53
5
\$\begingroup\$

Python 2, 63+63 = 126 bytes

Try it online

First program:

A='A=%r;print A[:23]%%A+A[29:35]23:29]';print A[:23]%A+A[23:29]

outputs:

A='A=%r;print A[:23]%%A+A[29:35]23:29]';print A[:23]%A+A[29:35]

Second program:

A='A=%r;print A[:23]%%A+A[29:35]23:29]';print A[:23]%A+A[29:35]

Outputs:

A='A=%r;print A[:23]%%A+A[29:35]23:29]';print A[:23]%A+A[23:29]
\$\endgroup\$
4
\$\begingroup\$

JavaScript (JsShell), 35 + 34 = 69 bytes

1:

(f=x=>print(`(f=${f})(${-x})`))(-1)

2:

(f=x=>print(`(f=${f})(${-x})`))(1)
\$\endgroup\$
3
\$\begingroup\$

Underload, 32+32=64 bytes

(a~a*(:^)*S)(~(a)~a*^a(:^)**S):^

Try it online!

(~(a)~a*^a(:^)**S)(a~a*(:^)*S):^

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Mathematica, 43 + 44 = 87 bytes

(Print[#1[#0[#1, -#2]]] & )[HoldForm, -1 1]

and

(Print[#1[#0[#1, -#2]]] & )[HoldForm, -(-1)]
\$\endgroup\$
2
  • \$\begingroup\$ Tested it on my computer and the output of the second one only has -1 at the end, not -1 1. \$\endgroup\$ Jul 13, 2017 at 5:31
  • 1
    \$\begingroup\$ @numbermaniac I wrote these codes in the text-based interface. It seems that they don't work in notebooks. \$\endgroup\$
    – alephalpha
    Jul 13, 2017 at 6:09
3
\$\begingroup\$

asmutils sh, 16+16 bytes, abusing the "stdin is closed" rule.

#!/bin/sh
tr x y

Since stdin is closed and sh will open its script to the first available handle (rather than move it to a high numbered handle like modern shells do), tr ends up reading from a copy of the script without having ever opened it.

This interquine is payload capable but inserting a payload is tricky.

In addition, this original version abuses some crazy bug in the ancient kernel I used in those days. (I don't know what's up with that kernel--I found out later on it had different major and minor numbers for devices too.) If you fix the ABI changes that broke asmutils the interquine still won't work. I forget if asmutils sh has exec or not, but if it does, this is a modern version:

exec dd skip=0 | tr x y

This abuses a deliberate bug in asmutils dd; it has a performance optimization it calls llseek for skip if it can, but to save a byte it passes SEEK_SET rather than SEEK_CUR. This results in garbage on stderr but the interquine on stdout. Asmutils dd doesn't have an option to suppress the stderr spam.

\$\endgroup\$
5
  • \$\begingroup\$ Will this work if stdin in connected to /dev/null instead? Anyway, good job! \$\endgroup\$
    – iBug
    Jul 5, 2017 at 23:51
  • \$\begingroup\$ @iBug: Nope. Depends utterly on stdin closed and the fact that asmutils sh isn't linked against libc and so doesn't inherit the auto-repair code in libc. \$\endgroup\$
    – Joshua
    Jul 6, 2017 at 1:26
  • \$\begingroup\$ Do you need the #!/bin/sh? \$\endgroup\$ Jul 9, 2017 at 21:31
  • \$\begingroup\$ @CalculatorFeline: that depends on the exactness of your definition of something else. \$\endgroup\$
    – Joshua
    Jul 9, 2017 at 23:01
  • \$\begingroup\$ Generally, shebangs are not counted, so this would be 6 bytes. \$\endgroup\$ Jul 10, 2017 at 15:48
2
\$\begingroup\$

><>, 16 + 16 = 32 bytes

":1-}80.r   !#o#

and

#o#!   r.08}-1:"

Try it online!

This works by using a jump in the program, the first programs jump will skip the reverse of the stack (if it reversed the stack it would be a quine). The second program doesn't skip the reverse but was it's already reversed by the flow of the program then it'll create the originial.

This code will end in an error.

\$\endgroup\$
1
\$\begingroup\$

Common Lisp, 58 characters

#1=(let((*print-circle* t))(print'(write '#1# :circle t)))

... or 24 characters if you don't mind assuming *print-circle* is globally set to T :

#1=(print '(write '#1#))

The printed representation of the code is read as a cyclic structure, where #1# points back to the cons cell following #1=. We quote programs so that they are not executed. Since *print-circle* is T, the REPL takes care to emit such reader variables during printing; this is what the above code prints, and returns:

#1=(write '(print '#1#)) 

When we evaluate the above code, it prints:

#1=(print '(write '#1#))

If you want to stick with the default value for *print-circle*, which is NIL in a conforming implementation, then you'll have to rebind the variable temporarily:

#1=(let((*print-circle* t))(print'(write '#1# :circle t)))

Inside the body of the LET, we print things with *print-circle* being T. So we obtain:

#1=(write
    '(let ((*print-circle* t))
       (print '#1#))
    :circle t) 

As you can see, the new program doesn't rebind *print-circle*, but since we are using write, which is the low-level function called by print, we can pass additional arguments such as :circle. The code then works as expected:

#1=(let ((*print-circle* t))
     (print '(write '#1# :circle t)))

However, you need to execute the above programs as a script, not inside a REPL, because even though you print things while taking care of circular structures, both write and print also returns the value being printed; and in a default REPL, the value is also being printed, but outside of the dynamic context where *print-circle* is T.

\$\endgroup\$
1
\$\begingroup\$

RProgN 2, 7 + 7 = 14 bytes

I wanted to try to show off a better usage of RProgN, rather than just abusing print orders...

1
«\1\-

and...

0
«\1\-

Explained

1   # Push the constant, 1. (Or 0, depending on the program)

«\1\-
«       # Define a function from this to the matching », in this case there isn't any, so define it from this to the end of the program, then continue processing.
 \      # Flip the defined function under the constant.
  1\-   # Get 1 - Constant.

Because this prints the stack upside down, the new constant is printed first, then the stringifed version of the function is printed.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

LOGO, 65 + 66 = 131 bytes

apply [(pr ? ` [[,? ,-?2]] )] [[apply [(pr ? ` [[,? ,-?2]] )]] 1]

and

apply [(pr ? ` [[,? ,-?2]] )] [[apply [(pr ? ` [[,? ,-?2]] )]] -1]
\$\endgroup\$
1
\$\begingroup\$

Python 3, 74+74=148 bytes

a='a=%r;b=%r;print(b%%(b,a))';b='b=%r;a=%r;print(a%%(a,b))';print(b%(b,a))

and

b='b=%r;a=%r;print(a%%(a,b))';a='a=%r;b=%r;print(b%%(b,a))';print(a%(a,b))

i don't understand it either

\$\endgroup\$
1
\$\begingroup\$

><>, 12 + 12 = 24 bytes

'3d*!|o|!-c:

and

':c-!|o|!*d3

Try it online!

Both programs use a wrapping string literal to add the code to the stack, then produce the ' command through different methods. When printing the stack it pushes the code backwards, however the ' stays at the front. There are several variations that produce the '; 3d*, d3*, 00g, :c- when paired with 3d* and :9- when paired with 00g.

A too similar solution to post, in Befunge-98 for 13*2 bytes

"2+ck, @,kc+2
\$\endgroup\$
1
\$\begingroup\$

Stax, 18+20=38 bytes

"Vn|^34bL"Vn|^34bL

Run and debug online!

"Vn|^34bL
"Vn|^34bL

Run and debug online!

Explanation

Added for completeness. Port of @jimmy23013's CJam answer. Toggles the newlines using set xor.

\$\endgroup\$
0
0
\$\begingroup\$

Javascript (ES6), 36 + 36 = 72 bytes

Program 1:

f=n=>('f='+f).replace(/4|5/g,n=>n^1)

Program 2:

f=n=>('f='+f).replace(/5|4/g,n=>n^1)

These programs work by cloning themselves and replace 5 with 4 and 4 with 5

console.log((
    f=n=>('f='+f).replace(/4|5/g,n=>n^1)
)())
console.log((
    f=n=>('f='+f).replace(/5|4/g,n=>n^1)
)())

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Since this is tagged quine, this is what would usually be considered a "cheating quine", since it reads its own source. Not sure what OP's decision on that is, but they are usually not allowed. \$\endgroup\$
    – Stephen
    Jul 4, 2017 at 13:11
0
\$\begingroup\$

Klein, 26 24 bytes

<:3+@+3<:"

Try it online!

Explanation

This works the same as my Klein Quine, where it prints the source backwards followed by a ", the last one got away with this by being palindromic, so all we need to do is make it non-palindromic without damaging its functionality. By switching < and : we were able to do this without interfering with functionality.

\$\endgroup\$
0
\$\begingroup\$

Pari/GP, 36 + 36 = 72 bytes

(f=(x)->print1("(f="f")("1-x")"))(1)

Try it online!

(f=(x)->print1("(f="f")("1-x")"))(0)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Python 2, 42 + 43 = 85 bytes,

Python 3, 44 + 45 = 89 bytes

Python 2 (85 bytes):

a='a=%r,-%d;print a[0]%%a',-1;print a[0]%a    # Program 1: 42 bytes
a='a=%r,-%d;print a[0]%%a',--1;print a[0]%a   # Program 2: 43 bytes

Try it online!

Python 3 (89 bytes):

a='a=%r,-%d;print(a[0]%%a)',-1;print(a[0]%a)    # Program 1: 44 bytes 
a='a=%r,-%d;print(a[0]%%a)',--1;print(a[0]%a)   # Program 2: 45 bytes

Try it online!

How it works? :

I started from the standard a='a=%r;print(a%%a)';print(a%a) quine. But instead of having a equal only to a string, I have a equal to a tuple regrouping a sting and an integer. I add the char - in front of my integer:

  • if it is equal to -1, -%d will be equal to --1
  • if it is equal to --1, %d will evaluate it as 1 so -%d will be equal to -1

Edits:

I found aferwards this pretty elegant solution. Not better, just elegant. (58 + 58 = 116 bytes):

a="print'a=%r;exec a.lower()'%a.swapcase()";exec a.lower() # 58 char each
a="PRINT'A=%R;EXEC A.LOWER()'%A.SWAPCASE()";exec a.lower() # 116 bytes in total

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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