Make an interweaving quine

17

Your task is to create a program that, when run, returns itself as output (this is known as a quine). However, this quine must, when it is copied n times, returns the quine, but with each of its characters duplicated in place n times, where n is a positive integer.

If your original program is Derp:

Derp -> Derp (must return itself as output to be a quine)

DerpDerp -> DDeerrpp
(the "Derp" is copied twice, so each character in the output has to be copied twice)

DerpDerpDerp -> DDDeeerrrppp
etc. etc.

Keep in mind you're allowed to have whitespace in your "base" program, but they are counted when "interweaving". Say your program is

Derp 
{newline}

(The newline signifies a trailing newline, and there's an extra space after the Derp). When duplicated to become

Derp 
Derp 
{newline}

You must output

DDeerrpp  
{newline}
{newline}

Keep in mind that there's 2 extra spaces after the DDeerrpp.

Rules and Specs:

  • Your program must contain at least two distinct characters (which implies that your code must be at least 2 bytes long).
  • Standard quine rules apply.

This is , so shortest code in bytes wins!

clismique

Posted 2016-12-28T05:18:22.397

Reputation: 6 600

1"Standard rules apply" - does that mean no reading the source code? – FlipTack – 2016-12-28T20:47:29.123

@FlipTack It does mean that - read the link for more information. – clismique – 2016-12-29T14:35:28.193

Answers

12

Fission, 6 bytes

'!+OR"

Try it online! Try two copies! Try three!

Explanation

This is just the Fission standard quine. It happens to work for this challenge, because Fission has explicit entry points into the program. In particular, by duplicating the program, we add another R which adds another atom (instruction pointer). Since the source code is toroidal, the effective code being executed doesn't change otherwise — to each atom, the code still looks the same locally. However, the atoms are executed in lock step, so that the things they print are interleaved and we get an additional copy of each character in the output.

For completeness' sake I'll just shortly reiterate how the program itself works. Regardless of whether we repeat the program or not (e.g. '!+OR"'!+OR"'!+OR"), each atom sees the following code:

R"'!+OR"'!+O

The " toggles string printing mode, so that the program starts by printing '!+OR directly to STDOUT, which is all of the quine except the quote. Then '! sets the atom's mass to the character code of !, + increments it, which gives ", and O prints it while simultaneously destroying the atom. The program then terminates, because there are no atoms left.

Martin Ender

Posted 2016-12-28T05:18:22.397

Reputation: 184 808

11

Python 2.7, 377 310 304 194 191 bytes!

This is my first golf, so I didn't expect it to be too good. But I thought the concept in the solution I came up with was somewhat funny, so I'm posting it anyway.

def f():
 import threading as T,inspect as i;global t,a,i
 try:t.cancel()
 except:a=0
 a+=1;t=T.Timer(1,d);t.start()
def d():print''.join(c*a for c in i.getsource(f)+i.getsource(d)+"f()")
f()

Indeed, this is a quine; you can try it here. It abuses the inspect module pretty hard.

If we try running it with the same source code x2, we get the right output as well; you can try that here. x3, x4, etc. all work as expected.

Ungolfed with explanation:

def f():                                   # Defines a central function f
    import threading as T,inspect as i     # Imports threading and inspect
    global t,a,i                           # Global vars
    try:
        t.cancel()                         # Tries to cancel Timer from previous code
    except:
        a = 0                              # Reached when code is 1st copy; initializes a.
    a += 1                                 # a++; this is the number of copies thus far.
    t = T.Timer(1,d)               # Creates, then starts a timer to call function
    t.start()                              # d in 1 second.

def d():                                   # Prints out the source code; the quine part.
    print''.join(c*a for c in i.getsource(f)+i.getsource(d)+"f()")

f()                                        # Calls f()!

Calconym

Posted 2016-12-28T05:18:22.397

Reputation: 459

Isn't this a cheating quine, as it reads the source code of its own functions using inspect? (see relevant meta post). On PPCG we have specific definitions of what makes a quine valid, and 'reading the source' is usually regarded as cheating.

– FlipTack – 2016-12-29T14:45:21.400

@FlipTack I'm not sure inspecting a function is the same as reading the source code. Quines in JavaScript and stack-based languages do this all the time. – Dennis – 2016-12-29T17:27:18.920

Ok :). I've added syntax highlighting for your post. Nice idea using threading! – FlipTack – 2016-12-29T18:03:53.440

import threading,inspect as i can be import threading as T,inspect as i – nedla2004 – 2016-12-29T18:12:47.280

@FlipTack Oops, thank you. – Calconym – 2016-12-29T23:48:53.873

@nedla2004 Thank you for 3 less bytes ;) – Calconym – 2016-12-29T23:53:16.753

3

CJam, 19 bytes

{]W=s"_~"+T):Te*}_~

