21
\$\begingroup\$

Given a positive integer nesting level n and string s of printable ascii characters( to ~, output a program which, when run in the same language, outputs a program which outputs a program . . . which outputs the string s.

A total of n programs should be generated, all of which should be run in the same language as your answer.

Note: you may output programs or functions -- anything you are allowed by default as a submission.

You may input s with escaped characters, how a program or function in your language would usually input a string.


Example

For example, given n=1 and s="recursion", a Python 2 program might output:

print "recursion"

Running this would output:

recursion

Given n=2 and s="PPCG", a Python 2 program might output:

print "print \"PPCG\" "

Running this outputs:

print "PPCG"

Running this outputs:

PPCG

Related (+title inspiration): One more LUL and I'm out

Also Related (in sandbox - now deleted, but can still be viewed with enough reputation): Source Code Recursion

Test Cases

Make sure that your code works for the following test cases (one per line):

n s
2 PPCG
4 Robert'); DROP TABLE Students;--
17 Deep
2 Spaces In Here
3 "Don't forget quotes!"
5 'Backt`cks might be a h`tch'
6 5%s
8 [Brackets]<Are>(Great){Usually}
3 !"#$%&'()*+,-./ 0123456789:;<=>?@ABCDEFGHIJKLMN
6 OPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
7 THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
3 the quick brown fox jumps over the lazy dog
\$\endgroup\$
  • 1
    \$\begingroup\$ Was reading the challenge and was like "hey, that looks very familiar..", and then noticed your "Also Related (in sandbox): Source Code Inspiration" to my Sandbox question. :) I'll leave my question there for now, but will delete it after a couple of weeks. Yours is basically the same, except with the addition of an integer parameter. \$\endgroup\$ – Kevin Cruijssen Sep 28 '17 at 7:11
  • 1
    \$\begingroup\$ As suggested here, is it allowed to return anonymous functions instead of programs? \$\endgroup\$ – Arnauld Sep 28 '17 at 9:07
  • 1
    \$\begingroup\$ Does "positive integer" include 0? \$\endgroup\$ – Felix Palmen Sep 28 '17 at 9:16
  • 1
    \$\begingroup\$ Did you choose program for a reason? The default is function or program? Is it allowed to have a function printing a function? \$\endgroup\$ – Kevin Cruijssen Sep 28 '17 at 11:48
  • 1
    \$\begingroup\$ @StewieGriffin because escaping in sub-expressions or nested programs might be problematic (and someone asked for quote test cases in sandbox). \$\endgroup\$ – fireflame241 Sep 28 '17 at 14:41

16 Answers 16

0
\$\begingroup\$

Excel VBA (32-Bit), 67 Bytes

Version Restricted to 32-Bit Excel VBA because 2^i evaluates without error in 32-Bit VBA, but not in 64-Bit VBA

Anonymous VBE immediate window function that takes inputs n and s from from ranges [A1] and [B1] and outputs an anonymous function that when evaluated down to only a terminal (after n iterations) outputs only s as that terminal

For i=0To[A1-1]:q=q+"?"+String(2^i,34):Next:?q[B1]Replace(q,"?","")

Sample Input / Output

[A1:B1]=Array(7, "PPCG")
For i=0To[A1-1]:q=q+"?"+String(2^i,34):Next:?q[B1]Replace(q,"?","")
?"?""?""""?""""""""?""""""""""""""""?""""""""""""""""""""""""""""""""?""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""PPCG"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
?"?""?""""?""""""""?""""""""""""""""?""""""""""""""""""""""""""""""""PPCG"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
?"?""?""""?""""""""?""""""""""""""""PPCG"""""""""""""""""""""""""""""""
?"?""?""""?""""""""PPCG"""""""""""""""
?"?""?""""PPCG"""""""
?"?""PPCG"""
?"PPCG"
PPCG
\$\endgroup\$
0
\$\begingroup\$

Ruby, 34 bytes

%p is a Ruby-specific printf flag that gets the inspect value of its argument, similar to %r in Python. $><< means print.

f=->n,s{"$><<%p"%(n>1?f[n-1,s]:s)}

Try it online!

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

R, 62 bytes

f=function(n,s){"if"(n,{formals(f)$n=n-1;formals(f)$s=s;f},s)}

Try it online!

Call it like so: f(n,s) followed by n copies of ()

A named function; returns an anonymous function. All it does is modify the default values of the formals of f, allowing the resulting function to be called (and then the result of that called, n times). when n reaches 0, it returns s.

R is actually not too bad at escaping! It uses C-style escaping, so you just have to take the input, replace " with \" and \ with \\, and then wrap the whole thing in " ".

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

Underload, 11 bytes

(a(S)*)~^^S

Try it online!

Input needs to start on the stack, with the number on top in the form of a church numeral. I don't know if this is a valid input method, but the specification has no input, and placing input to the top of the stack seems like a stranded method used in such languages.

\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog), 24 23 bytes

-1 thanks to ngn.

This is a full program which prompts for s and then for n and prints to STDOUT.

