29
\$\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\$
  • 8
    \$\begingroup\$ Related. \$\endgroup\$ – Martin Ender Jul 4 '17 at 11:42
  • 5
    \$\begingroup\$ "Do not use random functions."? What do you mean? Functions that output a random number? \$\endgroup\$ – Mr. Xcoder Jul 4 '17 at 13:00
  • 2
    \$\begingroup\$ Related Folklore \$\endgroup\$ – Ray Jul 4 '17 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 '17 at 21:04

20 Answers 20

18
\$\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\$
  • \$\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\$ – Kevin Cruijssen Jul 4 '17 at 22:12
  • \$\begingroup\$ Good for being different in length. \$\endgroup\$ – iBug ......................... Jul 5 '17 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\$ – Martin Ender Jul 6 '17 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\$
  • 7
    \$\begingroup\$ You can save two bytes by switching languages: tio.run/##Kyooyk/P0zX6/9@Ay/D/fwA \$\endgroup\$ – Martin Ender Jul 4 '17 at 13:00
  • \$\begingroup\$ @MartinEnder Ooh right I forgot RProgN 2 exhibits such behavior...btw I dunno if it's still that buggy. \$\endgroup\$ – Erik the Outgolfer Jul 4 '17 at 13:03
  • 11
    \$\begingroup\$ I don't know anything about RProgN except that this behaviour exists. \$\endgroup\$ – Martin Ender Jul 4 '17 at 13:04
  • \$\begingroup\$ @MartinEnder Author of RProgN here, just ask if you need anything clarified! \$\endgroup\$ – ATaco Jul 6 '17 at 0:14
  • \$\begingroup\$ @ATaco Well, I'd have asked you to clarify the downvote but I don't think you can... \$\endgroup\$ – Erik the Outgolfer Jul 6 '17 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\$
  • 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\$ – immibis Jul 5 '17 at 1:34
  • \$\begingroup\$ @immibis Yes, you are right, that suffices perfectly. \$\endgroup\$ – Steadybox Jul 6 '17 at 21:18
5
\$\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\$
  • 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 '17 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 '17 at 14:17
  • \$\begingroup\$ Replace "f="+(f+"") with ("f="+f) for -3 bytes. \$\endgroup\$ – kamoroso94 Jul 6 '17 at 17:36
  • \$\begingroup\$ Replace /0|1/g and /1|0/g with 0 and 1 respectively for -5 bytes. \$\endgroup\$ – kamoroso94 Jul 6 '17 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 '17 at 17:53
4
\$\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\$

Mathematica, 43 + 44 = 87 bytes

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

and

(Print[#1[#0[#1, -#2]]] & )[HoldForm, -(-1)]
\$\endgroup\$
  • \$\begingroup\$ Tested it on my computer and the output of the second one only has -1 at the end, not -1 1. \$\endgroup\$ – numbermaniac Jul 13 '17 at 5:31
  • \$\begingroup\$ @numbermaniac I wrote these codes in the text-based interface. It seems that they don't work in notebooks. \$\endgroup\$ – alephalpha Jul 13 '17 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\$
  • \$\begingroup\$ Will this work if stdin in connected to /dev/null instead? Anyway, good job! \$\endgroup\$ – iBug ......................... Jul 5 '17 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 '17 at 1:26
  • \$\begingroup\$ Do you need the #!/bin/sh? \$\endgroup\$ – CalculatorFeline Jul 9 '17 at 21:31
  • \$\begingroup\$ @CalculatorFeline: that depends on the exactness of your definition of something else. \$\endgroup\$ – Joshua Jul 9 '17 at 23:01
  • \$\begingroup\$ Generally, shebangs are not counted, so this would be 6 bytes. \$\endgroup\$ – CalculatorFeline Jul 10 '17 at 15:48
2
\$\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\$
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\$

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

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
\$\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\$
  • 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 '17 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\$

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.