14
\$\begingroup\$

You are to create a program that creates exact clones of itself infinitely until stopped. Whatever is in the original program must be in the clones. In other words, the clones and original program are the same in every way except for that the clones don't have to be in the same type of file as the source code (they can be text files).

Example:

If my original program is:

for i in range(0, 10):
     print i

the clone must also be:

for i in range(0, 10):
     print i

Rules and Clarifications:

  • Standard loopholes are forbidden

  • The clones must be the exact copy of the original

  • The clones must be readable files that can be run if put inside the correct interpreter

  • The program can read its own source code

  • All clones must be separate files

  • Printing your program out is not allowed

  • File names count into the number of bytes

  • The clones don't have to be in the same directory as the source file nor share the same file name

  • At least 1000 clones should be able to be created

Winning:

Least bytes wins!

\$\endgroup\$
0

14 Answers 14

4
\$\begingroup\$

Zsh, 19 17 9 bytes

#!/bin/zsh
<$0>$$;$0

Per consensus on meta, the shebang is excluded from the byte count.

Try it online!

Note that TIO's forkbomb protection will kill the process after 113 files have been generated. It can easily generate 1000 files on a system without such conservative resource limits.

\$\endgroup\$
2
  • \$\begingroup\$ I like yes `<$0`|split -1 a lot better, but that doubles the byte count... \$\endgroup\$
    – Dennis
    Commented Dec 27, 2016 at 20:10
  • \$\begingroup\$ Too bad the in-out redirection like that does not work well in bash :( For one moment, I naïvely thought to have outgolfed you :) \$\endgroup\$
    – zeppelin
    Commented Dec 27, 2016 at 20:27
4
\$\begingroup\$

Batch, 32 bytes

set/an=%1+1
copy %0 %n%
%0 %n%

Not using @ because there's no restriction on STDOUT. %1 defaults to the empty string, so n becomes 1 the first time and increments on every pass. Alternatively, this might work for 28 bytes, but I have no idea how random %random% actually is when used like this:

copy %0 %random%%random%
%0
\$\endgroup\$
2
  • 2
    \$\begingroup\$ IIRC %random% is based off the current time and can generate anything from 0 to something slightly above 32,000. \$\endgroup\$ Commented Dec 27, 2016 at 20:08
  • \$\begingroup\$ To clarify, %random% is a variable that, when accessed, yields a random number as @user2428118 mentioned. \$\endgroup\$ Commented Dec 27, 2016 at 20:51
3
\$\begingroup\$

Bash, 25, 16, 12, 11 bytes

EDITS:

  • Removed the newline (-1 byte), Added "Try It Online". Thanks @Dennis !
  • Use background job PID $! as the filename (will be reused every ~32k files, but that is now allowed), -4 bytes

Golfed

#!/bin/bash
$0&cp $0 $!

Explained

Re-spawns itself as a background job with &, before doing a copy, so each iteration will run under its own PID.

Uses the last job PID as the filename.

This can run infinitely (or until stopped) but will be reusing clone filenames approx. every ~32k iterations.

Could be a bit nasty to kill, but AFAIK is not against the rules.

Try It Online!

\$\endgroup\$
3
  • \$\begingroup\$ Do you have a testing place where I can try this out for myself? \$\endgroup\$ Commented Dec 27, 2016 at 17:22
  • \$\begingroup\$ @PythonMaster, I will normally use Tutorial Point's online testbed, but it does not have uuid installed, and does not like the script doing so much IO. \$\endgroup\$
    – zeppelin
    Commented Dec 27, 2016 at 18:39
  • \$\begingroup\$ TIO doesn't have a problem with I/O. Also, you don't need the newline after &. tio.run/nexus/bash#VY5BS8NAEIXP7q943W5tq6QpelMRRCIIGg/… \$\endgroup\$
    – Dennis
    Commented Dec 27, 2016 at 20:37
3
\$\begingroup\$

Ruby, 78 bytes, 77 43 + 4 (filename: a.rb) = 47 bytes

  • Version 1.2

43 bytes + name / Thanks to @Alexis So much shorter!!!

loop{File.write "#{$.+=1}",open("a.rb",?r)}

that's about as golfed as I think it's going to get

  • Version 1.1

73 bytes + name / Thanks to @Alexis Anderson

i=0
loop do
File.open("#{i}",?w){|b|b.puts File.read("a.rb",?r)}
i+=1
end
  • Version 1.0

74 bytes + name

i=0
loop do
File.open("#{i}","w") do{|b|b.puts File.read("a.rb")}
i+=1
end

This is my first Ruby answer so all inprovements are welcome.

\$\endgroup\$
8
  • \$\begingroup\$ kernel open forwards to file open, you should be able to omit the File. altogether. ?w in place of "w". I think the do on the File.open is useless, since you have the curly braces. \$\endgroup\$ Commented Dec 27, 2016 at 20:49
  • \$\begingroup\$ open('a.rb',?r) in place of File.read('a.rb') \$\endgroup\$ Commented Dec 27, 2016 at 20:57
  • \$\begingroup\$ ?w is a character w. A string in it's own right. ?w == 'w'. so you don't need the quotes in "?w" \$\endgroup\$ Commented Dec 27, 2016 at 20:59
  • \$\begingroup\$ i=0 loop do File.write "#{i}",open("a.rb",?r) i+=1 end \$\endgroup\$ Commented Dec 27, 2016 at 21:04
  • \$\begingroup\$ actually, you can also use curly braces for the loop method too \$\endgroup\$ Commented Dec 27, 2016 at 21:07
2
\$\begingroup\$

sh, 24 bytes