''''{⍺,⍨⍺,⍵/⍨1+⍵=⍺}⍣⎕⊢⍞

Try it online! (the 17 Deep case is omitted as it exceeds TIO's output limit – works offline)

prompt for s

 yield that (to separate and )

''''{}⍣⎕ prompt for n and apply this lambda with a single quote as left argument that many times. stands for the left argument (the quote) and is stands for the right argument (the input text):

⍵=⍺ Boolean where the text is equal to a quote

1+ add one

⍵/⍨ replicate each character of the argument the corresponding number of times

⍺, prepend a quote

⍺,⍨ append a quote

This works because strings in APL are ' delimited and single-quotes in strings are doubled, while no other characters need escaping.


Dyalog APL also ships with a utility (⎕SE.Dyalog.Utils.repObj) that generates an APL expression which evaluates to its argument (similar to Jelly's uneval). The following program is therefore equivalent to the above, but works for all arrays:

⎕SE.Dyalog.Utils.repObj⍣⎕⊢⎕

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I think APLX allows "doubly-" as well as 'singly-quoted' strings. If the rest works there, you can save a byte :) ngn/apl used to but I removed "" recently \$\endgroup\$ – ngn Sep 30 '17 at 10:10
  • \$\begingroup\$ Consider passing the quote as .- that saves (at least) a byte. \$\endgroup\$ – ngn Sep 30 '17 at 10:16
  • \$\begingroup\$ @ngn Thanks, but APLX doesn't have dfns. NARS2000 has both double-quotes and and dfns, but characters cost two bytes each. \$\endgroup\$ – Adám Oct 2 '17 at 7:30
1
\$\begingroup\$

QuadR, 8 bytes

Simple translation of ngn's answer.

Takes n as argument and s as Input.

^|'|$
'&

Try it online!

PCRE Replace all instances of

^|'|$ Beginning of line OR Quote OR End of line

'& with a Quote and the entire match

The Argument specifies how many times to repeat the transformation.

\$\endgroup\$
  • \$\begingroup\$ ah, now I know what that language is for :) \$\endgroup\$ – ngn Oct 2 '17 at 17:47
0
\$\begingroup\$

APL (Dyalog Classic), 19 bytes

