Program that outputs a program that outputs a program ... that outputs "Hello!"

8

1

Challenge

Write the shortest program P such that

  • P takes any positive integer n as input, and outputs a program string P1
  • executing P1 (with no input) outputs a program string P2,

  • executing P2 (with no input) outputs a program string P3,

  • ...

  • executing Pn (with no input) outputs exactly "Hello!" (without the quotes).

Schematically:

                P(n) → P1 → P2 → ... → Pn → Hello!

Criteria

  • I/O is via stdin/stdout.
  • Program length is measured in bytes.
  • Programs consist only of ASCII printable characters.
  • There must be no duplicates among the programs P, P1,...,Pn.

EDIT: Programs P, P1,...,Pn are meant to be source code, and "executing the program" refers to whatever processing produces the output (i.e., interpretation, compilation & execution, etc.).

r.e.s.

Posted 2012-07-04T20:19:42.810

Reputation: 2 872

1

Related: http://codegolf.stackexchange.com/questions/5510/can-you-meta-quine

– dmckee --- ex-moderator kitten – 2012-07-06T20:03:39.257

@dmckee - The relationship, if any, seems very remote. Schematically, a quine's behavior is like P-->P, and the linked programs' behavior is like P-->Q-->P; but here the behavior is like P(n)-->...-->Hello!, where P is not required to resemble any of the outputs. – r.e.s. – 2012-07-07T00:12:07.960

1That's not a criticism, r.e.s., just a note that people who like this problem might like the other one as well. – dmckee --- ex-moderator kitten – 2012-07-07T00:21:41.817

@dmckee - Good point, thanks. – r.e.s. – 2012-07-07T00:31:04.097

Answers

10

Golfscript 39 14