Try it online!

How it works

{               }_~  Define an anonymous code block (function).
                 _~  Push a copy, and execute the copy.
 ]W=                 Wrap the entire stack in an array and select its last element.
                     This discards whatever was on the stack before the original
                     code block, which is needed for subsequent iterations.
    s"_~"+           Cast the code block to string, push "_~", and concatenate.
                     This pushes the stringified source code on the stack.
          T):T       Push T (initially 0), increment it, and save the result in T.
              e*     Repeat each character in the stringified source code T times.

Dennis

Posted 2016-12-28T05:18:22.397

Reputation: 196 637

What... how... so fast... please explain the code, so you can teach me the ways of CJam. – clismique – 2016-12-28T05:55:22.870

@Qwerp-Derp I've added an explanation. – Dennis – 2016-12-28T06:00:10.610

3

RProgN, 66 bytes

Significant Whitespace be the death of me

[ "[ %q ] F 0 1 + `0 = `. { 0 m } R " ] F 0 1 + `0 = `. { 0 m } R 

Explained

[ "[ %q ] F 0 1 + `0 = `. { 0 m } R " ] F 0 1 + `0 = `. { 0 m } R   #
[                                                                   # Pop whatever is already on the stack, if anything.
  "[ %q ] F 0 1 + `0 = `. { 0 m } R "                               # This string contains basically the entire function.
                                      ] F                           # ] F duplicates the string, and then F formats it, which in this case puts the first string into the second at %q, surrounded by qoutes.
                                          0 1 + `0 =                # I needed an Incrementer, so I chose 0. 0, is conveniently, pre initilized at 0. And because RProgN is horrifying, you can remap the number functions as they're just more variables. So this increments 0 every time the group is called.
                                                     `. { 0 m } R   # Replace each character with itself repeated '0' times. Because '0' is an incrementer, each time the script is called, the amount of times the characters are repeated increase.

Good lord I'm a monster...

Try it online!

ATaco

Posted 2016-12-28T05:18:22.397

Reputation: 7 898

Also, although ~["[%q]F01+\0=`.{0m}R"]F01+`0=`.{0m}R` works fine in generally, it's not a valid solution, because there is no way to replicate the ZSS marker. – ATaco – 2016-12-28T06:23:35.370

2

Perl 5, 107 bytes

$_=q[$_=q[S];s/S/$_/;$a++;END{s/./$&x$a/eg;print if$a;$a=0}];s/S/$_/;$a++;END{s/./$&x$a/eg;print if$a;$a=0}

Ungolfed:

$_ = '...INSERT_SOURCE_HERE...';      # Standard quine
s/INSERT_SOURCE_HERE/$_;
$a++;                                 # Count the number of repetitions
END {
    s/./$&x$a/eg;                     # Interweave
    print if $a;                      # Print...
    $a=0;                             # ...but only once
}

Try it online!

Joey Marianer

Posted 2016-12-28T05:18:22.397

Reputation: 141

2

Python 3, 122 121 112 bytes

s='try:from atexit import*;n+=1\nexcept:n=1;register(lambda:[print(end=c*n)for c in"s=%r;exec(s);"%s])';exec(s);

Try It Online: one copy | two copies | three copies | four copies, with automatic verification

How it works

This uses the standard Python quine: Store the code you want to execute in a variable (as a string); include some logic in that string to print itself, everything before it, and everything after it; then execute that string.

The code that is executed via the string s is the following.

try:from atexit import*;n+=1
except:n=1;register(lambda:[print(end=c*n)for c in"s=%r;exec(s);"%s])

The first line unconditionally imports the atexit module, which will allow us to register an exit handler. Trying to import the same module multiple times doesn't affect the script in any way. Then it tries to increment the variable n, to keep track of how many copies of the source code were executed.

The second line is executed only if the first one contains an error. This will be the case in the first iteration, since n is still undefined. In this case, we initialize n as 1 and register a lambda that performs the actual magic.

The registered exit handler

lambda:[print(end=c*n)for c in"s=%r;exec(s);"%s]

will be called right before the program finishes. The lambda itself creates the string "s=%r;exec(s);"%s%r creates a string representation of the right argument (s), which includes everything between the single quotes and the quotes themselves – then iterates over its characters. For each character c, we simply print n copies of c. Passing c*n as the named argument end to print means that no linefeed will be appended.

Dennis

Posted 2016-12-28T05:18:22.397

Reputation: 196 637

1

CJam, 14 bytes

{s"_~"+]:.+}_~

Try it online!

Explanations

{s"_~"+]:.+}_~
{s"_~"+    }_~ Basic quine operator.
       ]:.+    Append each character to corresponding element of the previous result if existed.

jimmy23013

Posted 2016-12-28T05:18:22.397

Reputation: 34 042