Program template for printing *any* string

41

6

Write a program with the following properties:

  • When run as-is, the program produces no output (i.e. 0 bytes of output).

  • There is a location within the program (of your choice: it could be at the start, end, or somewhere in the middle) with the following property: modifying the program via placing any string there will cause the resulting program to print that string when executed.

    This must work regardless of whether the string contains quotes, backslashes, comment marks, delimiters, NUL bytes, etc.; no matter what you place there, the string is still interpreted as a string and printed entirely verbatim. You can, however, fail to handle very very long strings if they would cause the compiler to run out of memory, or the like (to be precise, you should at least be able to handle strings up to 1000 bytes long or three times the length of your program, whichever is longer).

An example of an invalid solution would be

print("");
#      ^ text goes here

in Python, Perl, Ruby, etc.; although it works for many strings, it will not work for a string containing a double quote, or a string containing the substring \n (which would be interpreted as a newline).

Note that this problem is probably impossible in most languages; the challenge is at least partially about finding a language where it works. Your chosen language must be a programming language under this site's definition, e.g. no submitting a solution in Text.

As this is a , the shortest program template wins. However, do not be discouraged from submitting solutions even if they can't beat the current winner! You can still compete for second, third, etc. place, or simply to find as many answers where it works as possible. You should, however, ensure that your program meets the entire specification before submitting it; approximate solutions would miss the point of the problem.

user62131

Posted 2016-11-24T00:45:52.910

Reputation:

The relevant Sandbox post is here.

– None – 2016-11-24T00:46:17.003

Can you clarify the range of characters we need to support for the inserted string? ASCII? ASCII + unprintable? All of unicode? – James – 2016-11-24T00:53:26.797

3All 256 octets. Whether you interpret those as bytes or Unicode is up to you; it won't make much difference when it's printed. – None – 2016-11-24T00:54:25.010

When outputting the string, does it have to be only the string that's output or can there be extra stuff (along the lines of this is the string: '<string_here>')? – milk – 2016-11-24T01:01:18.650