yes cp $0 '`uuid`'|sh -s
\$\endgroup\$
2
\$\begingroup\$

C#, 104 102 bytes

-2 bytes thanks to berkeleybross

namespace System.IO{class a{static void Main(){int i=0;while(1>0){i++;File.Copy("c{i}.cs");}}}}

No, it's not the shortest. But it's C#. What did you expect?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You don't need a namespace so you can fully qualify the File.Copy. Changing to a for loop so you can inline the int declaration and remove the 1>0 part. And pre increment the i in the File.Copy statement, that gives you 86 bytes I believe: class P{static void Main(){for(int i=0;;)System.IO.File.Copy("c.cs","c"+ ++i+".cs");}} \$\endgroup\$ Commented Dec 28, 2016 at 15:43
  • \$\begingroup\$ Actually this won't work because c.cs won't be in the output directory and has to be copied there manually. How does this work? \$\endgroup\$ Commented Dec 28, 2016 at 15:45
  • \$\begingroup\$ Dont forget about string interpolation $"c{++i}.cs" is 2 bytes shorter than "c"+ ++i+".cs" \$\endgroup\$ Commented Dec 28, 2016 at 17:59
1
\$\begingroup\$

Processing, 55 + 5 (name of file) = 60 bytes

I don't know if the filename counts as extra bytes

for(int i=0;;)saveStrings(i+++"",loadStrings("a.pde"));

Pretty much a series of builtins all chained together

Explanation

for(int i=0;;)           //A complex piece of code that cannot be explained in words alone
saveStrings(             //Save param2 (String[]) into file param1 (String)
 i+++"",                 // filename: the int i (and then is incremented)
 loadStrings("a.pde")    // content: load the content of file a.pde as a String[]
);
\$\endgroup\$
1
  • \$\begingroup\$ That "complex code" is smiling \$\endgroup\$ Commented Dec 27, 2016 at 20:04
1
\$\begingroup\$

ForceLang + the ForceLang-JS module, 162 bytes

set j require njs
j var a=function(){for(;;){var p=new java.io.PrintStream(Math.random()+".txt");p.println("set j require njs");p.print("j var a="+a+";a()")}};a()
\$\endgroup\$
1
\$\begingroup\$

Python 2, 54 bytes

from shutil import*
a=__file__
while`copy(a,a*2)`:a*=2
\$\endgroup\$
2
  • \$\begingroup\$ Don't you have to import sys? \$\endgroup\$ Commented Dec 27, 2016 at 21:18
  • \$\begingroup\$ @SamuelShifterovich I would have had. I'm not sure how that edit survived as the byte count I was using was for the program now shown \$\endgroup\$
    – Blue
    Commented Dec 27, 2016 at 21:52
1
\$\begingroup\$

Mathematica, 41 bytes

For[a=0,1>0,$Input~CopyFile~ToString@a++]

Full program. Copies its own source file into 0, 1, 2, etc. in the current directory.

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

Python 2, 61 bytes (unix) 65 (cross-platform)

Unix - 61 bytes

import os;i=1
while os.popen('cp %s %i.py'%(__file__,i)):i+=1

On unix cp is the systems copy-file - command. Using the console via popen allows me to copy the file by cp. new files will spawn in old-files directory.

CrossPlatform - 65 bytes

i=0
while 1:i+=1;open('%i.py'%i,'w').write(open(__file__).read())

This works, as open on default allows reading.

Funfact: replace 1:i+=1 with i:i-=1 and it will stop at i copies.

Other than that, I see no way of making it shorter than @muddyfish did it.

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

PHP, 91 60 bytes

Saved 31 bytes thanks to manatwork

<?for(;;)file_put_contents(++$i,file_get_contents("f.php"));

Usage: $ php f.php clones f.php and its code reproducing infinitely itself in filenames like 1, 2, 3... until timeout.

Previous version:

<?for($i=0;;$i++)$p=fwrite(fopen("$i.php","w"),fread(fopen($f="f.php","r"),filesize($f)));

Usage: $ php f.php clones f.php and its code reproducing infinitely itself like f1.php, f2.php, f3.php ... f(n).php until timeout.

\$\endgroup\$
1
  • \$\begingroup\$ As the clone file name can be anything, why not use just numbers without extension? <?for(;;)file_put_contents(++$i,file_get_contents("f.php")); \$\endgroup\$
    – manatwork
    Commented Dec 28, 2016 at 9:06
0
\$\begingroup\$

awk, 29 (21) bytes,

{while(close(i++)||1)print>i}

awk is not really the tool for this as it requires close() when running indefinitely. Otherwise all it produces are empty files.

If the clone count had a limit, for example 5:

{while(++i<5)print>i}

the program would be 21 bytes.

Paste the program to a file a and run:

$ awk -f a a
\$\endgroup\$
0
0
\$\begingroup\$

Python, 69 bytes

a=open(__file__).read()
i=0
while 1:i+=1;open(`i`+'.py','w').write(a)

I tried using a for the file name, but (unsurprisingly) Windows does not like files named a=open(__file__).read()\ni=0\nwhile 1:i+=1;open(i+'.py','w').write(a). I also tried this:

a=open(__file__).read()
i=''
while 1:i+='.py';open(i,'w').write(a)

However it gives me this error:

Traceback (most recent call last):
  File "C:/Python27/codeGolfCopy.py", line 3, in <module>
    while 1:i+='.py';open(i,'w').write(a)
IOError: [Errno 2] No such file or directory: '.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py.py'

It creates 83 files, but that is not even close to the needed 1000.

If you would like to remove these files, you can use this:

import os;i = 1
while 1:os.remove(`i`+'.py');i+=1
\$\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.