# Fault-Tolerant Hello World

At the end of your interview, the Evil Interviewer tells you, "We make all of our applicants take a short coding test, to see if they really know what they are talking about. Don't worry; it's easy. And if you create a working program, I'll offer you the job immediately." He gestures for you to sit down at a nearby computer. "All you have to do is create a working Hello World program. But"--and he grins broadly--"there's a catch. Unfortunately the only compiler we have on this machine has a small bug. It randomly deletes one character from the source code file before compiling. Ok, see you in five minutes!" And he walks out of the room, whistling happily.

Can you guarantee that you will get the job?

Write a program that will print Hello, world! to standard output even after a single character is removed from any position in the file. Or come as close to this as possible.

## The Rules

No Extraneous Output - Hello, world! must be the only substantive thing printed to standard output. It is ok to include other characters if they are naturally produced by your language of choice--such as a trailing newline or even something like [1] "Hello, world!" (for example if you were using R), but it must print the exact same thing every time. It cannot print Hello, world!Hello, world! or Hello world!" && x==1 some of the time, for example. Warnings, however, are allowed.

Testing In order to test determine your score, you have to test each possible permutation of the program: test it with each character removed, and see if it produces the correct output. I have included a simple Perl program for this purpose below, which should work for many languages. If it doesn't work for you, please create a test program and include it in your answer.

Scoring Your score is the number of times your program fails. In other words, the number of individual positions in your file where deleting a character prevents your program from working. Lowest score wins. In the event of a tie, the shortest code wins.

Trivial Solutions such as "Hello, world!" in several languages (score of 15) are acceptable, but they aren't going to win.

Happy programming, and may you get the job. But if you fail, you probably didn't want to work for that evil boss anyway.

Perl test script:

use warnings;
use strict;

my $program = 'test.pl'; my$temp_file = 'corrupt.pl';
my $command = "perl -X$temp_file"; #Disabled warnings for cleaner output.
my $expected_result = "Hello, world!"; open my$in,'<',$program or die$!;
local $/; #Undef the line separator my$code = <$in>; #Read the entire file in. my$fails = 0;
for my $omit_pos (0..length($code)-1)
{
my $corrupt =$code;
$corrupt =~ s/^.{$omit_pos}\K.//s;  #Delete a single character

open my $out,'>',$temp_file or die $!; print {$out} $corrupt; #Write the corrupt program to a file close$out;

my $result = $command;    #Execute system command.
if ($result ne$expected_result)
{
$fails++; print "Failure$fails:\nResult: ($result)\n$corrupt";
}
}

print "\n$fails failed out of " . length$code;

• Can the deleted character result in the program not compiling? Is that still counted as not working? Apr 18, 2013 at 7:06
• @lochok, yes, that would count as a failure. Any deleted character which leads to Hello, World! not being printed is a failure.
– user7486
Apr 18, 2013 at 7:09
• Similar question: codegolf.stackexchange.com/questions/4486/… Apr 18, 2013 at 8:26
• @Walkerneo, thanks! I searched for similar questions and didn't find that one. I think this is significantly different, though. In particular, that question guarantees that only modifications resulting in syntactically valid code have to be handled.
– user7486
Apr 18, 2013 at 8:33
• The Perl test script should be subject to the same 1-character deletion Jul 3, 2017 at 8:45

## Befunge, Score 0, 96 bytes

I think I cracked it - no single character deletion will change the output.
Deleting any character from line 1 changes nothing - it still goes down at the same place.
Lines 2 and 3 are redundant. Normally line 2 is executed, but if you delete a character from it, the < is missed, and line 3 takes charge.
Deleting newlines doesn't break it either (it did break my previous version).
No test program, sorry.

EDIT: simplified a lot.

                              vv
@,,,,,,,,,,,,,"Hello, world!"<<
@,,,,,,,,,,,,,"Hello, world!"<<


A short explanation of the flow:

1. Befunge starts executing from top-left, moving right. Spaces do nothing.
2. v turns the execution flow downward, so it goes down one line.
3. < turns the execution flow left, so it reads line 2 in reversed order.
4. "Hello, world!" pushes the string to the stack. It's pushed in reversed order, because we're executing right to left.
5. , pops a character and prints it. The last character pushed is printed first, which reverses the string once more.
6. @ terminates the program.
• +1, great solution. I don't think a test program is needed, because it is obvious that there is only a small number of potentially significant deletions.
– user7486
Apr 18, 2013 at 12:14
• So easy to verify and no discussion involved. Genius! Apr 19, 2013 at 22:51
• Congratulations on an excellent solution.
– user7486
Apr 29, 2013 at 7:39
• I know this isn't code-golf, but here's a version in 66 bytes. Feb 28, 2018 at 0:26

