Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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

xy=STDOUT
m="Hello, world!"
print(xy,m);

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

x=2;print("Hello,world!")  

Problem: x is assigned, but not used.

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

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

k=1
if k>0
  print("Hello, world!")
else
  print("abcghjmquvxyzABCDEFGIJKLMNOPQRSTUVWXYZ_+*-&|")
end  

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

x="Hello, world!";
print(x)  

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

share|improve this question
1  
1  
This seems relevant to your discussion meta.codegolf.stackexchange.com/questions/777/… –  Martin Büttner Jun 4 at 17:28
3  
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? –  Doorknob Jun 4 at 18:44
1  
@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. –  Glen O Jun 5 at 3:41
1  
@ACarter - basically, yes. But the restrictions and the deductions make it non-trivial. –  Glen O Jun 5 at 11:56

7 Answers 7

up vote 10 down vote accepted

Perl - 96

(Pretty good, given the theoretical max 97 score)

s{}[Hel0o, w3$=d!];y<"#%&'*.124578:?@BCDEFGIJKLMNOQ/-9>(
    6PRSTUVWXYZ^_`abfghjmqvxz|~\cAk-u)+print

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

Deobfuscation

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.

share|improve this answer
    
I don't know Perl enough to comment on this - what is the set of characters between the < and + doing? –  Glen O Jun 5 at 3:42
    
@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. –  mniip Jun 5 at 4:26
    
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. –  Glen O Jun 5 at 4:32
2  
@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. –  mniip Jun 5 at 4:43
2  
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. –  Glen O Jun 5 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!.

share|improve this answer
    
Please include the score of your code in your answer. –  ProgramFOX Jun 4 at 17:24
    
Also it won't change your score, but the the spaces around << need to be removed. –  Martin Büttner Jun 4 at 17:30
1  
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. –  Glen O Jun 4 at 17:30
1  
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. –  Glen O Jun 4 at 17:39

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
share|improve this answer
    
Looks fine to me, scoring-wise. No need to include penalties that don't apply, but no harm in including them. –  Glen O Jun 4 at 18:11
    
The . in 3.1 can be removed without issue. As can the x in 0x4 or the - in 8-5. –  MichaelT Jun 4 at 22:17

CJam, 94

{'H"EJO, WoRLD!"el96A+c/~_-3=0$@}"# 
`&^<>|;:?.()[]\1aBCdfFgGhiIjkKmMnNpPqQrsStTuUvVwxXyYzZ"254b87%*

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:

"#  
`&^<>|;:?.()[]\1aBCdfFgGhiIjkKmMnNpPqQrsStTuUvVwxXyYzZ"
:A,,{_A\<A@)>+254b87%}%`

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

share|improve this answer
    
When I run it in your link, it produces "Hello, world!" six times in a row. Also, what is the string of characters doing? –  Glen O Jun 5 at 3:54
    
I'm guessing the newline is the mistake - removing it makes it work. –  Glen O Jun 5 at 4:03
    
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. –  sudo Jun 5 at 4:04
    
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. –  Glen O Jun 5 at 4:09
    
I had horribly misinterpreted a part of your question. It's fixed now. –  sudo Jun 5 at 4:30

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:    !   
share|improve this answer
    
The code still functions if I remove the \t, \n, or the space. Not a PHP expert, but ; seems optional as well. –  mniip Jun 5 at 14:18
    
@mniip - Edits made. I was not aware the semicolon was optional in some cases. –  Yimin Rong Jun 5 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
share|improve this answer
3  
The problem is, everything after and including the if can be removed. –  Sieg Jun 4 at 20:58
    
@TheRare - nothing wrong with that, so long as the if does actually function and the stuff after it still obeys the rules. –  Glen O Jun 5 at 11:58
    
@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. –  Sieg Jun 5 at 12:53
    
@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). –  Glen O Jun 5 at 13:00
    
@GlenO You're the judge. Just ask me to delete these comments if you feel they're unnecessary. –  Sieg Jun 5 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,"\\")))?>
share|improve this answer
    
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. –  Glen O Jun 6 at 15:23
    
In particular, backslash was in the source of the question, but I hadn't realised that it had treated it as an escape sequence. –  Glen O Jun 6 at 15:24
    
That's not fair, you wrote yesterday in a reply to TheRare you weren't going to continue to change the rules. If you're going to change the rules to prevent me from exploiting a loophole, you should change the rules for everyone earlier who is exploiting loopholes. –  Yimin Rong Jun 6 at 15:29
    
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. –  Glen O Jun 6 at 17:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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