n-level Ouroboros Quine

10

This 128-language quine ouroboros (a program which outputs a program in another language, which outputs a program in yet another language, (125 languages later), which outputs the original program) is pretty impressive. But unfortunately, it has a static number of iterations.

Write a program which outputs a program (not necessarily in another language, but it can be), which outputs a program, which outputs a program, etc., which after n iterations, outputs the original program for the first time (i.e. no intermediate program should be the same as the original, because otherwise a quine which ignores its input would work), where n is a non-negative integer provided as input. The input can't be just a number in the original source code (e.g. putting x = <the value of n> at the start of your program), it should be one of the following:

  1. Passed as a command-line argument
  2. Read from standard input
  3. Passed as an argument to a function, which returns/outputs the new program.

For intermediate stages in the ouroboros, your program can either be a fully-functioning program, or a function with no arguments, which, when called, will return/output the next one.

You may not read from the source file itself, or use any quine-like builtins (I don't think there are any which would do this, but there might be)

To be clear, if n = 0, the program should output its own source code.

If n = 1, the program should output a different program, which outputs the original source code.

And so on...

Fewest bytes wins!

Edit:

I should have written "For intermediate stages in the ouroboros, your program can either be a fully-functioning program with no input, or a function with no arguments". If your program outputs the next one in the chain, then waits for input, that's fine, but your program shouldn't need the original value of n.

Leo Tenenbaum

Posted 2019-07-03T11:42:07.123

Reputation: 2 655

Related, related. – Kevin Cruijssen – 2019-07-03T11:56:08.190

Can we 1 index n? So n = 1 means print source code, n = 2 means print code which will print source code etc. – Expired Data – 2019-07-03T12:46:14.510

1Will the iteration versions still have the initial input? So let's say my first input is 3, and I run the program it output. Will there still be an input 3, or no input at all? If there is no input, I guess we need to handle that in case something like getInput() is used without any input provided. Or can we let's say input something random that's unused for later iterations, to prevent errors for the getInput()? A.k.a. is the current Python answer valid? – Kevin Cruijssen – 2019-07-03T13:11:02.707

I suspect that what we're asked to do is, given an integer n, output a program that is the "initial program" of an ouroboros quine of n iterations, and that our answer shouldn't count as one of the n iterations. Is this correct? – Erik the Outgolfer – 2019-07-03T14:12:12.010

@KevinCruijssen I probably should have been more clear about that. The intermediate stages can't have input in any form. I guess if the program outputs the next one and then waits for input, that would be fine. – Leo Tenenbaum – 2019-07-03T22:37:03.653

@EriktheOutgolfer Yes... – Leo Tenenbaum – 2019-07-04T06:07:16.493

Answers

5

05AB1E, 28 bytes

-4 bytes + fix thanks to Kevin Cruijssen

"34çìD«s<©di®ì"34çìD«s<©di®ì

Try it online!


Explanation

This works by appending the remaining number to print to the front of the code, which means it's added to the stack the same way an input would be. In the base case of input of "0" it will not concatenate the 0 on the front.

Expired Data

Posted 2019-07-03T11:42:07.123

Reputation: 3 129

d is non-negative (>=0) instead of positive (>0). Problem is that to check d without popping it, you need to duplicate it first, but then it also need to be discarded on iteration 0"quinsting", otherwise it will output the duplicated 0. :( – Kevin Cruijssen – 2019-07-03T13:36:49.897

"34çìD«s<©di®ì"34çìD«s<©di®ì for 28 bytes perhaps (which is still pretty close to your intended approach)? (I'm afraid your current version for iteration 0"34çìD«s<Ddiì"34çìD«s<Ddiì outputs -1 from the Duplicate..) – Kevin Cruijssen – 2019-07-03T13:39:46.597

4

Runic Enchantments, 39 bytes

"3X4+kSql1=c*?S:1-}C'LA-}!i:0)2*?~!'´@

Try it online!

Would be 4 bytes shorter than 05AB1E using the same tactic if inputs where less than or equal to 10. But as we need to support arbitrarily large values, it gets more complicated.

Numerical value of n gets placed at the front and parsed as a continuous number literal using ´. "3X4+kSq is the basic quine code. If no value is present at the front, the stack length will only be 1 (the quine) otherwise 2 letting l1=d*? determine how to handle things from there.

  • If there is a value, S:1-}'LA2+-} runs: swap the value to the top, subtract 1, duplicate it, leaving a copy on the bottom of the stack, get the Log10 of that value times 100 (resulting in the value's own character length, plus 1 for the ´), remove that many characters from the end of the string (effectively truncating itself off the end, both where it isn't needed and because it has the wrong value). C is one byte shorter than 2+ and results in the same value.

  • If there is not a value, read one from input.

Regardless: :0)2*? duplicate and compare with zero.

  • If non-zero push ´.

  • If zero, pop the value. We can cheat using ! instead of 2? and save a byte because when ´ tries to execute the first byte it sees is non-numeric and immediately drops out of number mode at the same position.

Print entire stack top to bottom.

Draco18s no longer trusts SE

Posted 2019-07-03T11:42:07.123

Reputation: 3 053

3

Java 10, 145 bytes

n->{Long N=n;var s="n->{Long N=%s;var s=%c%s%2$c;return s.format(s,N>0?N-1+%2$cL%2$c:%2$cn%2$c,34,s);}";return s.format(s,N>0?N-1+"L":"n",34,s);}

Try it online and see the outputs of some iterations.

Explanation:

explanation:

  • The var s contains the unformatted source code
  • %s is used to put this String into itself with s.format(...)
  • %c, %1$c, and 34 are used to format the double-quotes
  • s.format(s,34,s) puts it all together

Challenge part:

The first lambda function takes a long input as parameter.

  • This is set in variable Long N=n; in the first iteration. Or in Long N=%s; for next iterations.
  • The ternary check N>0?N-1+"L":"n" will fill this %s with value N-1, appended with L since it's a long and to convert it to a String for the %s, if N is larger than 1. If N is 0 instead (initial input was 0 or this is the last iteration of the interquine-'loop'), it will fill this %s with the initial n instead.

Kevin Cruijssen

Posted 2019-07-03T11:42:07.123

Reputation: 67 575

The spec says intermediate outputs have to be a full program or a function without arguments – Embodiment of Ignorance – 2019-07-04T04:11:56.590

@EmbodimentofIgnorance I know, that's what I have. The first lambda function takes a long function-parameter, and the other lambda functions take an unused Void parameter, which I also always use for challenges stating to take no input because v-> is 1 byte shorter than ()->.

– Kevin Cruijssen – 2019-07-04T06:48:13.993

2

Jelly, 22 20 bytes

“Ṫ_1xẸƲ;Ṿ⁾v,⁾¥ ”v,¥ 

Try it online!

Try repeated calls of code

A full program that takes a single argument \$n\$. Main version outputs correctly to stdout but cannot be used as a function with a function return. The repeated calls version is 2 bytes longer but returns programmatically usable output. L

Nick Kennedy

Posted 2019-07-03T11:42:07.123

Reputation: 11 829

2

Haskell, 195 164 bytes

main=putStr(x++show x++"\na=")>>(getLine:cycle[pure$show$a-1])!!a>>=putStr
x="main=putStr(x++show x++\"\\na=\")>>(getLine:cycle[pure$show$a-1])!!a>>=putStr\nx="
a=0

Try it online!

This uses a pretty simple quine technique. We modify it with a variable a which is set to a number. If that number is zero (which it is at the start) we take input and output our source with a set to the input number. If a is not zero we output our source with a set to one less. This way a counts down to zero before outputting the original source.

Post Rock Garf Hunter

Posted 2019-07-03T11:42:07.123

Reputation: 55 382

2

R, 92 bytes

f=function(n=-1){gsub("\\s","",paste("f=",sub("-?\\d+",n-1,paste(deparse(f),collapse=""))))}

Try it online!

If deparse is deemed cheating, here’s an alternative:

R, 108 bytes

function(n=-1){s="function(n=%d){s=%s%s%2$s;sprintf(s,n-1,intToUtf8(34),s)}";sprintf(s,n-1,intToUtf8(34),s)}

Try it online!

Nick Kennedy

Posted 2019-07-03T11:42:07.123

Reputation: 11 829

1

Python 3.8 (pre-release), 60 56 55 53 bytes

lambda n=-1,s='lambda n=%d,s=%r:s%%(~-n,s)':s%(~-n,s)

Try it online!

-2 bytes thanks to Jo King

As of the 53 byte version, also works in Python 2 and Python 3.

negative seven

Posted 2019-07-03T11:42:07.123

Reputation: 1 931

The intermediate function doesn’t seem to be a full program or a function that takes no arguments. – Nick Kennedy – 2019-07-03T18:31:07.220

That walrus operator := is a welcome addition to Python, that's for sure. – mbomb007 – 2019-07-03T18:40:24.997

"For intermediate stages in the ouroboros, your program can either be a fully-functioning program, or a function *with no arguments*, which, when called, will return/output the next one." – mbomb007 – 2019-07-03T18:41:48.300

@NickKennedy Updated to comply with the spec, and coincidentally saved 4 bytes. – negative seven – 2019-07-03T19:25:06.833

153 bytes without using := – Jo King – 2019-07-04T02:33:26.480

1

C# (Visual C# Interactive Compiler), 112 bytes

void f(int n=-1){var s="void f(int n={2}){{var s={0}{1}{0};Write(s,(char)34,s,n-1);}}";Write(s,(char)34,s,n-1);}

Saved a lot of bytes thanks to @NickKennedy!

Try it online!

Embodiment of Ignorance

Posted 2019-07-03T11:42:07.123

Reputation: 7 014

The intermediate outputs are neither a full program nor a function that takes a single argument. Also I think you have some ns that should be ls. How about https://tio.run/##Sy7WTS7O/P@/LD8zRSFNIzOvRCHPVtdQs7ossUih2FYJRbzaqFazGipTbVBbbVgLJK3DizJLUjWKdTSSMxKLNI1NdIp18oAmWNfWKuGW@5@WXwQ2NdPWyMA60w6IdXU1q4E2aUI0@WTmpWqAFAIA

– Nick Kennedy – 2019-07-03T18:57:59.557

1

Perl 6, 44 bytes

<say '<',S{\d+}=get||0-1,'>~~.EVAL'>~~.EVAL

Try it online!

Takes input via standard input and returns a program where the only thing changed is the first number. Each subsequent program will then output the same program, except with that number decremented.

Jo King

Posted 2019-07-03T11:42:07.123

Reputation: 38 234