40
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ The relevant Sandbox post is here. \$\endgroup\$ – user62131 Nov 24 '16 at 0:46
  • \$\begingroup\$ Can you clarify the range of characters we need to support for the inserted string? ASCII? ASCII + unprintable? All of unicode? \$\endgroup\$ – DJMcMayhem Nov 24 '16 at 0:53
  • 3
    \$\begingroup\$ All 256 octets. Whether you interpret those as bytes or Unicode is up to you; it won't make much difference when it's printed. \$\endgroup\$ – user62131 Nov 24 '16 at 0:54
  • 1
    \$\begingroup\$ The 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.) \$\endgroup\$ – user62131 Nov 24 '16 at 1:04
  • 1
    \$\begingroup\$ If this didn't require a code change, it'd be trivial in AWK, just 1 would do it. \$\endgroup\$ – Robert Benson May 4 '17 at 21:03

19 Answers 19

37
\$\begingroup\$

Excel, 1 byte

'

Ungolfed version

'        <-- print the following text,
             and exit the current formula
\$\endgroup\$
  • \$\begingroup\$ I don't think this can accept newlines. \$\endgroup\$ – Conor O'Brien Nov 25 '16 at 1:34
  • 3
    \$\begingroup\$ @ConorO'Brien it does with shift+enter \$\endgroup\$ – Adam Nov 25 '16 at 6:05
  • 2
    \$\begingroup\$ @MrPaulch This was quite a lot of retro engineering. I am pretty sure this command hides some other unknown functionnalities, like crashing the system. \$\endgroup\$ – Adam Nov 25 '16 at 8:02
  • 1
    \$\begingroup\$ This also works on OpenOffice Calc. It is used automatically when you set a cell to the format @. \$\endgroup\$ – Ismael Miguel Nov 26 '16 at 1:10
  • 1
    \$\begingroup\$ Personally 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 // &quot; &quot;&quot; ///</Data></Cell> </Row> \$\endgroup\$ – Kelly Lowder Nov 28 '16 at 15:37
20
\$\begingroup\$

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
\$\endgroup\$
15
\$\begingroup\$

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.

\$\endgroup\$
  • 2
    \$\begingroup\$ I 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. \$\endgroup\$ – Dada Nov 24 '16 at 7:05
  • \$\begingroup\$ 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. \$\endgroup\$ – user62131 Nov 24 '16 at 7:19
  • 4
    \$\begingroup\$ You can use __END__ instead of __DATA__. \$\endgroup\$ – ninjalj Nov 25 '16 at 18:57
  • \$\begingroup\$ 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). \$\endgroup\$ – b_jonas Jan 2 '17 at 16:49
14
\$\begingroup\$

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
\$\endgroup\$
  • 1
    \$\begingroup\$ @Copper There is a trailing newline. The string is inserted after that. \$\endgroup\$ – jimmy23013 Nov 24 '16 at 0:57
  • \$\begingroup\$ Ah, I see. Thanks for correcting me! \$\endgroup\$ – Copper Nov 24 '16 at 0:58
  • \$\begingroup\$ 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). \$\endgroup\$ – user62131 Nov 24 '16 at 7:54
  • \$\begingroup\$ @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. \$\endgroup\$ – jimmy23013 Nov 24 '16 at 8:02
  • 1
    \$\begingroup\$ for bash you can use sed 1d instead of tail -n+2 \$\endgroup\$ – Adam Nov 25 '16 at 11:31
13
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ ,[.,]! works here and is 6 bytes (just tick the box marked !). Also it terminates. \$\endgroup\$ – FinW Nov 24 '16 at 19:25
  • \$\begingroup\$ @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. \$\endgroup\$ – user62131 Nov 25 '16 at 4:32
  • \$\begingroup\$ it worked fine without a NUL byte when I did it. \$\endgroup\$ – FinW Nov 26 '16 at 10:34
  • 1
    \$\begingroup\$ You 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. \$\endgroup\$ – user62131 Nov 26 '16 at 20:22
  • \$\begingroup\$ 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. \$\endgroup\$ – FinW Nov 27 '16 at 11:07
9
\$\begingroup\$

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

\$\endgroup\$
9
\$\begingroup\$

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

\$\endgroup\$
  • 1
    \$\begingroup\$ It not only stole it, it even is shorter... \$\endgroup\$ – simbabque Nov 24 '16 at 15:44
9
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ Chrome'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. \$\endgroup\$ – user62131 Nov 26 '16 at 20:19
7
\$\begingroup\$

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

\$\endgroup\$
6
\$\begingroup\$

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!

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

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.

\$\endgroup\$
  • \$\begingroup\$ 1) I count 93 bytes, not 94. 2) false!==$c=... needs no parentheses. 3) rb needs no quotes. 4) You can save one byte with for($f=fopen(...),fseek($f,88);false!==(...);)echo$c; 5) another two bytes shorter: <?for($f=fopen(__FILE__,rb);false!==$s=fgets($f,86);)echo$i++?$s:"";__halt_compiler(); \$\endgroup\$ – Titus Nov 27 '16 at 0:47
  • \$\begingroup\$ 6) and another two bytes if you omit the second parameter for fgets and add a trailing linebreak to the template. \$\endgroup\$ – Titus Nov 27 '16 at 0:52
3
\$\begingroup\$

Perl 6, 23 bytes

print $=finish
=finish


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

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

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 <?.

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – ToXik-yogHurt Nov 25 '16 at 16:20
  • \$\begingroup\$ Try this: <?die(substr(file_get_contents(__FILE__),48))?>STRING HERE. Should work. I've tried with <?die('a')?> and it worked. \$\endgroup\$ – Ismael Miguel Nov 26 '16 at 1:38
  • \$\begingroup\$ @IsmaelMiguel will not work. die does not print it´s parameter, but send it as exit code. That would have to ´be die(print ...). \$\endgroup\$ – Titus Nov 26 '16 at 22:57
  • \$\begingroup\$ @ToXik-yogHurt most string functions are binary safe. even file. Actually I currently can´t think of any that´s not. \$\endgroup\$ – Titus Nov 27 '16 at 0:29
  • \$\begingroup\$ @Titus Try die('text'); \$\endgroup\$ – Ismael Miguel Nov 27 '16 at 0:58
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Out of interest, why don't the trailing zero bits between the identity function and insertion get echoed? \$\endgroup\$ – user62131 Jun 11 '17 at 9:11
  • \$\begingroup\$ @ais523 The interpreter reads a byte at a time, and once λx. x has been parsed, the padding has already been consumed. \$\endgroup\$ – Anders Kaseorg Jun 11 '17 at 9:22
2
\$\begingroup\$

Bash, 17 bytes

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

Developed independently of jimmy23013's answer.

\$\endgroup\$
  • \$\begingroup\$ Don't you mean $0? Apart from that, I think it works (I've confirmed that it doesn't parse anything after exit). \$\endgroup\$ – user62131 Nov 25 '16 at 15:16
  • \$\begingroup\$ @ais523 Fixed! Thanks. \$\endgroup\$ – noɥʇʎԀʎzɐɹƆ Nov 25 '16 at 15:37
1
\$\begingroup\$

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!

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

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

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

Vim (in ex mode), 28 bytes

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

28 bytes is including the last newline.

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

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.

\$\endgroup\$

Your Answer

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