Your goal: to write a piece of code that will result in the classic result of "Hello, world!" being printed to STDOUT or equivalent.

Rules: Code must be entirely in printing ASCII. All code must be functional - removal of any single counting character must change the result or cause the code to not function. All variables must be used after assignment. Character and String literals must be necessary to the output - that is, replacement of any character literal or any character within a string literal with another character must be capable of changing the result (and not via the effect of escape sequence - replacing character with backslash or equivalent)

(NOTE: Final rule was edited in)

Scoring: This is where it gets interesting. Highest score wins as determined by number of characters, as per typical code-bowling rules. But repeated use of characters will result in point deductions. Specifically...

  1. Repeated use of any alphanumeric character (a-z, A-Z, 0-9) will result in a deduction of 3 points per repeat (first use does not result in a deduction).
  2. Repeated use of basic punctuation ([!?.-,":';]) - including the brackets - will result in a deduction of 2 points per repeat.
  3. Repeated use of other ASCII characters {`~@#$%^&*_+=|\/><} - including the curly brackets - will result in a deduction of 4 points per repeat.
  4. Repeated use of spaces, tabs, and newlines will result in a deduction of 1 point per repeat. That is, only the first use of a space, tab, or newline will count towards your total.

Note: comments do not count towards total, although the characters marking the start/end of a comment do. For instance, in C/C++, If you have /* This is a comment */, then it will count two slashes and two asterisks, but nothing between them.

Some examples (note: using Julia as sample language)...

print("Hello, world!");

Total visible characters: 22
Contains Space: +1
Repeated alphanumerics: -12 for llor
Repeated punctuation: -2 for "
Final score: 22+1-12-2 = 9

print("Hel",char(108),"o, wor",0x108,"d!"); # 0x108 makes a Uint8 that prints as ASCII

Total characters: 43 (does not count any characters after #, which is the comment character)
Contains Space: +1
Repeated alphanumerics: -18 for rr1008
Repeated punctuation: -24 for ()""""",,,,,
Final score: 43+1-24-18 = 2

m="Hello, world!"

Total visible characters: 37
Contains Newline: +1
Contains Space: +1
Repeated alphanumerics: -18 for xyllor
Repeated punctuation: -4 for ",
Repeated other ASCII: -4 for =
Final score: 37+1+1-18-4-4 = 13

A couple of invalid pieces of code...


Problem: x is assigned, but not used.

print("Hello,"*" world!")  

Problem: * is unnecessary, result will be the same without it.

if k>0
  print("Hello, world!")

Problem: The second print command will not run. Also, removing characters in quote in second print command will not change output.

x="Hello, world!";

Problem: removal of newline will not change result or cause error (in Julia, semicolon is only necessary if multiple commands are on the same line, otherwise just suppresses return value).

print("Hellos\b, world!")  

Problem: s character does not affect result, as it gets erased by \b. This is acceptable if done through code ("Hello",char(100),"\b, world!"), but cannot be done via string literals or character literals.

Convenient score-calculator - http://jsfiddle.net/4t7qG/2/ - thanks to Doorknob

  • 1
    \$\begingroup\$ Seems awfully close to codegolf.stackexchange.com/questions/19477/… and codegolf.stackexchange.com/questions/18721/… \$\endgroup\$
    – Kyle Kanos
    Commented Jun 4, 2014 at 17:08
  • 1
    \$\begingroup\$ This seems relevant to your discussion meta.codegolf.stackexchange.com/questions/777/… \$\endgroup\$ Commented Jun 4, 2014 at 17:28
  • 3
    \$\begingroup\$ I created a JSFiddle where you can put your code and it will automatically figure out your score. Would you be okay with me editing a link to it it in to the post? \$\endgroup\$
    – Doorknob
    Commented Jun 4, 2014 at 18:44
  • 1
    \$\begingroup\$ @Dennis - if your program produces a newline because of the command, no problem (for instance, println in Julia prints and then adds a newline on the end). But it shouldn't be part of the string. \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 3:41
  • 1
    \$\begingroup\$ @ACarter - basically, yes. But the restrictions and the deductions make it non-trivial. \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 11:56

12 Answers 12


Perl - 96

(Pretty good, given the theoretical max 97 score)

s{}[Hel0o, w3$=d!];y<"#%&'*.124578:?@BCDEFGIJKLMNOQ/-9>(

(Note that second line starts with an actual \t tab character)

The code is 98 characters long and contains every ascii char exactly once, plus an extra -.
98 - 2 = 96

There are no string literals here, but removal of any single character breaks the program.


There are 3 statements in this program (well, actually 2 but I abused + as some kind of statement separator)

  1. s{}[Hel0o, w3$=d!]
    This is a very stretched case of the sed operator. It is more commonly written as s/a/b/, or s:a:b:, but perl allows much more fantasy here: s(a)(b) s(a)^b^ s(a)[b], and even s qaqbq.
    It replaces an empty string (inside {}) with Hel0o w360d! (inside []) ($= interpolates to 60 by default). Because of the lack of an ~= operator, it operates on $_.

  2. y<"#%&'*.124578:?@BCDEFGIJKLMNOQ/-9>(\n\t6PRSTUVWXYZ^_`abfghjmqvxz|~\cAk-u)
    This is also a very stretched case, but of a tr operator, which is also called y (y< >( )).
    Let's look at the replacement table:
    " # %&'*.124578:?@BCDEFGIJKLMNOQ /-9
    \n\t6PRSTUVWXYZ^_`abfghjmqvxz|~\cA k-u
    I have moved some characters around so that existing string is not broken. The only actually working part here is /-9 -> k-u. It replaces 0 with l, 3 with o, and 6 with r.
    Again because of lack of the ~= operator, it operates on $_
    So now we have the complete phrase in the $_ variable.

  3. print
    Lack of arguments makes it print just the $_ variable.

  • \$\begingroup\$ I don't know Perl enough to comment on this - what is the set of characters between the < and + doing? \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 3:42
  • \$\begingroup\$ @GlenO Only /-9 and k-u are actually used to transform the string. The rest is an equally sized garbage. If you remove just one char, the sets will misalign and the program won't output "Hello, world!" anymore. \$\endgroup\$
    – mniip
    Commented Jun 5, 2014 at 4:26
  • \$\begingroup\$ In that case, in what way is the "garbage" being executed? That is, in what way is it functional? If it's just filler that gets jumped over by the code, then it's equivalent to non-running code within a conditional. \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 4:32
  • 3
    \$\begingroup\$ @GlenO It's not. To the spec: <...> removal of any single counting character must change the result or cause the code to not function. Removal of 1 character anywhere breaks it. You can make it work by removing 2 characters, but that's not in the rules. \$\endgroup\$
    – mniip
    Commented Jun 5, 2014 at 4:43
  • 2
    \$\begingroup\$ All code must be functional. You're clearly bending the rules, at the very least. I'm not saying "it breaks the rules" outright, but it's definitely questionable. \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 5:19

This answer was created before adding of the rule about string literals and does not participate in the contest.

#include <iostream>
int main(){std::cout<<56+"  !$%^&*?12347890-_QWERTYUIOPASDFGJKLZXVBNM,.qypfghjk:zvbHel\x6Co, world!";}

It's completely legit. :P If you remove any character from that string, it will print ello, world!.

  • \$\begingroup\$ Please include the score of your code in your answer. \$\endgroup\$
    – ProgramFOX
    Commented Jun 4, 2014 at 17:24
  • \$\begingroup\$ Also it won't change your score, but the the spaces around << need to be removed. \$\endgroup\$ Commented Jun 4, 2014 at 17:30
  • 1
    \$\begingroup\$ Hmmm... while I do applaud your answer, it has primarily revealed a minor hole in my restrictions. I'm going to give you an upvote, and I'm happy for others to do the same if they like it, but I'll be editing in an additional restriction. \$\endgroup\$
    – Glen O
    Commented Jun 4, 2014 at 17:30
  • 1
    \$\begingroup\$ OK, further to my previous comment, I've now added a restriction stating that string and character literals must be relevant - replacement of characters within them must be able to change the result. This allows if 'x'>'w' techniques, but blocks "k\bH" to result in "H", for instance. Feel free to contribute a second answer following the added restriction. \$\endgroup\$
    – Glen O
    Commented Jun 4, 2014 at 17:39

CJam, 94

{'H"EJO, WoRLD!"el96A+c/~_-3=0$@}"# 

Try it online! Note that there should be a tabulator right before the linefeed. SE doesn't like tabulators, so you'll have to insert it manually.

  • 100 characters long
  • repeated alnum: -0 ()
  • repeated punctuation: -6 (""")
  • repeated other: -0 ()
  • repeated whitespace: -0 ()

Total score: 94

I've used the following code to check that none of the characters inside the string can be removed:


It prints an array showing the number of times Hello, world! would get printed if the character corresponding to the index were removed.

  • \$\begingroup\$ When I run it in your link, it produces "Hello, world!" six times in a row. Also, what is the string of characters doing? \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 3:54
  • \$\begingroup\$ I'm guessing the newline is the mistake - removing it makes it work. \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 4:03
  • \$\begingroup\$ Copy-paste issue. There should be a tabulator right before the LF. It looks like SE won't let me do that... The string is considered a base-254 number (254b). The final result modulus 7 should be 1, so the previous code block is executed once. I'll need a modulus to make each character necessary. \$\endgroup\$
    – Dennis
    Commented Jun 5, 2014 at 4:04
  • \$\begingroup\$ Well, after adding in the missing tab (which does "fix" the code), removing the Z, the T, or probably a few other characters doesn't change the result. \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 4:09
  • \$\begingroup\$ I had horribly misinterpreted a part of your question. It's fixed now. \$\endgroup\$
    – Dennis
    Commented Jun 5, 2014 at 4:30

Befunge-98, 97 points!

"v!dlrow ,h
$<QRSTUV@|5cg1fe':-%\64*ab+7_/89}{0  j2
s()impq	n 3~
Atuxz&;y^ ?

Try it online!

The tab is between the q and the n.

Uses a similar trick to the previous Befunge answer to pad the lines with the leftover characters, but avoids using duplicate characters in the executing section. Removing any of the non-executing characters results in the executing parts being out of place, usually ending up in infinite loops or printing the wrong output.

How It Works

Really, the only executing part looks like:

"v!dlrow ,h
         k     H
$<      @|5cg1fe':-%\64*ab+7
        ^ ?

First it uses a wrapping string literal to add , world! to the stack. This avoids two "s.

$<      @|5cg1fe':-%\64*ab+7

This adds Hello to the stack using a variety of methods to avoid duplicate characters. $ pops the excess space caused by the wrapping string literal.

7+ adds 7 to the h from the end of the string literal to create the o . ba*46\%: calculates 111, the ascii value of l and duplicates it.

'e adds e to the stack.

f1g gets the character at 1,15 which is the H

It then reuses the , in the string to print out the whole Hello, world!. The rest is just direction changes to navigate to the ending @.


Ruby, 28 41

Just to start off the answers with a solution in the spirit of the question:

print"He#{?l*2}o, "+'world!'if[$`&(9<=>6)^7|~8-5/3.1%0x4]

Scoring (I think I got this right):

  • 57 characters long
  • repeated alnum: -12 (orli)
  • repeated punctuation: -4 ("')
  • repeated other: -0
  • repeated whitespace: -0
  • \$\begingroup\$ Looks fine to me, scoring-wise. No need to include penalties that don't apply, but no harm in including them. \$\endgroup\$
    – Glen O
    Commented Jun 4, 2014 at 18:11
  • \$\begingroup\$ The . in 3.1 can be removed without issue. As can the x in 0x4 or the - in 8-5. \$\endgroup\$
    – user12166
    Commented Jun 4, 2014 at 22:17

PHP, 1 (yes, one point!)

Using magic characters to generate a checksum, which in binary form matches "Hell", "o, w", "orld", and "! ".

Usually I like to find loopholes, but this time I decided to play by the spirit and intent of the contest. Every character and its position is essential to the output. The only places you can substitute are variable names which are not literal values, the whitespace between php and foreach which PHP treats as equivalent, and use of ' vs " which PHP treats as similar.

<?php foreach(array('_MC:`~+V4@SbHR/l[J','dN#UB`5!Rv^NG@D}','9gm6L&-kuD','8OM97g.q]XQ0')as$j)print(hash("crc32",$j,1))?>

FYI, these are some other magic strings and hashes of interest:

E.D}S:  Hell
9UDIRQ: Hell
N\7&*`%:    orld
UWX[E^O:    orld
mAHzDEb:    !   
uLJ7Ck&:    Hell
B+bG5mYJ:   Hell
:OvMzuOR:   !   
TgYR9g!6k:  o, w
NkFN`!8mI:  o, w
N#VA\j~}J[: Hell
vEl*]@0XQ5: o, w
9gm6L&-kuD: orld
*}{Xg@HN`\: !   
Pj@Y44uA6YJ:    Hell
|7OX0VF8gv}:    !   
DLRJAjgMj}\:    !   
!0bT*D}O4Lw:    orld
YGN97^v7ZY`:    Hell
++~bL/kP:|]W:   o, w
8OM97g.q]XQ0:   !   
l^m-DqZ^g[&+:   !   
Ewu]Rv~*DHQ7:   Hell
JIqjgF|S!\`8l:  Hell
b4l!MEG7vTu6/:  Hell
+B:zEq*J\k-Cm:  !   
_}E7wZD76^`Y9AU:    orld
q:Nq-~+_S7~N9Hz:    !   
  • \$\begingroup\$ The code still functions if I remove the \t, \n, or the space. Not a PHP expert, but ; seems optional as well. \$\endgroup\$
    – mniip
    Commented Jun 5, 2014 at 14:18
  • \$\begingroup\$ @mniip - Edits made. I was not aware the semicolon was optional in some cases. \$\endgroup\$
    – user15259
    Commented Jun 5, 2014 at 14:37