1The intent of the question (and the way it's currently worded) is that you can't have any additional output. Did you have a solution in mind that can't be adapted to avoid it? (Using extra bytes to avoid stray output is preferable to creating stray output and not complying with the spec.) – None – 2016-11-24T01:04:40.643

My idea was to write a program that doesn't print anything, but adding any string makes it output syntax error: '<string_here>' when run. ;p I guess I'll try to think of something else... – milk – 2016-11-24T01:06:30.677

I suspect that doesn't work because syntax errors tend to stop at newlines rather than printing the whole of the rest of the program source. Interesting idea, though. – None – 2016-11-24T01:08:51.827

Newlines are allowed in ruby strings, and I think python strings as well. Just to be pedantic. – Conor O'Brien – 2016-11-24T02:24:56.897

That's why I didn't specify newline as a character that would break. Rather, the two characters backslash, n break in the example because they're incorrectly interpreted as a newline. – None – 2016-11-24T02:40:37.423

@jimmy23013 Well, I don't know. Can you prove that it's impossible? It seems impossible, but I'm not 100% sure. (If replacements weren't done in a loop, it would be as simple as //\\/.) If you're sure it's impossible then we might as well delete the comments. – Martin Ender – 2016-11-24T10:29:19.047

@MartinEnder Let S be the first matched string, A be a character different from the first and last character of S. A len(S) times cannot be changed by the first replacement. Let X be A len(S) times concatenated with S, and Y be the result of the first replacement applied to X. Y cannot contain S, so applying the first replacement to it yield itself too. Prefixing a string won't make a difference either, because of the A len(S) times part. X and Y would be indistinguishable afterwards. – jimmy23013 – 2016-11-24T10:51:18.150

If the string will never have either of these characters 「」 that will be as simple as print 「」 in Perl 6.

– Brad Gilbert b2gills – 2016-11-24T20:43:34.197

Do trailing newlines count? – user8397947 – 2016-11-25T15:51:19.863

You should aim to reproduce the trailing newlines of the strings. You're trying to make a byte-by-byte copy of them. – None – 2016-11-25T16:23:48.050

1If this didn't require a code change, it'd be trivial in AWK, just 1 would do it. – Robert Benson – 2017-05-04T21:03:11.470

Answers

37

Excel, 1 byte

'

Ungolfed version

'        <-- print the following text,
             and exit the current formula

Adam

Posted 2016-11-24T00:45:52.910

Reputation: 591

I don't think this can accept newlines. – Conor O'Brien – 2016-11-25T01:34:31.553

3@ConorO'Brien it does with shift+enter – Adam – 2016-11-25T06:05:44.000

2@MrPaulch This was quite a lot of retro engineering. I am pretty sure this command hides some other unknown functionnalities, like crashing the system. – Adam – 2016-11-25T08:02:13.113

1This also works on OpenOffice Calc. It is used automatically when you set a cell to the format @. – Ismael Miguel – 2016-11-26T01:10:57.450

1Personally I think this answer is fine. @Dennis deleted my Mathematica post which uses the same concept. The front end of excel will store test // " "" /// as a non-verbatim string so by his logic, this should be deleted. Here is how it's stored <Row> <Cell><Data ss:Type="String" x:Ticked="1">test // " "" ///</Data></Cell>

</Row> – Kelly Lowder – 2016-11-28T15:37:44.093

20

Jolf, 6 bytes

a Lq6(

Explanation

a Lq6(
a       print
  L 6   all but the first 6 characters of
   q    the source code
     (  and exit

Conor O'Brien

Posted 2016-11-24T00:45:52.910

Reputation: 36 228

15

Perl 5, 30 21 19 bytes

print<DATA>__END__

Try it online!

Trailing newline. This makes use of a Perl feature which allows arbitrary data to be appended to the source file, which can then be read via the DATA filehandle. When we give a filehandle as an argument to print, it's given a list context, which causes the filehandle to return a list of all the lines in the file, newlines included (likewise, a newline on the final line will be omitted). Then print implicitly concatenates them all, undoing the splitting into lines and giving us the exact original string regardless of where the newlines were.

Thanks to @Dada, who realised there was no need to handle newlines manually, and @ninjalj and @b_jonas, who each spotted a character which could be golfed off.

user62131

Posted 2016-11-24T00:45:52.910

Reputation:

2I don't think you need undef$/. As an argument of print, <DATA> is called in list context, so it should read every line there is. – Dada – 2016-11-24T07:05:38.910

You're right. It reads the input a line at a time, keeping the line separators, then implicitly concatenates them all when printing, so there's no need to slurp in the first place. That's an 8-byte saving, as well; I'll go fix the post. – None – 2016-11-24T07:19:18.810

4You can use __END__ instead of __DATA__. – ninjalj – 2016-11-25T18:57:37.087

What @ninjalj says, plus you can omit the newline after the greater than sign (but you do need the newline at the end of the program). – b_jonas – 2017-01-02T16:49:12.577

14

Zsh, 6 bytes

<<'
'

There is a trailing newline. The string is inserted at the end of the program.

Bash, 20 17 bytes

Thanks to Adam for removing 3 bytes.

exec sed 1d "$0"

*nix shell script, 21 14 bytes

Thanks to Adam for removing 7 bytes.

#!/bin/sed 1d

jimmy23013

Posted 2016-11-24T00:45:52.910

Reputation: 34 042

1@Copper There is a trailing newline. The string is inserted after that. – jimmy23013 – 2016-11-24T00:57:47.590

Ah, I see. Thanks for correcting me! – Copper – 2016-11-24T00:58:23.820

The 6/9-byte solutions look like they're exploiting a bug in the interpreter to me (not that that's disallowed, of course). (AFAICT with some experimentation, they're looking for a newline on a line by itself, but the lines are defined by splitting on newlines, so a newline on a line by itself can never happen.) The zsh solution seems correct; however, the 9-byte bash solution is wrong (it adds a trailing newline if the file doesn't have one). – None – 2016-11-24T07:54:37.673

@ais523 Seemed to be a bug to me too. And I didn't expect them to be allowed by the interpreters. Removed the Bash solution. – jimmy23013 – 2016-11-24T08:02:30.190

1for bash you can use sed 1d instead of tail -n+2 – Adam – 2016-11-25T11:31:04.417

13

brainfuck (Unreadable Brainfuck), 9 bytes

,+[-.,+]!

Append the input to the end. There isn't a trailing newline, this time.

Looking for languages which would accept input appended to the end of the program, brainfuck seemed like a distinct possibility; many brainfuck interpreters written in esolangs take both the program and the program's input from standard input, and thus need some way to tell between them. There's a convention that's used in this case that a ! character differentiates between the program and the input, a trick that's often used to write short brainfuck programs like ,[.,]!Hello, world!; this basically creates a different dialect of brainfuck in which ! has a different meaning from normal.

In theory, therefore, we could just find one of these interpreters and give it a cat program in order to fulfil the spec. There's a major subtlety, though; brainfuck typically uses 256 values for each cell, there are 256 octets, and one needs to be used for EOF. So if we want to be able to echo all 256 octets literally, we can't detect EOF at all and will need to end the program some other way. In other words, we need to find an implementation that either gives the 256 octets and EOF 257 different values, or that crashes on EOF.

Enter Unreadable. There's a brainfuck interpreter in Unreadable that predates this challenge, and which accepts input after an !; additionally, unlike most brainfuck interpreters, it uses bignum cells and -1 for EOF, allowing EOF to be distinguished from the other 256 possible octets. Thus, by use of Unreadable Brainfuck as the specific interpreter for the program, we can solve the challenge in just 9 bytes, via writing a brainfuck cat program that halts on EOF=-1.

Is it possible to do better? Well, we could try the following 7-byte program, which attempts to output EOF at the end of the string before it breaks out of the loop:

+[,.+]!

The behaviour of this program depends on the behaviour of the Unreadable interpreter on error conditions (thus, it depends not only on the implementation of brainfuck, but on the implementation used to run the implementation of brainfuck). Unfortunately, the Unreadable interpreter I use outputs errors on standard output, meaning that this saving doesn't work. If anyone knows of an Unreadable interpreter that exits on an attempt to output EOF, or silently skips the attempt, let me know; that would be a seven-byte solution right there.

user62131

Posted 2016-11-24T00:45:52.910

Reputation:

1,[.,]! works here and is 6 bytes (just tick the box marked !). Also it terminates. – FinW – 2016-11-24T19:25:33.193

@FinW: I can't figure out how to enter a NUL byte into that website, but that code would definitely terminate early if it saw one. – None – 2016-11-25T04:32:27.037

it worked fine without a NUL byte when I did it. – FinW – 2016-11-26T10:34:56.937

1You literally have a , (read standard input to the current tape element) followed by a ] (exit loop if current tape element is 0). Thus, reading an input byte with value 0 (i.e. NUL) would break the loop. – None – 2016-11-26T20:22:10.180

But if the interpreter reads no input, (e.g. the end of the string after the !) it automatically sets the current tape element to 0, therefore ending the loop. – FinW – 2016-11-27T11:07:47.663

Yes, and if it reads a NUL that isn't the end of the input, it also sets the current tape element to 0, therefore ending the loop. You not only have to handle exiting at the end of the file; you also have to handle not exiting not at the end of the file. – None – 2016-11-28T16:31:17.970

9

Dyalog APL, 11 bytes

The following is the body of the function f:

2↓⎕CR'f'⋄→

There is a trailing newline, after which anything may be inserted.

2↓ drop the first two lines (header and this line) of

⎕CR'f' the Character Representation of f

then

quit

Adám

Posted 2016-11-24T00:45:52.910

Reputation: 37 779

9

Ruby, 20 bytes

print *DATA
__END__

Input goes at the end (after the trailing newline). The DATA idiom is one of many that Ruby stole from Perl.

Try it on eval.in: https://eval.in/684370

Jordan

Posted 2016-11-24T00:45:52.910

Reputation: 5 001

1It not only stole it, it even is shorter... – simbabque – 2016-11-24T15:44:09.317

9

JavaScript + HTML5 DOM, 163 Bytes

<html><body><script>fetch(location).then((r)=>r.text().then((t)=>console.log(t.slice(145,t.lastIndexOf("</b")))));document.body.remove()</script></body></html>

You may insert anything you like directly before the closing body tag. This works by fetching the page source and stripping the opening code and the closing tags.

The real kicker was figuring out how to escape an infinite loop. Putting while(true){} in the page blocks all callbacks forever, freezing the execution, and JavaScript has no way of pausing the main thread. However, code that no longer exists never runs, so the document body commits seppuku in the very last command, deleting itself while it waits for its clone to load.

Yeah, it's long and roundabout, but the mere fact that it's possible in JS is kind of amazing.

Emmett R.

Posted 2016-11-24T00:45:52.910

Reputation: 241

1Chrome's got all annoyed at parser-blocking scripts recently, and complains about them a bunch. I like the idea of blocking the parser intentionally to prevent any script in it from ruining your printing attempt. – None – 2016-11-26T20:19:17.397

7

PHP, 46 bytes

(including the trailing linebreak)

<?=join([""]+file(__FILE__));halt_compiler();
STRING HERE

Yes: even the file function is binary safe.

[""]+ replaces the 0-index (first line of the file) with an empty string

Titus

Posted 2016-11-24T00:45:52.910

Reputation: 13 814

6

gs2, 4 bytes

╥¶=☼

Uses CP437 encoding. The string goes at the end. gets the source code, pushes 4, = drops that many leading characters, and exits.

Try it online!

Lynn

Posted 2016-11-24T00:45:52.910

Reputation: 55 648

5

PHP 94 bytes

<?$f=fopen(__FILE__,'rb');fseek($f,93);while(false!==($c=fgetc($f)))echo$c;__halt_compiler();

Place your string after the final semicolon.

Yay for obscure features I guess? __halt_compiler() does exactly what you'd expect from the name. The prior code just opens the file and writes any bytes after that last semicolon to stdout. NUL, BEL etc come out fine. Unicode literals (♪) get screwed up on Windows but I think that's just Windows cmd failing at unicode.

ToXik-yogHurt

Posted 2016-11-24T00:45:52.910

Reputation: 311

>

  • I count 93 bytes, not 94.
  • false!==$c=... needs no parentheses.
  • rb needs no quotes.
  • You can save one byte with for($f=fopen(...),fseek($f,88);false!==(...);)echo$c;
  • another two bytes shorter:
  • <?for($f=fopen(__FILE__,rb);false!==$s=fgets($f,86);)echo$i++?$s:"";__halt_compiler(); – Titus – 2016-11-27T00:47:59.443

    start="6">

  • and another two bytes if you omit the second parameter for fgets and add a trailing linebreak to the template.
  • < – Titus – 2016-11-27T00:52:34.223

    3

    Perl 6, 23 bytes

    print $=finish
    =finish
    
    
    

    The string is placed starting on the newline after =finish.

    Brad Gilbert b2gills

    Posted 2016-11-24T00:45:52.910

    Reputation: 12 713

    3

    PHP, 48 60 bytes

    <?=substr(file_get_contents(__FILE__),60);__halt_compiler();STRING HERE
    

    Just became aware that closing PHP does not prevent the string from containing <?.

    Titus

    Posted 2016-11-24T00:45:52.910

    Reputation: 13 814

    You've got a misplaced closing bracket. Much neater file dump than my attempt though, I thought substr() would choke on null bytes - guess not. – ToXik-yogHurt – 2016-11-25T16:20:01.753

    Try this: <?die(substr(file_get_contents(__FILE__),48))?>STRING HERE. Should work. I've tried with <?die('a')?> and it worked.

    – Ismael Miguel – 2016-11-26T01:38:38.780

    @IsmaelMiguel will not work. die does not print it´s parameter, but send it as exit code. That would have to ´be die(print ...). – Titus – 2016-11-26T22:57:44.327

    @ToXik-yogHurt most string functions are binary safe. even file. Actually I currently can´t think of any that´s not. – Titus – 2016-11-27T00:29:52.743

    @Titus Try die('text'); – Ismael Miguel – 2016-11-27T00:58:39.657

    I know I'm repeating myself, but die() outputs text. It was used a lot like mysql*_connect(...) or die('Error while connection to DB'); – Ismael Miguel – 2016-11-27T01:09:01.267

    @IsmaelMiguel It may, but it won´t stop the compiler from parsing. – Titus – 2016-11-27T01:12:29.597

    Oh, you changed your answer. Sorry. – Ismael Miguel – 2016-11-27T01:15:01.230

    2

    Bash, 17 bytes

    tail -n+3 $0
    exit
    <string here>
    

    Developed independently of jimmy23013's answer.

    noɥʇʎԀʎzɐɹƆ

    Posted 2016-11-24T00:45:52.910

    Reputation: 1 316

    Don't you mean $0? Apart from that, I think it works (I've confirmed that it doesn't parse anything after exit). – None – 2016-11-25T15:16:41.413

    @ais523 Fixed! Thanks. – noɥʇʎԀʎzɐɹƆ – 2016-11-25T15:37:34.033

    2

    Binary Lambda Calculus, 1 byte

     [text goes here]
    

    That’s a single space (0x20) before the text.

    Try it online!

    How it works

    0x20 = 001000002 is parsed as

    00    λx.
    01        x
    0000  (ignored, can be anything)
    

    (So in fact, any of the characters !"#$%&\'()*+,-./ will work equally well.)

    Since this is a complete expression, the remainder of the program is interpreted as input data, and under the binary lambda calculus I/O conventions, the identity function λx. x copies the input directly to the output.

    Anders Kaseorg

    Posted 2016-11-24T00:45:52.910

    Reputation: 29 242

    Out of interest, why don't the trailing zero bits between the identity function and insertion get echoed? – None – 2017-06-11T09:11:22.657

    @ais523 The interpreter reads a byte at a time, and once λx. x has been parsed, the padding has already been consumed. – Anders Kaseorg – 2017-06-11T09:22:03.673

    1

    RProgN, 19 Bytes

    Q 19 Q L sub exit 
    

    Note the trailing space.

    Insert any text after that chunk and it will be printed.

    Based off of Lynn's gs2 answer.

    Try it Online!

    ATaco

    Posted 2016-11-24T00:45:52.910

    Reputation: 7 898

    1

    Excel VBA, 6 Bytes

    This is mainly to answer the question of how to print the text as held in Adam's Answer to the Immediates Window in the VBA environment

    Basic Setup:

    In cell A1 in the activesheet the use the formula below to hold the string to be printed. For the sake of byte counting this shall add 1 Byte

    '[Your Text Here]
    

    eg:

    'Hello 
    World
    

    Immediates Window Function, 5 + 1 = 6 Bytes

    ?[A1]
    

    +1 Byte for a ' in cell A1

    Taylor Scott

    Posted 2016-11-24T00:45:52.910

    Reputation: 6 709

    0

    Vim (in ex mode), 28 bytes

    #!/bin/ex -c ':1d' -c ':wq'
    [string]
    

    28 bytes is including the last newline.

    iBug

    Posted 2016-11-24T00:45:52.910

    Reputation: 2 477

    0

    Vim, 738 bytes

    :imap <esc> <c-v><esc>
    :imap <c-a> <c-v><c-a>
    :imap <c-b> <c-v><c-b>
    :imap <c-c> <c-v><c-c>
    :imap <c-d> <c-v><c-d>
    :imap <c-e> <c-v><c-e>
    :imap <c-f> <c-v><c-f>
    :imap <c-g> <c-v><c-g>
    :imap <c-h> <c-v><c-h>
    :imap <c-i> <c-v><c-i>
    :imap <c-j> <c-v><c-j>
    :imap <c-k> <c-v><c-k>
    :imap <c-l> <c-v><c-l>
    :imap <c-m> <c-v><c-m>
    :imap <c-n> <c-v><c-n>
    :imap <c-o> <c-v><c-o>
    :imap <c-p> <c-v><c-p>
    :imap <c-q> <c-v><c-q>
    :imap <c-r> <c-v><c-r>
    :imap <c-s> <c-v><c-s>
    :imap <c-t> <c-v><c-t>
    :imap <c-u> <c-v><c-u>
    :imap <c-v> <c-v><c-v>
    :imap <c-w> <c-v><c-w>
    :imap <c-x> <c-v><c-x>
    :imap <c-y> <c-v><c-y>
    :imap <c-z> <c-v><c-z>
    :imap <c-@> <c-v><c-@>
    :imap <c-\> <c-v><c-\>
    :imap <c-]> <c-v><c-]>
    :imap <c-^> <c-v><c-^>
    :imap <c-?> <c-v><c-?>
    i
    

    Rebinds all control characters in insert mode to <c-v>, followed by that control character, which will enter them literally. ^_ (unit seperator) doesn't seem to need rebinding, as it gets outputted literally by default.

    The variable text comes at the end, of course.

    L3viathan

    Posted 2016-11-24T00:45:52.910

    Reputation: 3 151