~'Hello!'{`}@*

Example:

Assuming that n=4 and our program is P, these are the steps:

  1. Run P with parameter 4. The output is "\"\\\"\\\\\\\"Hello!\\\\\\\"\\\"\"" (P1)

  2. Running P1 outputs "\"\\\"Hello!\\\"\"" (P2)

  3. Running P2 outputs "\"Hello!\"" (P3)

  4. Running P3 outputs "Hello!"(P4)

  5. Running P4 outputs Hello!. If you don't trust me, follow this link ☺.

Cristian Lupascu

Posted 2012-07-04T20:19:42.810

Reputation: 8 369

1I find your P1,P2,P3,P4 behaving as required, but with input from stdin your P doesn't output P1 -- instead, it outputs \'\\\'\\\\\\\'Hello!\\\\\\\'\\\'\' (i.e., missing the outer quotes), when I run it both under Linux and under Win 7 (using echo 4 | ... at a command prompt). Any idea what the problem might be? – r.e.s. – 2012-07-04T23:04:07.750

@r.e.s. You are right; that's a shortcoming of the Golfscript testing website I made. I managed to fix that by adding three chars, but in the meantime I found a much shorter version and edited my post. – Cristian Lupascu – 2012-07-05T07:31:03.240

@r.e.s. The correct version of the old approach is ~''\(,{)2\?('\\'*}/]"'"*:z"'Hello!"z-1%"'" – Cristian Lupascu – 2012-07-05T07:36:18.260

At 14 bytes, impressive! ... and nice website btw. (It seems that stdin can be simulated by preceding a program by ;"...", where ... is the input. E.g., ;"4" would have revealed the missing-quote problem above, whereas simply preceding the program by "4" does not.) ... – r.e.s. – 2012-07-05T12:54:25.320

@r.e.s. Thanks a lot! You are absolutely right about the leading ;. When I wrote the first program I forgot about this along the way, although it was me who wrote about it on the meta site: http://meta.codegolf.stackexchange.com/a/521/3527

– Cristian Lupascu – 2012-07-05T12:58:08.963

4

Perl (45 36)

say"say q("x($m=<>),"Hello!",")"x$m         

Run with perl -M5.010 to use say.

For n=1, outputs say q(Hello!)
For n=2, outputs say q(say q(Hello!))
For n=3, outputs say q(say q(say q(Hello!)))
and so on.

marinus

Posted 2012-07-04T20:19:42.810

Reputation: 30 224

4

JavaScript, 58 chars

function $(_){alert(_?$+'$('+--_+')':'Hello!')}$(prompt())

copy

Posted 2012-07-04T20:19:42.810

Reputation: 6 466

How does it works? – thepirat000 – 2014-03-08T22:58:24.347

@thepirat000 If the argument _ is 0, it outputs "Hello!", otherwise it outputs the function definition and call with _ minus one – copy – 2014-03-08T23:30:03.720

+1 for abusing rules by using a counter rather than elongating the code... – WallyWest – 2014-03-09T11:59:02.053

2

Common Lisp: 65

#1=(SETF N(READ)(CADDR'#1#)(1- N)W(PRINT(IF(= N 0)"Hello!"'#1#)))

This version is smaller than the existing CL-answer. In case your Lisp croaks with a stackoverflow, then you have to use this, 81 bytes:

#1=(SETF N(READ)*PRINT-CIRCLE* T(CADDR'#1#)(1- N)W(PRINT(IF(= N 0)"Hello!"'#1#)))

I know I'm late to the party, and I'm sure this could still be optimized.

Demonstration (careful, some online REPLs don't work correctly):

* #1=(SETF N(READ)*PRINT-CIRCLE* T(CADDR'#1#)(1- N)W(PRINT(IF(= N 0)"Hello!"'#1#)))
2
#1=(SETF N 1
         *PRINT-CIRCLE* T
         (CADDR '#1#) (1- N)
         W
           (PRINT
            (IF (= N 0)
                "Hello!"
                '#1#))) 
#1=(SETF N 1
         *PRINT-CIRCLE* T
         (CADDR '#1#) (1- N)
         W
           (PRINT
            (IF (= N 0)
                "Hello!"
                '#1#)))
* (eval *)

#1=(SETF N 0
         *PRINT-CIRCLE* T
         (CADDR '#1#) (1- N)
         W
           (PRINT
            (IF (= N 0)
                "Hello!"
                '#1#))) 
#1=(SETF N 0
         *PRINT-CIRCLE* T
         (CADDR '#1#) (1- N)
         W
           (PRINT
            (IF (= N 0)
                "Hello!"
                '#1#)))
* (eval *)
"Hello!" 
"Hello!"
* 

Note that:

  • Tested using SBCL 1.2.11.debian

  • There are lots of warnings because I'm doing things that are seriously not supposed to be done. Thankfully, all warnings are printed with a semi-colon, so they would be treated as comments anyway.

  • Duplication is because one is the return value and one actual output. If the return value would also count, then it simplifies to 58 bytes: #1=(SETF N(READ)(CADDR'#1#)(1- N)W(IF(= N 0)"Hello!"'#1#))

  • I still know I'm late to the party

Mike Gebirge

Posted 2012-07-04T20:19:42.810

Reputation: 121

2

Python3, 66

r="print(%r)";e=eval;n=e(input())+1;e(e("(r%"*n+"'Hello!'"+")"*n))

Ev_genus

Posted 2012-07-04T20:19:42.810

Reputation: 341

2

Common Lisp, 68 characters

(do((n(read)(1- n))(s'(princ"Hello!")`(print',s)))((= 0 n)(eval s)))
(do ((n (read) (1- n))
     (s '(princ "Hello!") `(print ',s)))
    ((= 0 n) (eval s)))

The only non-straightforward thing: it generates one more level of program than needed and evaluates it, because eval is one character shorter than print.

Kevin Reid

Posted 2012-07-04T20:19:42.810

Reputation: 1 693

1

Bash, 47 or 12 (if I use golfbash)

Code:

read x;for((;x>=0;x--)){ O+=" echo";};$O Hello!

golfbash code:

R;n e Hello!

Previous code (49):

read x;E=echo;eval \"\${E[0]\"{0..$x}\"}\" Hello!

Use:

Make program P

$ echo '<paste code here>' > P

$ chmod +x P

Example

Make P1:

$> echo 4 | ./P > 
echo echo echo echo Hello!

Make P2:

$> echo 4 | ./P | bash
echo echo echo Hello!

Make P3:

$ echo 4 | ./P | bash | bash
echo echo Hello!

Make P4:

$ echo 4 | ./P | bash | bash | bash
echo Hello!

Run P4:

$ echo 4 |./P | bash | bash | bash | bash
Hello!

Say that I make a new general purpose language called golfbash - at bit like golfscript - that has some useful commands like these:

R which reads stdin and places result into variable $REPLY.
n $1 $2 which echo's $1 $REPLY times followed by $2.
e which echo's all parameters to stdout.

Then I could write this:

R;n e Hello!

This would be legal, would't it?

philcolbourn

Posted 2012-07-04T20:19:42.810

Reputation: 501

+1. I guess the downvote was for your invented language that appears to be specifically for this challenge. See http://meta.codegolf.stackexchange.com/questions/871/creating-new-language-would-it-be-legal

– Cees Timmerman – 2015-10-30T10:59:15.663

Fine, but I did it in bash as well. – philcolbourn – 2015-11-01T11:22:27.733

1That's rude. -1 for what? – philcolbourn – 2014-03-08T09:14:49.093

1

Python 2.7, 57

print reduce(lambda x,y:y+`x`,input()*["print"],"Hello!")

JPvdMerwe

Posted 2012-07-04T20:19:42.810

Reputation: 2 565

1

Haskell, 62

main=interact$(iterate(("main=putStr"++).show)"Hello!"!!).read

Joey Adams

Posted 2012-07-04T20:19:42.810

Reputation: 9 929

0

J - 31 char

Keep in mind that J uses Pascal-style strings: 'It''s too easy!'

'Hello!'(],,)''''#~<:2^".1!:1]1

Explained:

  • ".1!:1]1 - Read in a line from stdin and convert it to a number.
  • <:2^ - Take 2 to the power of this number, and decrement.
  • ''''#~ - Make a string with that many copies of the single quote character.
  • 'Hello!'(],,) - Append these quotes to the front and back of Hello!.

