22
\$\begingroup\$

Making a versatile integer printer is nice and all, but writing a single code that prints a lot of different numbers is cumbersome. Wouldn't it be easier to make a script that outputs a number, but also gives you a new script to get the next number?

Challenge:

Write a code that outputs a single integer N and an executable code. The next code should output N+1 and a code that can output N+2. Continue this path until you reach N = 15. (The last printed number should be 15).

Rules:

  • No input (assume the input is empty).
  • Full program or function or other convenient formats are allowed.
  • The first code should output 1.
  • You can't output leading zeros. I.e. you can't print 01 for 1.
  • The output must be on the format N, Code_for_N+1. Note that the output is separated by a comma and a single space. The code for N+1 has no surrounding quotation marks. N , Code_for_N+1 is not accepted (space in front of the comma). Trailing newlines are OK.
  • The first character(s) of the output must be the number. (No leading spaces, or ans = N).
  • The printed number should not be part of the next code (the code can contain this number, but you can't take the output number as part of the code)
    • Example: The output for N=2 can be: 2, printer 2. In this case, printer 2 is the code for N=3. You can't use the entire output: 2, printer 2 as code for N=3.
  • The scripts may be in different languages
  • The datatypes are irrelevant (the number can be a string), but it can't be surrounded by anything (quotation marks, parentheses etc).
  • If there is a code outputted for N=15 then it must either print STOP! (see bonus), or don't print anything at all (not even a space or newline).
    • The code for N=15 can not crash (but outputting to STDERR is OK).
    • You are disqualified if the output code for N=15 prints 16 or anything else (except the bonus case).
  • Built in quine operators are not allowed.
  • Accessing the source file through the file system is not allowed.

Bonus:

-10 bytes if the code that prints 15 also produces a code that prints "STOP!"

Examples using Python syntax: (obviously, these will only work for the selected integers, not from 1 to 15.)

N = 1
print "1, print 2"
1, print 2

---
N = 15
print 15
15

---
N = 15   (Qualifies for the -10 bytes bonus)
print "15, print 'STOP!'"
15, print 'STOP!'

print 'STOP!'
STOP!

----

N = 15   (Qualifies for the -10 bytes bonus)
print "15, disp('STOP!')"
15, disp('STOP!')        (disp('STOP!') outputs STOP! in MATLAB)

----
N = 15   (This one is not OK. The submission is disqualified)
print "15, print 16"
15, print 16

Standard golfing rules apply! Smallest code (for N=1) in bytes win!

\$\endgroup\$
6
  • \$\begingroup\$ So, say, f=>f+"" would be invalid? (f+"" returns the function's construction code.) \$\endgroup\$ Commented Jan 7, 2016 at 17:23
  • \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ without it, is it even possible to achieve the task... \$\endgroup\$
    – nicael
    Commented Jan 7, 2016 at 17:27
  • \$\begingroup\$ @nicael It's been done already, at least in the js answer \$\endgroup\$ Commented Jan 7, 2016 at 17:29
  • 1
    \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ ...in a viable way :D \$\endgroup\$
    – nicael
    Commented Jan 7, 2016 at 17:31
  • \$\begingroup\$ The rules are confusing, can I output something like 14, print(14+1) or not? \$\endgroup\$
    – user344
    Commented Jan 9, 2016 at 15:48

17 Answers 17

39
\$\begingroup\$

Pyth + ///, 15 bytes - 10 = 5

pPt`S15", STOP!

This prints 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, STOP! in Pyth, by taking range(1,15+1) and stripping off the start and end brackets, and printing it immediately followed by ", STOP!".

The next fourteen programs are in ///, which directly outputs all programs that don't contain / or \. So the second program

2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

gives 2 and the third program 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15. The penultimate program, 15, STOP!, prints 15, STOP!, so the last program is just STOP!.

\$\endgroup\$
4
  • 4
    \$\begingroup\$ Cheeky. I like it. :) \$\endgroup\$ Commented Jan 7, 2016 at 17:42
  • \$\begingroup\$ Does cat count as a language? \$\endgroup\$ Commented Jan 8, 2016 at 11:50
  • \$\begingroup\$ @immibis cat doesn't do a primality test, so no. \$\endgroup\$
    – user48538
    Commented Jan 8, 2016 at 14:21
  • 1
    \$\begingroup\$ Programs #2 and up also work in PHP. :) \$\endgroup\$ Commented Jan 8, 2016 at 15:24
31
\$\begingroup\$

JavaScript, 131238 - 10 = 131228 bytes

The naive approach turned out worse than expected. In hindsight I should have expected it. But I thought I'd share it anyway. Full code here.

Idea: Iteratively escaping and adding the N-1, ...

alert("14,alert(\"15, alert(\\\"STOP!\\\")\")")
\$\endgroup\$
5
  • 8
    \$\begingroup\$ I think this is the most backslashes in any PPCG answer ever. \$\endgroup\$
    – lirtosiast
    Commented Jan 7, 2016 at 17:19
  • 1
    \$\begingroup\$ I admit having used NP++ and regex for this=) \$\endgroup\$
    – flawr
    Commented Jan 7, 2016 at 17:22
  • 21
    \$\begingroup\$ Haha, this -10 helps a lot :D \$\endgroup\$
    – nicael
    Commented Jan 7, 2016 at 18:53
  • 2
    \$\begingroup\$ I have created a slightly less naive 87573-byte solution. \$\endgroup\$ Commented Jan 8, 2016 at 0:21
  • 1
    \$\begingroup\$ You can save some bytes with no bonus. \$\endgroup\$
    – Riker
    Commented May 4, 2016 at 14:32
8
\$\begingroup\$

CJam, 26 25 24 bytes

1{", "2$)@"_~"](_F<@*}_~

Try it online.

The subsequent programs simply have the first number incremented. This runs the program 16 times.


Or with bonus for the same score:

1{", "\2$)_G<\@`+"_~"+"STOP!"`?}_~

Try it online.

The subsequent programs simply have the first number incremented. This runs the program 16 times.

Alternative solution for the bonus:

1{", "\2$)Gmd@`+"_~"+"STOP!"`\?}_~
\$\endgroup\$
3
  • 2
    \$\begingroup\$ @FryAmTheEggman cjam.tryitonline.net/… uses Base64 to encode the program, which makes posting permalinks in comments a bit easier. </selfpromotion> \$\endgroup\$
    – Dennis
    Commented Jan 7, 2016 at 17:28
  • \$\begingroup\$ @Dennis Thanks, that was a bit of a headache :P Looks like martin wrote his own, anyway. \$\endgroup\$ Commented Jan 7, 2016 at 17:29
  • \$\begingroup\$ @FryAmTheEggman Only after I saw your link though, so thanks for the suggestion. ;) \$\endgroup\$ Commented Jan 7, 2016 at 17:30
7
\$\begingroup\$

JavaScript (ES6), 62 61 bytes - 10 bonus = 51 score

_=>"1, "+(f=n=>`_=>"`+(n<16?n+`, "+(${f(n+1)})`:`STOP!"`))(2)

Explanation

A solution which does not read it's own source code and is also not ridiculously long.

The first program constructs all 15 other programs and nests them inside each other using a recursive function. I get around the backslash issue by nesting the functions themselves (which are then cast to strings during output) rather than strings.

_=>
  "1, "                // print the first number
  +(f=n=>`_=>"`+(      // f = recursive function for printing program N
    n<16?              // for programs 2 - 15:
      n+`, "+(${       // add N to the output of the nested function
        f(n+1)         // nest the code of program N + 1
      })`
    :`STOP!"`          // program 16 just outputs "STOP!" for the bonus
  ))(2)                // start from program 2

Test

var nextProgram = '_=>"1, "+(f=n=>`_=>"`+(n<16?n+`, "+(${f(n+1)})`:`STOP!"`))(2)',
    n = 1;
while(nextProgram) {
  result.textContent += "Program " + n++ + ": " + nextProgram + "\n";
  var output = eval("(" + nextProgram + ")()");
  result.textContent += "   Output: " + output + "\n\n";
  var index = output.indexOf(",");
  nextProgram = index > 0 ? output.substr(index + 2) : null;
}
<pre id="result"></pre>

\$\endgroup\$
4
  • 1
    \$\begingroup\$ +1 for not using JavaScript's built-in feature of getting a function's body (grey area for quining) \$\endgroup\$ Commented Jan 8, 2016 at 3:02
  • 2
    \$\begingroup\$ @Callodacity How does "" + (n=>m) not count as getting the body of the function n=>m? \$\endgroup\$
    – Neil
    Commented Jan 8, 2016 at 23:37
  • \$\begingroup\$ @Neil Actually you're right it does count - I'd overlooked that since I'd only looked at program 1 and hadn't gone through the output \$\endgroup\$ Commented Jan 8, 2016 at 23:47
  • \$\begingroup\$ Where did all the backslashes go!? \$\endgroup\$
    – Noodle9
    Commented Jan 9, 2016 at 10:38
5
\$\begingroup\$

Matlab, 226 212 - 10 = 202 bytes

Thanks to @StewieGriffin for a few bytes=)

'awFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)

The first part is a string that represents the second line (below), the actual code (just shifted by 9). In Matlab, strings are matrices filled with characters, so you can easily perform the shifts by just adding/substracting a scalar. So the program just prints out the same string* again, plus the same string but shifted which results in the code.

*Not quite: The first byte is the counter which needs to be increased in each iteration.

The quine trick with the string was shamelessly stolen from here.

'awFjw|Dro)w1:26B?G:>DwF0\}xy*0Dnu|nDwFdw~v;|}{1w1:26B?2505)05<B5w1:24:5w1;Cnwm25<B5>B5w1;Cnwm26B500fDnwmDmr|y1w2';
n=ans;if n(1)-96>15;n='Stop!';else;n=[num2str(n(1)-96),', ',39,n(1)+1,n(2:end),39,59,n(2:end)-9,''];end;disp(n)

Here the last few lines of the sequence copied from the console:

>> 'mwFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)
13, 'nwFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)
>> 'nwFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)
14, 'owFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)
>> 'owFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)
15, 'pwFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)
>> 'pwFjw|DWFw1:2DVFw1;Cnwm2Dro)WG:::DwF0\]XY*0Dnu|nDwFdw~v;|}{1W6B?2505)05<B5W4:5V5<B5>B5V6B500fDnwmDmr|y1w2';n=ans;N=n(1);M=n(2:end);if N>111;n='STOP!';else;n=[num2str(N-96),', ',39,N+1,M,39,59,M-9,''];end;disp(n)
STOP!
\$\endgroup\$
0
5
\$\begingroup\$

JavaScript, 50 47 44 42 44* bytes

a=_=>(x=1)+(x<15?", a="+a:"").replace(x,x+1)

It's a function which extracts its own body (just a) and makes replacements in it. Getting the function body a built-in feature of JavaScript, though not being explicitly a quine operator (if it's invalid, will remove the answer).

