Interquine - Two programs that output each other in a loop

29

2

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.

iBug

Posted 2017-07-04T11:39:04.477

Reputation: 2 477

8Related. – Martin Ender – 2017-07-04T11:42:26.663

5"Do not use random functions."? What do you mean? Functions that output a random number? – Mr. Xcoder – 2017-07-04T13:00:33.517

2Related Folklore – Ray – 2017-07-04T22:53:38.360

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. – Joshua – 2017-07-05T21:04:55.677

Answers

18

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.

Martin Ender

Posted 2017-07-04T11:39:04.477

Reputation: 184 808

17

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.

jimmy23013

Posted 2017-07-04T11:39:04.477

Reputation: 34 042

+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 >.> – Kevin Cruijssen – 2017-07-04T22:12:13.670

Good for being different in length. – iBug – 2017-07-05T00:27:50.680

"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. – Martin Ender – 2017-07-06T09:31:29.990

12

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.

Erik the Outgolfer

Posted 2017-07-04T11:39:04.477

Reputation: 38 134

7

You can save two bytes by switching languages: https://tio.run/##Kyooyk/P0zX6/9@Ay/D/fwA

– Martin Ender – 2017-07-04T13:00:00.317

@MartinEnder Ooh right I forgot RProgN 2 exhibits such behavior...btw I dunno if it's still that buggy. – Erik the Outgolfer – 2017-07-04T13:03:37.317

11I don't know anything about RProgN except that this behaviour exists. – Martin Ender – 2017-07-04T13:04:49.353

@MartinEnder Author of RProgN here, just ask if you need anything clarified! – ATaco – 2017-07-06T00:14:12.157

@ATaco Well, I'd have asked you to clarify the downvote but I don't think you can... – Erik the Outgolfer – 2017-07-06T09:42:14.050

6

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);}

Steadybox

Posted 2017-07-04T11:39:04.477

Reputation: 15 798

1Why not just call it C always, and rely on i changing to make the program different? C is shorter than %c – user253751 – 2017-07-05T01:34:19.233

@immibis Yes, you are right, that suffices perfectly. – Steadybox – 2017-07-06T21:18:29.253

5

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.

SuperStormer

Posted 2017-07-04T11:39:04.477

Reputation: 927

1Let'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() – Tushar – 2017-07-05T11:38:44.427

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 – Craig Ayre – 2017-07-05T14:17:04.090

Replace "f="+(f+"") with ("f="+f) for -3 bytes. – kamoroso94 – 2017-07-06T17:36:00.867

Replace /0|1/g and /1|0/g with 0 and 1 respectively for -5 bytes. – kamoroso94 – 2017-07-06T17:43:13.777

Did you run it? It works like this f=_=>alert(("f="+f).replace(0,a=>+!+a)+";f()");f(). – kamoroso94 – 2017-07-06T17:53:09.730

oh, never mind. – SuperStormer – 2017-07-06T17:54:50.893

I don't think that this is is a valid solution, since it reads it's own source code (using String.prototype.toString or "f="+f), which is a standard loophole in questions tagged quine. – Herman L – 2017-07-07T11:44:04.467

@HermanLauenstein I added a valid solution based on your answer to Tri-interquine – SuperStormer – 2017-07-07T19:05:00.243

4

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]

Dead Possum

Posted 2017-07-04T11:39:04.477

Reputation: 3 256

4

JavaScript (JsShell), 35 + 34 = 69 bytes

1:

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

2:

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

tsh

Posted 2017-07-04T11:39:04.477

Reputation: 13 072

3

Mathematica, 43 + 44 = 87 bytes

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

and

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

alephalpha

Posted 2017-07-04T11:39:04.477

Reputation: 23 988

Tested it on my computer and the output of the second one only has -1 at the end, not -1 1. – numbermaniac – 2017-07-13T05:31:25.280

@numbermaniac I wrote these codes in the text-based interface. It seems that they don't work in notebooks. – alephalpha – 2017-07-13T06:09:25.377

3

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.

Joshua

Posted 2017-07-04T11:39:04.477

Reputation: 3 043

Will this work if stdin in connected to /dev/null instead? Anyway, good job! – iBug – 2017-07-05T23:51:43.367

@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. – Joshua – 2017-07-06T01:26:06.477

Do you need the #!/bin/sh? – CalculatorFeline – 2017-07-09T21:31:16.780

@CalculatorFeline: that depends on the exactness of your definition of something else. – Joshua – 2017-07-09T23:01:24.797

Generally, shebangs are not counted, so this would be 6 bytes. – CalculatorFeline – 2017-07-10T15:48:01.207

2

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!

Madison Silver

Posted 2017-07-04T11:39:04.477

Reputation: 139

1

LOGO, 65 + 66 = 131 bytes

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

and

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

user202729

Posted 2017-07-04T11:39:04.477

Reputation: 14 620

1

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.

coredump

Posted 2017-07-04T11:39:04.477

Reputation: 6 292

1

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

Teal pelican

Posted 2017-07-04T11:39:04.477

Reputation: 1 338

1

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!

ATaco

Posted 2017-07-04T11:39:04.477

Reputation: 7 898

1

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

aaay aaay

Posted 2017-07-04T11:39:04.477

Reputation: 71

1

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

Jo King

Posted 2017-07-04T11:39:04.477

Reputation: 38 234

1

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.

Weijun Zhou

Posted 2017-07-04T11:39:04.477

Reputation: 3 396

0

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

Herman L

Posted 2017-07-04T11:39:04.477

Reputation: 3 611

2Since this is tagged [tag: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. – Stephen – 2017-07-04T13:11:27.160

0

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.

Post Rock Garf Hunter

Posted 2017-07-04T11:39:04.477

Reputation: 55 382

0

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!

alephalpha

Posted 2017-07-04T11:39:04.477

Reputation: 23 988