# Perl, Score 0

(147 characters)

Here is my solution, which I managed to get from 4 down to 0:

eval +qq(;$_="Hello, world!";;*a=print()if length==13or!m/./#)|| +eval +qq(;$_="Hello, world!";;print()if*a!~/1/||!m/./#)##)||
print"Hello, world!"


It must appear all on one line to work; line breaks are for "readability" only.

It benefits from Perl's pathologically permissive syntax. Some highlights:

• Barewords that are not recognized are treated as strings. So when eval becomes evl, that is not an error if a string is permissible at that point.
• Unary + operator, which does nothing other than disambiguate syntax in certain situations. This is useful with the above, because function +argument (where + is unary) becomes string + argument (addition) when a function name is mangled and becomes a string.
• Many ways to declare strings: a double quoted string qq( ) can become a single-quoted string q(); a string delimited by parentheses qq(; ... ) can become a string delimited by a semicolon qq; ... ;. # inside strings can eliminate balancing issues by converting things to comments.

The length of this can probably be reduced somewhat, though I doubt ugoren's solution can be beaten.

• +1 for line breaks are for readability only ... Apr 24, 2013 at 14:47

# HQ9+

This will never fail to produce the intended result when a character is deleted so gets a score of zero.

HH


When do I start?

• It produces "hello, world" though, not "Hello, world!" as specified. Apr 17, 2013 at 21:17
• Nonsense, the language was just incorrectly specified on the esolang wiki ;) Apr 17, 2013 at 21:20
• Good for you if they have an HQ9+ compiler on the interview computer... :)
– user7486
Apr 18, 2013 at 4:41
• You could write your own buggy compiler. Feb 19, 2014 at 20:50
• @mbomb007 This interpreter prints Hello, world! for the H command. Dec 14, 2016 at 1:28

## Befunge-98, score 0, 45 bytes

20020xx""!!ddllrrooww  ,,oolllleeHH""cckk,,@@


Try it online!

