1
\$\begingroup\$

Write a quine that

  1. Writes its source code to disk
  2. Recursively executes the written source code
  3. Produces some variation to the code the third time (so not a true Quine)
  4. Stops recursively calling itself the fifth time

Bonus points for leaving nothing on disk after execution.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Is this code-golf, or is there some other winning criterion, making it a code-challenge? It doesn't make sense to be both. \$\endgroup\$ Jan 7, 2014 at 17:48
  • \$\begingroup\$ @KendallFrey I guess I misunderstood what code-challenge was for. Removing the tag. Thanks! \$\endgroup\$
    – simon
    Jan 7, 2014 at 17:52
  • \$\begingroup\$ It's not clear what you consider to be a recursive call (or, for that matter, what "itself" is, given that you're creating imperfect copies), or what you expect to leave on the disk after it finishes. \$\endgroup\$ Jan 7, 2014 at 22:36
  • \$\begingroup\$ @PeterTaylor, thanks for the feedback. See clarifying edits. \$\endgroup\$
    – simon
    Jan 7, 2014 at 23:02

4 Answers 4

2
\$\begingroup\$

TCL 220

proc a b {
if {"$b"=="bb"} {
rename puts w
rename p puts
set b \;exit
}
puts [set q [open [incr ::i] w]] "proc a b \{[info body a]\};a b"
catch {rename puts p}
proc puts {n m} "p \$n \${m}$b"
close $q
source $::i
};a b

The code generates files 1, 2, 3 and 4. The variation is only present in 2, the others are equivalent to the original.

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

PHP 643

<?
$c=1;
$o="<?\n\$c=".($c+1).";\n";
$m="quine";
$s=array(
'$o="<?\n\$c=".($c+1).";\n";',
'$m="quine";',
'$s=array(',
');',
'if($c==3)$s[1]="\$m=\"bip\";";',
'for($i=0;$i<3;$i++)$o.=$s[$i]."\n";',
'for($i=0;$i<count($s);$i++)$o.=chr(39).$s[$i].chr(39).",\n";',
'for($i=3;$i<count($s);$i++)$o.=$s[$i]."\n";',
'echo $m."\n";',
'if($c<5){file_put_contents("q$c.php", $o);echo `php q$c.php`;}',
);
if($c==3)$s[1]="\$m=\"bip\";";
for($i=0;$i<3;$i++)$o.=$s[$i]."\n";
for($i=0;$i<count($s);$i++)$o.=chr(39).$s[$i].chr(39).",\n";
for($i=3;$i<count($s);$i++)$o.=$s[$i]."\n";
echo $m."\n";
if($c<5){file_put_contents("q$c.php", $o);echo `php q$c.php`;}

Output:

quine
quine
quine
bip
bip

The variation in the code is produced in the 3rd iteration and is then only noticeable in the echoes of the 4th and 5th iterations.

\$\endgroup\$
1
  • \$\begingroup\$ Interesting interpretation of the rules! I didn't say whether the variation should be propagated or not. I guess technically a proper quine would propagate the change... +1 \$\endgroup\$
    – simon
    Jan 7, 2014 at 20:53
0
\$\begingroup\$

GTB, 19

X+1→X@X<15$@X=13:1&

Explanation

X starts by default at 10, so we increment X once. Then, if X<15 check if X=13. If X=13, change the code. Then dump it all to memory.

\$\endgroup\$
2
  • \$\begingroup\$ If you are going to write your own language to answer code golf questions, you at least need to explain what it does... ;) \$\endgroup\$
    – simon
    Jan 8, 2014 at 17:36
  • \$\begingroup\$ Okay, I have :) \$\endgroup\$
    – Timtech
    Jan 8, 2014 at 21:35
0
\$\begingroup\$

In Squeak 4.x Smalltalk, it's not golfed, but there is a 299 chars version below

Compile this method in Object:

quine
[| value morph |
value := (((self negated raisedTo: self - 1) / 15) exp exp - 1) reciprocal significand rounded reciprocal.
morph := ToolSet inspect: value.
[(Delay forSeconds: value reciprocal * 5) wait.
morph delete] fork.
World displayWorld.
(Delay forSeconds: 1) wait]
    on: Error
    do: [:exc | 
        FileDirectory default deleteFileNamed: 'quine'.
        ^self].
(FileStream forceNewFileNamed: 'quine') nextPutAll: thisContext method getSource; close.
^self class newCompiler
    evaluate: ((FileStream oldFileNamed: 'quine') contentsOfEntireFile lines allButFirst reduce: [:a :b | a , b])
    for: self + 1

Then evaluate '1 quine' where you want.

Each evaluation differs, because it is evaluated with incremented receiver. ( evaluate: ... for: self+1 )

The awfull expression computing the value is different for 3 (lead to a Fraction 1/2 instead of Integer 1) and for 5 (lead to ZeroDivide).

The file is deleted when the exception is caught and 5 is returned.

Otherwise, an inspector is opened on the value, the display is refreshed, the process is paused during 1 second before evaluating next quine.

A process for closing opened inspectors after a longer pause is forked.

The source of quine is retrieved via the current context of execution (thisContext method getSource), written, then re-evaluated without the first line (the name of the method). So the second and successive evaluation do not evaluate #quine, but an anonymous (#Doit) method sharing exactly the same contents.

Based on same principles, this less funny example will print 00100 in Transcript then stop when evaluating 1 quine, but it avoids explicit 3 and 5 in source:

quine|v|v:=self highBit-self lowBit.Transcript show:(1bitAnd:v).(2bitAnd:v)=0or:[^FileDirectory default deleteFileNamed:'q'].(FileStream forceNewFileNamed:'q')nextPutAll:thisContext method getSource;close.^Compiler evaluate:((FileStream oldFileNamed:'q')contentsOfEntireFile allButFirst:5)for:self+1
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.