a=_=>(x=1)+(x<15?", a="+a:"").replace(x,x+1);
alert(a());

In case it doesn't work properly embedded there (because for me it doesn't), you can see an example there.


* - looks like the snippet produces the result without a=, making further calls impossible

\$\endgroup\$
11
  • 1
    \$\begingroup\$ How is "a builtin feature for getting the function body" not the same as a quine operator? I'm not saying it's invalid, I'm just wondering what the difference is? \$\endgroup\$ Commented Jan 7, 2016 at 17:42
  • \$\begingroup\$ I was just working on one. o_o Can't you do .replace(x++,x)? \$\endgroup\$ Commented Jan 7, 2016 at 17:43
  • 3
    \$\begingroup\$ @StewieGriffin Ones made for quining, the other is a legitimate feature. \$\endgroup\$ Commented Jan 7, 2016 at 17:46
  • \$\begingroup\$ @Stewie But the "quine operator" is supposed to return the whole program, while in my example it retrieves a function, without the purpose to make a quine (there's no built-in to return the whole program code). As you've allowed the functions, it could be similar though, therefore I was wondering. \$\endgroup\$
    – nicael
    Commented Jan 7, 2016 at 17:47
  • \$\begingroup\$ Does a=_=>(x=1)+(x<15?`, ${a}`:"").replace(x,x+1) work? \$\endgroup\$ Commented Jan 7, 2016 at 17:53
5
\$\begingroup\$

Python 2.7.10, 196 92 - 10 = 82 bytes

Whee!!! This was fun. Much shorter now. :P

n=1;a='n=%d;a=%r;print n,a%%(n+1,a)if n!=15else"STOP!"';print n,a%(n+1,a)if n!=15else"STOP!"

Explanation:

I started with this:

a='a=%r;print a%%a';print a%a

That is just a simple quine. This is that with a counter added:

n=1;a='n=%d;a=%r;print n,a%%(n+1,a)';print n,a%(n+1,a)

n is a counter variable that is printed at the beginning. Then when its prints the n= part, it substitutes n+1 for the %d. So from here it will count up infinitely.

And here is the final version. It adds an if clause to stop at 15, and prints "STOP!" as well.

n=1;a='n=%d;a=%r;print n,a%%(n+1,a)if n!=15else"STOP!"';print n,a%(n+1,a)if n!=15else"STOP!"

Old code:

a= ['if num==15:print"STOP!!!";exit()','print num','print"a=",a','print"num=",num+1', 'for s in a:print s']
num= 1
print num
if num==15:print"STOP!!!";exit()
print"a=",a
print"num=",num+1
for s in a:print s

Never going to win, but fun. :P Much shorter now, though I still don't stand a chance. :P

\$\endgroup\$
4
  • \$\begingroup\$ Wow. Can you add an explanation because this is cool but I have no idea what's going on :D \$\endgroup\$
    – Sherlock9
    Commented Jan 8, 2016 at 6:57
  • \$\begingroup\$ @Sherlock9 done. Thanks for your appreciation. \$\endgroup\$
    – Riker
    Commented Jan 8, 2016 at 16:23
  • \$\begingroup\$ If I cut and paste this into an interactive python 2.7.6 session it complains that there's no spaces before the elses. \$\endgroup\$
    – eric
    Commented Jan 8, 2016 at 22:44
  • \$\begingroup\$ @eric I am using python 2.7.10 and it works for me... \$\endgroup\$
    – Riker
    Commented Jan 8, 2016 at 23:20
3
\$\begingroup\$

PowerShell, (215-10)=205 197 167 106 104 103 bytes

$d='$c=(,1*{2}).count;$d={0}{1}{0};(("$c, $d"-f[char]39,$d,($c+1)),$c)[$c-eq15]';"1, $d"-f[char]39,$d,2

(If your only tool is PowerShell, every problem looks like a nail. Wait...)

Essentially, we start with setting $d equal to a big-ole-lengthy string of an almost-quine of the original code. It outputs 1 and then $d with the format operator -f to correctly populate the {0},{1},{2} stand-ins, incrementing the {2} number in the ,1*{2} section by one each time.

The ,x*y operation in PowerShell creates a new array of y items, each of which is equal to x. For example, ,2*3 is equivalent to @(2,2,2).

This means, the first output will be 1, $c=(,1*2).length;$d=(etc...), so when the second code is executed, $c will equal the count of the array @(1,1), or 2, etc. Note that $c isn't used as a variable in the original code, just in subsequent runs.

Stops when it prints 15 by simply calculating whether $c equals 15 and then indexing into an array, the 0th element is $c, $d as described above, the other is just 15. Thus, when $c is 15, it'll output 15 and nothing else. Doesn't qualify for the bonus, because "15, {0}STOP!{0}" is 5 characters too long for the -10 to be worthwhile.

Requires a PowerShell terminal of width > ~150. Or for you to manually remove the extra linebreak (that the terminal helpfully inserts on output wrap) when copy-pasting the code. Or for you to capture output into a variable and then re-execute that variable. Etc.

Edit 1 -- Saved some bytes by removing the "STOP!" wording.
Edit 2 -- Durr, don't use .length each time, just call it once
Edit 3 -- Doesn't need to be a quine, so the initial run can be a lot shorter
Edit 4 -- Changed from using strings to arrays to calculate $c, which saved two bytes. I'm pretty sure this is almost optimal for this approach.
Edit 5 -- Saved another byte by directly counting equality rather than modding

\$\endgroup\$
1
  • \$\begingroup\$ The Windows 10 console window no longer copies the output wrap linebreak. \$\endgroup\$
    – Neil
    Commented Jan 9, 2016 at 12:53
2
\$\begingroup\$

JavaScript, 79 - 10 = 69 bytes

s='STOP!';for(i=15;i;){s=i--+',alert("'+s.replace(/[\\"]/g,"\\$&")+'")'};alert(s)

Without using Function.prototype.toString in any way at all.

\$\endgroup\$
2
\$\begingroup\$

Befunge, 57 - 10 = 47 bytes

1:'!`'#*j:.',,1+:9`''*'0++,1#;:0g:48*`j@,1+;"!POTS",,,,,@

This one is awesome. Try it here.

\$\endgroup\$
2
  • \$\begingroup\$ The right casing for the stop message is STOP! \$\endgroup\$
    – user48538
    Commented Jan 8, 2016 at 14:22
  • \$\begingroup\$ @zyabin101 fixed. \$\endgroup\$
    – MegaTom
    Commented Jan 8, 2016 at 14:26
2
\$\begingroup\$

Batch, 73 + 5 - 10 = 68 bytes

@set a=STOP!
@for /l %%a in (15,-1,1)do @set a=%%a, @echo !a!
@echo %a%

Requires CMD /V:ON so I added 5 bytes for that.

\$\endgroup\$
2
\$\begingroup\$

Python 2.7, 107 characters

By using recursion and not writing a quine, I thought I could save a lot, which is true, but not good enough. Although not a winner, I think the approach is fun to share.

I started by making up a string for N=4, escaping the \ and " characters.

print "1, print \"2, print \\\"3, print \\\\\\\"4, print \\\\\\\\\\\\\\\"STOP!\\\\\\\\\\\\\\\"\\\\\\\"\\\"\""

Then I created a lambda function that creates this string, based on a start index and a stop index, using recursion. This is it:

l=lambda n,m:str(n)+", print "+"\\"*(2**(n-1)-1)+"\""+l(n+1,m)+"\\"*(2**(n-1)-1)+"\"" if n<m else "STOP!"

Use it like this:

print l(1,15)

Output: [32902 characters, too long to handle]

So, it seems that my kolmogorov complexity approach isn't that successful ;-)

\$\endgroup\$
2
\$\begingroup\$

SMBF, 28 bytes

\x10 represents a literal byte (decimal value 16). The integer is output as an integer (byte). So the first character output is \x01. The program then prints ", ". When printing its own source, it prints an extra + at the beginning.

+.<-<<.>.>[[<]>.[.>]<[-]], \x10

Explanation:

+.                                  Increment number and print
  <-                                Pre-decrement loop counter
    <<.>.>                          Print comma and space from own source
          [             ]           Only execute if loop counter != 0
           [<]>.                    Move to left of source, then print `+`
                [.>]                Print entire source.
                    <[-]            Zero out the loop counter so this program halts.
                         , \x10     The comma, space, and loop counter used earlier.
                                    Input is empty, so `,` doesn't do anything.

Note that you cannot run this in a standard interpreter because it requires a hex literal in the input. You also need a special terminal for hex output to work properly.

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

Bash, 78 74 73 - 10 = 63 bytes (Example, can't win)

p='if(($((++a>15))));then unset a p;fi;echo ${a-STOP\!}${p+, $p}';eval $p

Coming in late, but saw bash hadn't been tried so gave it a go. First gulf challenge and quine-like puzzle. They're fun!

Explanation:

This works because a steps from 1 to 15 and is then unset along with p. The script (stored in p) prints them both out if they're set and "STOP!" otherwise. The initially unset a is set to 0 because it appears in an arithmetic expansion.

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

𝔼𝕊𝕄𝕚𝕟, 30 chars / 47 bytes (non-competitive)

⟮a=1)+(a<ḏ?⬬+ⒸⅩ222+ᶈ0:⬯)ē(a,⧺a

Try it here (Firefox only).

Finally found a good ol' true quine for 𝔼𝕊𝕄𝕚𝕟.

Explanation

Here's the true quine that I used: ⟮ⒸⅩ222+ᶈ0

You see it in my answer? Hopefully, y'all will be able to expand from there.

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

Keg+PHP, 19-10=10 bytes

ï_(. \,,,)\!POTS(,

Counts from 1 to 15 and then stops. TIO

Keg, 13 bytes

ï_(. \,,,).
\$\endgroup\$
1
\$\begingroup\$

Python 2, 68 (-10) bytes, Python 3, 69 (-10) bytes

My previous answers were incorrect. That's now fixed :)

Python 2 (68 bytes, 58 points)

a,b="print'%d, a,b=%r,%d;exec a'%(b,a,b+1)*(b<16)or'STOP!'",1;exec a

Try it online!

Python 3 (69 bytes, 59 points)

a,b="print(f'{b}, a,b=%r,{b+1};exec(a)'%a*(b<16)or'STOP!')",1;exec(a)

Try it online!

How it works:

  • I started from the quine a="print("a=%r;exec(a)"%a);exec(a)"
  • I assign b to the value to be printed
  • Then I print b, and the quine replacing b by b+1
  • If b is equal to 16, I print STOP! intead
\$\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.