Usage:

   'Hello!'(],,)''''#~<:2^".1!:1]1   NB. let's try 3
3
'''''''Hello!'''''''
   '''''''Hello!'''''''  NB. P1
'''Hello!'''
   '''Hello!'''          NB. P2
'Hello!'
   'Hello!'              NB. and P3 prints Hello!
Hello!

algorithmshark

Posted 2012-07-04T20:19:42.810

Reputation: 8 144

0

Python 2.7: 75

def h(n):
 return "Hello"if n<1 else'print %s' % `h(n-1)`
print h(input())

First time golfing, not sure if I'm doing it right ;p

heo

Posted 2012-07-04T20:19:42.810

Reputation: 91

2Doesn't that assume that the definition of h is also known in the subsequent programs? (So that this would have to be run in a REPL or something?) – Martin Ender – 2015-05-29T10:01:59.913

0

F#, 182

let say msg = sprintf "%s" msg
let gen num = 
    let rec g n a =
        match n with
        | i when i > 0 -> g (i-1) ("say \"" + a + "\"")
        | _ -> say a
    g num "Hello!"

vasu

Posted 2012-07-04T20:19:42.810

Reputation: 1

When I run your program, it does not appear to input anything from stdin, nor to output anything to stdout.

– r.e.s. – 2012-07-06T12:50:34.663

0

Clojure, 36 bytes

(str(apply str(repeat 5\'))"Hello!")

Symbol

'something

evaluates to

something

Build up a symbol with 5 single quotes and run the result until no quotes left.

Michael M

Posted 2012-07-04T20:19:42.810

Reputation: 101