'^|''|$'⎕r'''&'⍣⎕⊢⍞

Try it online!

\$\endgroup\$
  • \$\begingroup\$ That's very clever. I tried this approach, but didn't think of prepending. \$\endgroup\$ – Adám Oct 2 '17 at 7:09
  • \$\begingroup\$ Sell also this. \$\endgroup\$ – Adám Oct 2 '17 at 7:17
5
\$\begingroup\$

Haskell, 17 bytes

As of when I write this, this is the shortest answer for a non-golfing-specific language.

It is a function which takes s and n in that order, and returns the result or the source code of an expression which, when evaluated, returns the next source code.

(!!).iterate show

Argument for why this counts:

  1. Solutions are allowed to be functions.
  2. Their outputs are allowed to be functions.
  3. Those functions have no parameters.
  4. In Haskell, since it is lazy and everything-is-curried, the most natural — for practical programming purposes — definition of a 0-parameter function is the same as its result; the closest alternative, a 1-parameter function which ignores the parameter, is silly.

If f is given PPCG and 2 as its parameters, the result is the text "\"PPCG\"" (first generated function), which when evaluated returns the text "PPCG" (second generated funtion), and when that is evaluated it returns PPCG.

Thanks to nimi for suggesting a shortening.

\$\endgroup\$
  • \$\begingroup\$ There is a relevant Meta question on the issue of functions with no arguments in Haskell, though it hasn't received that much attention yet and still has open questions: codegolf.meta.stackexchange.com/q/12924/56433 \$\endgroup\$ – Laikoni Sep 29 '17 at 6:48
19
\$\begingroup\$

JavaScript (ES6), 47 44 bytes

Saved 3 bytes thanks to @HermanLauenstein

Takes input in currying syntax (n)(s).

n=>g=s=>`alert(atob("${btoa(--n?g(s):s)}"))`

Example

f(2)('PPCG')

Will output:

'alert(atob("YWxlcnQoYXRvYigiVUZCRFJ3PT0iKSk="))'

Which will print:

'alert(atob("UFBDRw=="))'

Which will print:

'PPCG'

Demo

A more complex example where alert() has been overridden so that intermediate results are printed to the console and automatically executed.

let f =

n=>g=s=>`alert(atob("${btoa(--n?g(s):s)}"))`

alert = s => { console.log(s); try { eval(s); } catch(e) {} }

alert(f(5)("'Backt`cks might be a h`tch'"));


Alternate version, 40 bytes

Suggested by @Shaggy

This one returns an anonymous function instead of a full program.

n=>g=s=>`_=>atob("${btoa(--n?g(s):s)}")`
\$\endgroup\$
  • \$\begingroup\$ Could you return an anonymous function, instead of using the alert? 41 bytes \$\endgroup\$ – Shaggy Sep 28 '17 at 9:00
  • \$\begingroup\$ @Shaggy I don't really know. I've asked the OP. \$\endgroup\$ – Arnauld Sep 28 '17 at 9:08
  • \$\begingroup\$ If not, maybe you could get away with an IIFE instead for 45 bytes. \$\endgroup\$ – Shaggy Sep 28 '17 at 9:09
  • \$\begingroup\$ -3 bytes using currying: n=>g=s=>BTalert(atob("${btoa(--n?g(s):s)}"))BT (replace BT with backticks) \$\endgroup\$ – Herman L Sep 28 '17 at 17:41
  • \$\begingroup\$ @HermanLauenstein Thanks! :) \$\endgroup\$ – Arnauld Sep 28 '17 at 17:55
2
\$\begingroup\$

Java 8, 95 93 bytes

String c(String s,int n){return"v->\""+(n-->1?c(s,n).replaceAll("[\\\\\"]","\\\\$0"):s)+'"';}

-2 bytes thanks to @Lynn.

Escaping special characters is so annoying in Java..

Try it here and try the resulting method here.

Explanation:

String c(String s,int n){  // Method with String and int parameters and String return-type
  return"v->\""+           //  Return literal "v->" + a leading double-quote +
   (n-->1?                 //   If `n` is larger than 1:
     c(s,n)                //    Recursive-call,
      .replaceAll("[\\\\\"]","\\\\$0")
                           //    with all double-quotes ('"') and slashes ('\') escaped
    :                      //   Else:
     s)                    //    The input String
   +'"';                   //   + a trailing double quote
}                          // End of method 

Additional explanation for the regex replacement:

.replaceAll("[\\\\\"]","\\\\$0")
.replaceAll("        ","      ")  // Replace the match of the 1st String, with the 2nd
             [      ]             //  One of these inner characters:
              \\\\                //   Escaped slash ('\')
                  \"              //   Escaped double-quote ('"')
                                  //  And replace them with:
                        \\\\      //   Escaped slash ('\'),
                            $0    //   plus found match

Why all these slashes?

\   →  \\       // Escapes a single slash for the regex
\\  →  \\\\     // Escapes both regex-escaped slashes for the String
"   →  \"       // Escapes a double-quote for the String
\$\endgroup\$
  • 1
    \$\begingroup\$ I don’t think you need to escape " in a regex character class, so \\\\\" (five backslashes) should be fine. \$\endgroup\$ – Lynn Sep 28 '17 at 16:10
1
\$\begingroup\$

GolfScript, 5 bytes

~{`}*

Try it online!

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

Firefox JavaScript, 41 35 bytes

f=(s,n)=>"_=>"+uneval(--n?f(s,n):s)

Firefox has a nice uneval, which does what it sounds like - unevals a given object, in this case - string.

\$\endgroup\$
5
\$\begingroup\$

Python 2, 40 bytes

f=lambda r,t:r and"print%r"%f(r-1,t)or t

Try it online!

-4 bytes thanks to xnor

\$\endgroup\$
0
\$\begingroup\$

Pyth, 21 bytes

L++NsXbJ,N\\+L\\JNyFz

Try it here.

Unfortunately the recursive function (not full program as above) is longer (24 bytes):

M?GgtG++NsXHJ,N\\+L\\JNH
\$\endgroup\$
10
\$\begingroup\$

sh + coreutils, 31 bytes

yes exec sed 1d \$0|sed $1q;cat

Takes n as a command-line parameter and s on STDIN.

\$\endgroup\$
  • 8
    \$\begingroup\$ This code says: "Yes, you definitely have to execute me." \$\endgroup\$ – RedClover Sep 28 '17 at 4:29
  • \$\begingroup\$ Can you add an explanation? I’m having trouble working it out \$\endgroup\$ – JoshRagem Sep 28 '17 at 14:07
  • 1
    \$\begingroup\$ @JoshRagem yes repeatedly prints its command line, which is exec sed 1d $0 (the $ is a shell metacharacter so it has to be quoted). sed $1q stops printing after $1 (i.e. n) lines. cat then copies the input string. The resulting file is a sh script that tells the shell to replace itself with a copy of sed with the parameters 1d and the script's file name. sed then skips the first line of the file and outputs the rest. Each script has one fewer exec sed 1d $0 prefix, until after n executions only the original input is printed. \$\endgroup\$ – Neil Sep 28 '17 at 18:29
19
\$\begingroup\$

Jelly, 2 bytes

Ṿ¡

Try it online!

Ṿ¡  Main link; left argument (text) is x, right argument (repetitions) is y
 ¡  Repeat y times:
Ṿ   Uneval x; produce code that outputs x

hehe builtins

\$\endgroup\$
  • \$\begingroup\$ This is broken, "hi" produces hi, not "hi" \$\endgroup\$ – Tahg Sep 28 '17 at 0:41
  • 10
    \$\begingroup\$ @Tahg Jelly input is automatically evaluated as Python code if it doesn't throw an error. If it does, then it's just a string. You'd have to do '"hi"' to see the expected outcome \$\endgroup\$ – HyperNeutrino Sep 28 '17 at 0:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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