Although an optimal solution has already been found (and there's no tie breaker), I thought I'd show that this can be simplified considerably with Befunge 98.

### Explanation

The 20020xx reliably sets the delta (the steps of the instruction pointer between ticks) to (2,0) so that starting at the first x, only every other command is executed. See this answer for a detailed explanation of why this works. Afterwards, the code is merely:

"!dlrow ,olleH"ck,@


We first push all the relevant character codes onto the stack with "!dlrow ,olleH". Then ck, means print the top of the stack (,), 13 (c plus 1) times (k). @ terminates the program.

## J, 7 points

Selecting every letter with odd position:

   _2{.\'HHeellllo,,  wwoorrlldd!!'
Hello, world!

• The same thing in golfscript would be 4 points: 'HHeelllloo,, wwoorrlldd!!'2% Apr 18, 2013 at 0:07
• @cardboard_box Feel free to submit it. :) Apr 18, 2013 at 10:04
• Upvoting because I understand it, and it doesn't feel like cheating. Apr 17, 2014 at 16:43

# Unary, score 0, 74817134662624094502265949627214372599829 bytes

The code is not included due to post length limitations, but it consists of 74817134662624094502265949627214372599829 zeros.

If any of these zeros is removed, the resulting brainfuck program is KSab's hello world program.

Sadly, I didn't get the job because my machine had only 500 GB of hard disk space.

# Klein 0X1, score 0, 38 bytes

Works in both 011 (real projective plane) and 001 (Klein bottle)

//
@"!dlrow ,olleH"<
@"!dlrow ,olleH"<


Try it online!

This reflects the ip over the top of the program. The geometry causes the ip to reenter the program on the opposite end of the program. This makes it a lot shorter than the traditional method which requires a full length line to reach the right side of the program.

# 000, score 0, 38 bytes

<<@"!dlrow ,olleH"/
<@"!dlrow ,olleH"/


Try it online!

# 1X1 or 20X, score 0, 39 bytes

Works in 101, 111, 200, and 201

..

@"!dlrow ,olleH"<
@"!dlrow ,olleH"<


Try it online!

Due to the longstanding bug that spaces are trimmed off the front of Klein programs two .s are needed to make this work. If it were not for this bug the 37 byte program:



@"!dlrow ,olleH"<
@"!dlrow ,olleH"<


world work in all of these geometries.

The idea here is that we choose a geometry that naturally reaches the location we want and clear its way. Particularly we want geometries that connect the east edge to either the north or south edges with the proper twisting so that the ip leaving the east edge enters on the right side of the program. There are 4 of these.

# 0X0, score 0, 40 bytes

Works in both 000 (torus) and 010 (Klein bottle)

||@"!dlrow ,olleH"./
..@"!dlrow ,olleH"/


Try it online!

# 1X1, 20X, 210, or 101, score 0, 43 bytes

Works in 101, 111, 200, 201, 210, and 101

..

@"!dlrow ,olleH"<
@"!dlrow ,olleH"<


Try it online!

A modified version of the above where we move the @s out of the path so that 210 and 101 work. Once again .. is required due to a bug and could be removed for a 2 byte save if the bug were fixed.

# XXX, score 0, 54 bytes

Works in every geometry

.               \\
@"!dlrow ,olleH"<
@"!dlrow ,olleH"<


Try it online!

# Lost, Score 0, 122 bytes

>>>>>>>>>>>>>%%/>>>>>>>>>>/
\\
>>>>>>>>>>>>>//>>>>>>>>>>>\\
//
/@+-(  "vUvdlrow ,olleH"?<<
///
/@+-("vUvdlrow ,olleH"? <<<


Try it online!

It never stops amazing me that are possible in Lost.

If you haven't seen Lost before it is a 2-D programming language in which instead of starting execution at a fixed location it chooses a random location and direction and starts there. This makes writing any lost program a bit of a radiation hardening challenge normally, since a program must work from every start location. But now we layer on too and every program must work from every start location. With 122 bytes, four directions and a 28 by 6 bounding box, this means there are approximately 80,000 different programs that must be work.

This program is built with a mix of standard lost methods and standard radiation hardening methods. To start here is the normal Hello World for lost:

v<<<<<<<<<<>>>>>>>>>>>
>%?"Hello, worldvU"-+@


It is comprised of a "collector" which gathers all the stray instruction pointers and points them to the beginning of the actual program.

v<<<<<<<<<<>>>>>>>>>>>
>               v


A more detailed explanation of how this program works can be found here.

Now we want to modify this program to use the duplicate alignment method of radiation hardening. This method works by having two copies of the desired code and entering them from the end of the line.

>>>>>>>>>vv
program <
program <


This way when on of the programs is edited it becomes misaligned and the other one is executed

>>>>>>>>>vv
progam <
program <


To do this with our lost program is pretty simple:

>>>>>>>>>>>>>>>>>>>>>\\
@+-"Uvdlrow ,olleH"?%<
@+-"Uvdlrow ,olleH"?%<


However there are some problems with this. The alignment of the "s is an issue because it causes infinite loops (in the example above there are basically two strings ">" lain out vertically, so if you start on the quotes going in the right direction you just push the > character endlessly). So you need to make sure the quotes don't line up even when a character has been deleted.

>>>>>>>>>>>>>>>>>>>>>>>\\
@+-  "Uvdlrow ,olleH"?%<
@+-"Uvdlrow ,olleH"?%  <


Also since v is needed to escape the inside of the string it's deletion is potentially a problem. So we need a backup.

>>>>>>>>>>>>>>>>>>>>>>>>>\\
@+-(  "vUvdlrow ,olleH"?%<
@+-("vUvdlrow ,olleH"?%  <


Now while alignment prevents most pointers from entering the wrong program, if we delete a non-critical character from a program, e.g.

>>>>>>>>>>>>>>>>>>>>>>>>>\\
@+-(  "vUvdlrow ,olle"?%<
@+-("vUvdlrow ,olleH"?%  <


Then if execution starts on the % it doesn't need to care about the alignment at all and it will just execute the bad program. So we need to move % before the alignment

>>>>>>>>>>>>>>>>>>>>>>%%\\
@+-(  "vUvdlrow ,olleH"?<
@+-("vUvdlrow ,olleH"?  <


Now another line of collector is needed to fill the gap we made by adding non-redirecting characters to our collector (%s).

>>>>>>>>>>>>>>%%/>>>>>>>/
>>>>>>>>>>>>>>//>>>>>>>>\\
@+-(  "vUvdlrow ,olleH"?<
@+-("vUvdlrow ,olleH"?  <


(Some small changes are glossed over here mainly just edge casey nonsense)

Now we have to worry about what happens when a newline is deleted. This would normally be ok because the alignment doubling strategy works for these, however for us it opens the door to a lot of potential infinite loops for example in the program:

>>>>>>>>>>>>>>%%/>>>>>>>/
>>>>>>>>>>>>>>//>>>>>>>>\\@+-(  "vUvdlrow ,olleH"?<
@+-("vUvdlrow ,olleH"?  <


we now have a bunch of columns with no redirecting characters on them, so pointers starting there can just loop up or down endlessly.

The trick we use here is to add (nearly) blank lines so that deleting a newline doesn't smash two big lines together.

>>>>>>>>>>>>>>%%/>>>>>>>/

>>>>>>>>>>>>>>//>>>>>>>>\\

@+-(  "vUvdlrow ,olleH"?<

@+-("vUvdlrow ,olleH"?  <


So if we delete a newline:

>>>>>>>>>>>>>>%%/>>>>>>>/

>>>>>>>>>>>>>>//>>>>>>>>\\
@+-(  "vUvdlrow ,olleH"?<

@+-("vUvdlrow ,olleH"?  <


Nothing fundamentally changed about our program. However these lines can't be completely blank as it leaves the door open for infinite loops. In fact they need to have at least two (because one could be deleted) redirecting characters.

>>>>>>>>>>>>>>%%/>>>>>>>/
//
>>>>>>>>>>>>>>//>>>>>>>>\\
//
@+-(  "vUvdlrow ,olleH"?<
//
@+-("vUvdlrow ,olleH"?  <


Now if we delete the last newline our quotes align again:

>>>>>>>>>>>>>>%%/>>>>>>>/
//
>>>>>>>>>>>>>>//>>>>>>>>\\
//
@+-(  "vUvdlrow ,olleH"?<
//@+-("vUvdlrow ,olleH"?  <


Which is no good so we use 3 characters on the 3rd filler line:

>>>>>>>>>>>>>>%%/>>>>>>>/
//
>>>>>>>>>>>>>>//>>>>>>>>\\
//
@+-(  "vUvdlrow ,olleH"?<
///
@+-("vUvdlrow ,olleH"?  <


From here we arrive at the final program with just some minor fiddling. Iteratively fixing and finding mistakes. I've covered everything I think is interesting, but if you are interested in exactly why this or that just leave a commend and I will add it to the explanation.

# Python 3, score = 6 4, 454 426 bytes

xec=eec=exc=exe=exeexec=rint=pint=prnt=prit=prin=ppprint=hhh=hh=hhh=fr=""""pp(fr[1::2]) rrr________:__"ii______p____;nn____p______ptt__(________p(( __________(ff__________rfrr________[__r[[______1____[11____:______1::__:________:22 __________:66__________-2::________4__]22______]____)]]____)______ ))"""##"""
xec=eec=exc=exe=exec
pp=print
fr=fr=fr=""""HHeelllloo,,  wwoorrlldd!!"""##"""

exec(hhh[1::2++2++2++2++2++2++2++00])


Try it online!

The undeletable char are parenthesis for the exec function and the brackets.

## How it works:

• hhh=hh=hhh=fr=... initialize the main code and stor it in hhh

• xec=...=ppprint=... initialize all possibe deletion of exec and print to avoid a future NameError

• xec=eec=exc=exe=exec ensure that exec (with possible deletions) is well defined

• fr=fr=fr=""""HHeelllloo,, wwoorrlldd!!"""##""" store in fr the string Hello, world! but doubled to keep the information even with a deletion

• the last slice can be equal to either [1::14], [::14], [1:14] or [1::12]. Both of them slice the main code to have respectively print(fr[1:26:2]), "r";pp(fr[1::2]) , pp(fr[1::2])  or p :pp( fr[1:: 6-4])

Thanks to @Jo King♦ for pointing me my errors, helping me to solve them and helped me to golf the result

• 457 bytes
– Jo King
Aug 5, 2021 at 3:39
• @JoKing Thanks a lot. I even gained 3 bytes by using fr instead of rr as variable name Aug 12, 2021 at 18:13

# 8086 machine code (MS-DOS .COM), 71 bytes, score = 0

Slight variation on previous answers on the same theme.

In binary form:

00000000 : EB 28 28 E8 00 00 5A 83 C2 09 B4 09 CD 21 C3 48 : .((...Z......!.H
00000010 : 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 24 90 90 90 : ello, World!$... 00000020 : 90 90 90 90 90 90 90 90 90 90 EB D7 D7 E8 00 00 : ................ 00000030 : 5A 83 C2 09 B4 09 CD 21 C3 48 65 6C 6C 6F 2C 20 : Z......!.Hello, 00000040 : 57 6F 72 6C 64 21 24 : World!$


cpu 8086
org 0x100

%macro CODEPART 0
call near .nextline
.nextline:
pop dx
mov ah, 0x09
int 0x21
ret

# !@#$%^&*()_+, score 2, 242 bytes !!!!!!!!!!!!!! ^!!!!!!!!!!!!!ddddddddddddddllllllllllllllrrrrrrrrrrrrrrooooooooooooooWWWWWWWWWWWWWW ,,,,,,,,,,,,,,oooooooooooooolllllllllllllllllllllllllllleeeeeeeeeeeeeeHHHHHHHHHHHHHH(((@%%%%%%%%%%%%%%))üü&& ^dlroW ,olleH((@)  Try it online! Well, I give up. I'm on a mobile phone, so I cannot put the null character there. If someone would be so kind to replace the !!_+ in the TIO link, I would appreciate it. The two weaknesses are the  ^ between the exclamation marks. This is not particularly clever, and most of the characters are just padding. Contains two Unicode characters; the challenge specifications said remove one character, not one byte. The HW is repeated 14 times to be immune to % removal or removal in the HW string. !@#$%^&*()_+ allow unmatched ( but not unmatched ) when parsing, so the left parenthesis is repeated one more time than the right parenthesis.

What if the @ was removed? We can know from the stack size if 13 characters went missing, so we use stack indexing to exit by error if the stack size is too short. Each character is doubled to make sure the test is performed. If the test passed, it means the @ is the removed character, and none of the characters after the test was removed, so you can put a normal Hello, World program there.

I made this one bored afternoon at school with a pencil, but I did not have time to debug and post this until now. Bugs might still be present.

# R -e 'options(error=function(){})', 204137 130 bytes, score 0

(or any other R environment in which errors do not halt execution of subsequent commands: entering the program into the R interactive console (or Rstudio) works fine; in batch mode or TIO we can set the global enviroment option error to an empty function; or in Rscript we can set this using the command-line option -e 'options(error=function(){})').

a="Hello, world!"##"
b="Hello, world!"##"
T=cat(ifelse(exists("a"),ifelse(exists("b"),ifelse(nchar(a)==13,a,b),a),b));
if(T)cat(a)


Try it online!

Explanation:

Lines 1 & 2: At least one of a or b should contain the text "Hello, world!" even if any character is deleted:

• any deletion inside one quoted string shouldn't affect the other;
• deletion of any of a=" will simply error without assigning a (or the same for b);
• deletion of the second " will assign "Hello, world!##" to that string without affecting the other;
• deletion of any of ##" has no effect;
• deletion of the first newline will convert the following line into a comment and prevent assignment of b, without affecting a;
• deletion of the second newline will convert the following line into a comment, without affecting either a or b (see line 3 below).

Line 3: Aims to output one of a or b that exists and is the correct, 13-character "Hello, world!" string, or to error.
If it succeeds without erroring, the variable T is re-assigned to NULL (instead of its default value of TRUE).

• deletion of any of T=, cat(), ifelse(,,b), exists("a"), or nchar(a)== will error and fail to re-assign T.
• deletion of any of 13 will select b instead of a to output; however, since this was the single deletion made, b is intact so this is Ok.
• deletion of either ; or the third newline has no effect;
• if the entire line is commented-out (by deletion of the second newline), it will not re-assign T.

Line 4: If T is non-zero, then either an error has occurred (so the deletion was on line 3), or the second newline was deleted (so line 3 was commented-out).
In either case a should be the correct "Hello, world!" string, and nothing has yet been output, so we can safely output a.
Any deletion to this line should cause an error so that it doesn't output anything to stdout.

• deletion of any of if(T) will error;
• if T is NULL (so no error has yet occurred, and line 3 ran Ok), if(T) will error and this line will not output anything.
• if T is still TRUE`, then the single deletion already happened on another line, so we shouldn't need to worry about further deletions on this line.