Ruby, 78

More rules abuse, I feel like, not sure exactly what the patch'd be. Takes a long string and checks the sum of the result, so any deletion or change will cause the program to fail. Could probably be optimized a little to remove duplication of some letters and get whitespace in there.

puts('Hello, world!')if%["\#$&*+-/:;<>?@ABCDEFGIJKLMNOPQRSTUVWXYZ^_`abcghjknqvxyz{|}~123].sum==4980
  • 3
    \$\begingroup\$ The problem is, everything after and including the if can be removed. \$\endgroup\$
    – seequ
    Commented Jun 4, 2014 at 20:58
  • \$\begingroup\$ @TheRare - nothing wrong with that, so long as the if does actually function and the stuff after it still obeys the rules. \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 11:58
  • \$\begingroup\$ @GlenO But isn't it counted as "removable code"? Just puts('Hello, world!') would work. I think the rules need clarifying if this is legit. \$\endgroup\$
    – seequ
    Commented Jun 5, 2014 at 12:53
  • \$\begingroup\$ @TheRare - in hindsight, I probably should have used a sweeping "a subset of the code should not be capable of producing the same output", but I don't think I should continue to change the rules. As they stand, as long as the code is functional and non-arbitrary, and follows the other rules, it's legitimate. At the very least, this method of solution isn't achievable in most languages (the edit I did make closed a loophole that works in most languages). \$\endgroup\$
    – Glen O
    Commented Jun 5, 2014 at 13:00
  • \$\begingroup\$ @GlenO You're the judge. Just ask me to delete these comments if you feel they're unnecessary. \$\endgroup\$
    – seequ
    Commented Jun 5, 2014 at 13:05

PHP, 2257

Loophole: the backslash was omitted from the specifications and the score calculator!

This code counts the number of occurrences of backslashes in each string and prints an ASCII equivalent. Replacing any backslash with another character, or deleting a backslash, either causes a parse error or changes the result.

A neat feature about backslashes and PHP is that they need to be escaped, so that doubles the score automatically! You can re-double, triple, etc., the score by multiplying the number of backslashes, but didn't want to be greedy, and I think it might exceed the limits of what you can enter.

<?php foreach(array('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\','\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\')as$x)print(chr(substr_count($x,"\\")))?>
  • \$\begingroup\$ It's clearly nothing more than a typo in the description, not a loophole. What's more, you knew that already. The description does explicitly say "other ASCII characters". By the time you read this, it'll have been edited to include it. \$\endgroup\$
    – Glen O
    Commented Jun 6, 2014 at 15:23
  • \$\begingroup\$ In particular, backslash was in the source of the question, but I hadn't realised that it had treated it as an escape sequence. \$\endgroup\$
    – Glen O
    Commented Jun 6, 2014 at 15:24
  • \$\begingroup\$ This isn't a change in rules, it's correcting a minor typo. The backslash was in the rules, it just wasn't displaying (to see this for yourself, click on the "edited" button, then click on "side-by-side markdown"). And the others aren't exploiting loopholes, they're exploiting features of their languages. \$\endgroup\$
    – Glen O
    Commented Jun 6, 2014 at 17:05

Befunge - 87

"dlrow ,olleH"bk,                                                                   v
!#$%&'()*+-./0123456789:;  <=>?ABCDEFGIJKLMNOPQRSTUVWXYZ[\]^_`acfghijmnpqstuvxyz{|}~@

The first line is worth four points due to all the repetition, but there are no duplicated characters on the second line. The only string literal in this code is dlrow ,olleH, which gets reversed and printed as output. Removing any one character will disconnect the v at the end of the first line from the @ at the end of the second, causing the program to never terminate. If the v itself is removed, then the code will go in to an infinite loop printing the correct output.


Aceto, 3

Finally managed to get a positive score!

"Hello, "-J' sJ"world!"∑-JUJpn

Try it online!

  • 1
    \$\begingroup\$ isn't in printing ASCII \$\endgroup\$
    – L3viathan
    Commented Feb 10, 2018 at 18:33

Acc!!, -138 (and yes that's negative 138)

While this may not exactly be the best score I've ever gotten in PPCG, I doubt it can get any higher than this in Acc!!

Write 72
Write 101
Count i while i-2 {
	Write _
Write _+3
Write 44
Write 32
Write 119
Write 111
Write 114
Write _
Write 100
Write 33

Try it online!


Pascal, 17

One of the few occasions on this site a verbose case-insensitive language is “useful”. This is a program adhering to ISO standard 7185 “Pascal”:

WRiTe('Hello, world!':1*82-75+6)EnD.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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