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.

Write the shortest program that prints the entire lyrics of "Never Gonna Give You Up" by Rick Astley.

Rules:

  • Must output the lyrics exactly as they appear in the above pastebin. Here's the raw dump: http://pastebin.com/raw.php?i=wwvdjvEj
  • Cannot rely on any external resources - all lyrics must be generated by / embedded in code.
  • No use of existing compression algorithms (e.g. gzip / bzip2) unless you include the full algorithm in your code.
  • Use any language, shortest code wins.

Update, 1st June 2012:
For solutions containing non-ASCII text, the size of your solution will be counted in bytes, based on UTF-8 encoding. If you use codepoints that cannot be encoded in UTF-8, your solution will not be judged as valid.

Update, 7th June 2012:
Thank you all for your awesome solutions! I'll be accepting the shortest answer tomorrow afternoon. Right now, Ed H.'s 554-character solution is winning, so get cracking on some improvements if you want to beat him! :)

share|improve this question
3  
@w0lf You're correct. I only scanned the lyrics to verify their accuracy, I must've missed that one. I'll accept either "know" or "known". –  Polynomial May 29 '12 at 7:30
6  
26k+ views in just 3 days. WOW... –  Gaffi Jun 1 '12 at 21:30
3  
How in the world did this generate so many views and votes? Whatever he did, I'm going to reverse engineer it. –  PhiNotPi Jun 2 '12 at 21:27
12  
@PhiNotPi Good luck reverse engineering "Jeff Atwood tweeting you". –  breadbox Jun 3 '12 at 8:04
20  
+1 for mass rickrolling CodeGolf SE –  Optimus Jun 3 '12 at 21:43

53 Answers 53

up vote 42 down vote accepted
+100

Ruby 576 557 556 (552) chars && PHP 543 chars

Another search-and-replace solution. Note that this form of solution is essentially a Grammar-based Compression Code http://en.wikipedia.org/wiki/Grammar-based_code Check out http://www.cs.washington.edu/education/courses/csep590a/07au/lectures/lecture05small.pdf for a simple to understand compression example.

I've written the substitution rules so that the starting character for each substitution is computed (they are in sequential ASCII order); it need not be present in the transition data.

i=44
s="We; n7trangMsL8loT63Ke rules5s8d8I
AJull commit4nt'sChatFKink: of6CHldn'tRetKisJrom<ny@Ruy-/A= if?<sk 42DS'tLE 4?;Lo8bli=L7ee..
O,R1)O,R001)/-.."
"
I justCannaLE?2Gotta >u=Msta=.|
Ng1Nlet? downNrun<rH=5desMt?N>cryNsayRoodbyeNtE< lie5hurt?|

We'T3n each@Jor s8lSg6r hear9<ch: but6;Lo7hyL7BInsideCe both3Cha9Ro: S
We3KeRa45we;QplB|1)O)NgiT, nPgiT
(G|iT? up| howFJeel:
| know|me|<= |
YH|8s|o |t's been|ing|'re| a|nd|make? | yH| othM|A|ay it
| w|D|ell| I'm|G|ou|I| f|Lh| t|er|
NP|
(Ooh|eTrQ|RSna | g|on|ve".scan(/[^|]+/){s.gsub!((i+=1).chr,$&)}
puts s

implementation notes

  • The above solution is 556 chars long, but scores 552 with the removal of newlines from source code. It is slightly better scoring than the original 556 char solution I had that scored 554.
  • I use "known" instead of "know"; this makes the verse repetition identical and should make the compression better
  • I originally optimized the rules by repeatedly searching for the substitution that would yield the most decrease in current code size. However, I found that RiderOfGiraffe's substitution rules were (slightly) better than mine, so I'm now using a modified version of his rules.
  • I spent time reordering the rules so that a single substitution pass can decompress everything.
  • Due to the computed initial character in the substitution rules, my rule list has a rule for every character in a contiguous ASCII range. I found that having some "dummy" substitution rules was better for code size than having all real rules and coding a final text fixup substitution.
  • This example is small enough that you probably could successfully write a program to find the optimal (least total cost) set of rules. I would not expect doing this would yield size reductions of more than a few bytes.

older implementation

This older implementation has 576 characters and started with substitution rules from ugoren's bash/sed implementation. Ignoring the substitution variable renaming, my first 28 substitutions are exactly the same as those performed in ugoren's program. I added a few more to lower the overall byte count. This is possible because my rules are more efficiently represented than those in ugoren's implementation.

i=44
puts"WeM noHtraLersB loJ;6 C rules=so do $
& full commitment'sGhat<thinkDof;Gouldn'tKet this fromFny oCrKuy.
-&E if9ask me1~on't @ me:MBo bliEBHee//

3300-.//|
We'J6n each oCr forHo loL;r hear2FchDbut;MBoHhyBH7$nsideGe both6Gha2ADon
We6 CKame=weM>pl7|
$ justGanna @:1#otta 8uEerstaE/|
5?9up5let9down5runFrouE=desert:58cry5sayAodbye5@F lie=hurt:|(Ooh)5?, nI>?
(#4| how<feeliL
|t's been|(Ooh,K4|iJ9up)
|
NI>| know|ay it
|make9|: | you|
You| $'m |FE |Anna |giJ|tell|Ko| to|the|iL |nd| a| w| s|eJr|ve| g|ng|'re".split("|").inject{|m,o|m.gsub((i+=1).chr,o)}.tr('&~#$',"ADGI")

I did not try optimizing the substitution rules in this one.

contest notes

The search-and-replace decompression scheme works well for this contest because most languages have pre-built routines that can do this. With such a small amount of text to be generated, complex decompression schemes do not seem to be feasible winners.

I've used only ASCII text and also avoided using unprintable ASCII characters. With these restrictions, each character in your code can only represent up to a maximum of 6.6 bits of information; this is very different than to real compression techniques where you use all 8 bits. In some sense, it is not "fair" to compare to gzip/bzip2 code size because those algorithms will use all 8 bits. A fancier decompression algorithm may be possible if you can include traditionally unprintable ASCII in your strings AND each unprintable character is still written in your code as a single byte.

PHP Solution

<?=str_replace(range('-',T),split(q,"
I justCannaLE?2Gotta >u=Msta=.q
Ng1Nlet? downNrun<rH=5desMt?N>cryNsayRoodbyeNtE< lie5hurt?q

We'T3n each@Jor s8lSg6r hear9<ch: but6;Lo7hyL7BInsideCe both3Cha9Ro: S
We3KeRa45we;QplBq1)O)NgiT, nPgiT
(GqiT? upq howFJeel:
q knowqmeq<= q
YHq8sqo qt's beenqingq'req aqndqmake? q yHq othMqAqay it
q wqDqellq I'mqGqouqIq fqLhq tqerq
NPq
(OohqeTrQqRSna q gqonqve"),"We; n7trangMsL8loT63Ke rules5s8d8I
AJull commit4nt'sChatFKink: of6CHldn'tRetKisJrom<ny@Ruy-/A= if?<sk 42DS'tLE 4?;Lo8bli=L7ee..
O,R1)O,R001)/-..");

The above solution takes the PHP from "a sad dude" and combines it with my substitution rules. The PHP answer turns out to have the shortest decompression code. See http://ideone.com/XoW5t

share|improve this answer
    
My sed solution surely can't beat it. I'm working on something that hopefully has a chance - you have 75 bytes of overhead, maybe I'll cut it down (not in Ruby). –  ugoren Jun 3 '12 at 19:50
    
I find 555 bytes in your program (with no trailing newline). –  r.e.s. Jun 5 '12 at 1:03
1  
The OP's scoring method is to exclude newline separators in ascii source code, so it seems this should score 554. –  r.e.s. Jun 7 '12 at 12:35
    
Great solution! :) –  Polynomial Jun 8 '12 at 15:55
    
Looks like the shortest decompression code was in PHP. Here's a 543 byte solution (my rules, using code snippets from "a sad dude") ideone.com/XoW5t –  Ed H. Jun 9 '12 at 17:38

So instead of making the shortest possible code, I decided to try and make my code look as much like a song summary as possible. Thus 2015 characters. Fun with the preprocesser.

#define BEAT putchar('\n');
#define CH0RUS a
#define CHORUS a++;
#define CROON(x) printf("(%s)\n",x);
#define END }
#define ENDSONG return 0;}
#define NEVERGONNA(x) printf("Never gonna %s\n",x);
#define NEXTVERSE goto chorus;
#define REPEAT(x) for(int i=0; i<a; i++){
#define RICKROLL int a=0;int main(){
#define SING(x) puts(x);
#define VERSE if(0==a){goto verse1;}else if(1==a){goto verse2;}else{goto verse3;}
#define START goto verse1;
#include <stdio.h>

RICKROLL
  START
  chorus:
    REPEAT(CH0RUS)
    NEVERGONNA("give you up")
    NEVERGONNA("let you down")
    NEVERGONNA("run around and desert you")
    NEVERGONNA("make you cry")
    NEVERGONNA("say goodbye")
    NEVERGONNA("turn around and hurt you")
    BEAT
    END
    VERSE
  verse1:
    SING("We're no strangers to love")
    SING("You know the rules and so do I")
    SING("A full commitment's what I'm thinking of")
    SING("You wouldn't get this from any other guy")
    SING("I just wanna tell you how I'm feeling")
    SING("Gotta make you understand")
    BEAT
    CHORUS
    NEXTVERSE
  verse2:
    SING("We've known each other for so long")
    SING("Your heart's been aching but")
    SING("You're too shy to say it")
    SING("Inside we both know what's been going on")
    SING("We know the game and we're gonna play it")
    SING("And if you ask me how I'm feeling")
    SING("Don't tell me you're too blind to see")
    BEAT
    CHORUS
    NEXTVERSE
  verse3:
    CROON("Ooh, give you up")
    CROON("Ooh, give you up")
    CROON("Ooh")
    NEVERGONNA("give, never gonna give")
    CROON("Give you up")
    CROON("Ooh")
    NEVERGONNA("give, never gonna give")
    CROON("Give you up")
    BEAT
    SING("We've known each other for so long")
    SING("Your heart's been aching but")
    SING("You're too shy to say it")
    SING("Inside we both know what's been going on")
    SING("We know the game and we're gonna play it")
    SING("And if you ask me how I'm feeling")
    SING("Don't tell me you're too blind to see")
  ENDSONG
share|improve this answer
10  
I giggled at CROON. Good stuff. –  Polynomial May 30 '12 at 17:22
3  
-1 no no no. it is longer than bash / sed solution –  user4635 Jun 3 '12 at 23:36
20  
@RocketSurgeon It's much longer, but if you read the first sentence in the post it says "instead of making the shortest possible code". I won't accept this as an answer, but Code Golf is about having fun, so there's no problem with having the answer here. –  Polynomial Jun 5 '12 at 15:30
24  
That's why I used gotos –  walpen Jun 6 '12 at 21:07
19  
Came to answers expecting cryptic golfed programs. Was rickrolled instead. –  muntoo Jun 8 '12 at 1:23

Python, 285 characters

import md5,sha,random
C="\n ')(,ADGIONWYacbedgfihkjmlonpsrutwvy"
L,M,S=1870,"de6e9b659905649220cc3f5d93cb70ab","5bdae7294f4bb9badd8370a47271217ae553da42"
t=""
while md5.new(t).hexdigest() != M or sha.new(t).hexdigest() != S:
  t="".join([random.choice(C) for _ in xrange(L)])
print t,

Generates random 1870-char-long strings of the appropriate alphabet until the MD5 and SHA sums of the string match those of the lyrics to the Rick Astley song "Never Gonna Give You Up".

If unclear that this works, replace line #3 "L,M,S=..." with this one:

L,M,S=3,"e1faffb3e614e6c2fba74296962386b7","606ec6e9bd8a8ff2ad14e5fade3f264471e82251"

Run the program and see it output "AAA", since AAA is 3 chars long, has an MD5 sum of e1faffb3e614e6c2fba74296962386b7 and an SHA1 sum of 606ec6e9bd8a8ff2ad14e5fade3f264471e82251.

Rationale

Trade runtime for code size, since execution time limit is unspecified and success is defined strictly by correctness and code size.

Potential problems

  1. Execution time of non-deterministic solution likely exceeds Heat Death of the Universe.
  2. Problem specifies that code must be self-contained, it is assumed that importing standard hash functions (md5,sha) are acceptable. Inlining the code for these algorithims would clearly make the programs very large, though if necessary we could switch to some sort of custom hash function.

Potential improvements

  1. We can reduce the code size even further by omitting the MD5-related data and relying only on SHA; though it's unclear if this would always lead the correct answer.
  2. Speed up our program by including character counts so we're just shuffling permutations, like so:

Python, 410 chars (the long string-building literal can be condensed)

import array as a,sha,random
S,t="5bdae7294f4bb9badd8370a47271217ae553da42",a.array('c',
 "\n"*306+"e"*197+"o"*162+"n"*162+"a"*109+"r"*91+"u"*84+"g"*77+" "*73+
 "t"*69+"y"*66+"v"*57+"d"*49+"l"*43+"i"*39+"N"*38+"s"*36+"h"*34+"w"*26+"m"*20+"'"*19+"k"*17+"b"*15+"p"*12+"c"*11+"I"*9+"f"*9+")"*6+"("*6+"Y"*6+"WWWWW,,,,GGGGOOOOAAjjD")
while sha.new(t.tostring()).hexdigest() != S:
  random.shuffle(t)
print t.tostring(),

Alternatives

  1. install popular PHP web application and wait for file to be hacked and output file modified into lyrics by Rick Astley hacker fanboys
  2. import rickrolling as r; print r.lyrics
  3. integrate lyrics into next POSIX standard as const char * rckrll_txt_r(void)
  4. integrate lyric opcodes into next generation x86 instruction set expansion
  5. Set up voice-to-text software, call Rick Astley and have him sing into the phone. Sometimes the manual solutions are the best ones.
share|improve this answer
5  
We had the same idea. :) It'd probably be more efficient to use a LargeInt package to just COUNT until you hit a string with right number of characters, hashing to the right amount. In fact, with a good seed based on some number that's easily expressible, we could probably speed it up so it finishes before the universe dies of heat death! –  Matt Cruikshank Jun 1 '12 at 20:51
8  
As they teach you while programming: first make sure it runs correct, and only after that worry about performance ;-) @Matt: The "performance advice" sort of made me laugh. It was like telling a snail to keep its head low for better earodynamics :) –  Wouter van Nifterick Jun 1 '12 at 21:24
6  
PEP21: import rickrolling: this might be approved before actual Heat Death of the Universe ;-) –  dschulz Jun 2 '12 at 1:23
34  
The chance that this produces the correct output is vanishingly small: there are a vast number of other strings with the same hash, and you will almost certainly find one of them first. –  Geoffrey Irving Jun 2 '12 at 5:19
10  
The (pseudo) random number generator you are using is cyclic, so it's unlikely to ever produce the correct result. –  gnibbler Jun 6 '12 at 12:02

Bash / Sed, 705 650 588 582 chars

Logic:
The basic idea is simple replacement. Instead of writing, for example, Never gonna give you up\nNever gonna let you down, I write Xgive you up\nXlet you down and replace all X with Never gonna.
This is achieved by running sed with a set of rules, in the form s/X/Never gonna /g.
Replacements can be nested. For example, Never gonna is common, but so is gonna in other contexts. So I can use two rules: s/Y/ gonna/g and s/X/NeverY/g.
When adding rules, parts of the song texts are replaced by single characters, so it gets shorter. The rules become longer, but if the string replaced is long and frequent, it's worth it.
The next step is to remove repetition from the sed commands themselves. The sequence s/X/something/g is quite repetitive.
To make it shorter, I change sed commands to look like Xsomething. Then I use sed to convert this into a normal sed command. The code sed 's#.#s/&/#;s#$#/g;# does it.
The final result is a sed command, whose arguments are generated by another sed command, in back-quotes.
You can find a more detailed explanation in this link.

Code:

sed "`sed 's#.#s/&/#;s#$#/g#'<<Q
LMWe'veKn each o!r for-o longPr hearHzchJbutP're2o-hy2-@Insidexe bothKxhaHCJonMWeK ! game+we'reZpl@
TMI justxanna _UFGotta QuXerstaXR
RM~Squp~letqdown~runzrouX+desertU~Qcry~sayCodbye~_z lie+hurtU
E(Ooh)~S, neverZSM(GV
F how=feelingM
Ht's been
%(Ooh, gV
Vivequp)M
~MNeverZ
K know
@ay itM
Qmakeq
qU 
U you
PMYou
= I'm 
+zX 
ZCnna 
Sgive
_tell
C go
2 to
!the
Jing 
Xnd
z a
x w
- s
M\n`"<<_
We're no-trangers2 lovePK ! rules+so do I
A full commitment'sxhat=thinkJofPxouldn't get this fromzny o!r guyT
LAX ifqask meFDon't _ meU're2o bliX2-eeRRMM%%EELTRR

Notes:
The decompression engine is just 40 characters long. The other 543 are the translation table and compressed text. bzip2 compresses the song to 500 bytes (without the engine, of course), so there must be room for improvement (though I don't see how I'd add Huffman encoding or something like this cheap enough).
<<Q (or <<_) is used to read until a given character. But the end of script (or backquote expression) is good enough. This sometimes causes a warning.

Older and simpler solution, 666 chars:

sed "
s/L/ MWe'veKn each other for so longMYour heart's been aching butMYou're too shy to say itMInside we bothK what's been going onMWeK the game+we'reZplay itM/;
s/T/MI just wanna tellU how I'm feelingMGotta makeU understandR/;
s/R/M ~giveU up~letU down~run around+desertU~makeU cry~say goodbye~tell a lie+hurtU/g;
s/E/(Ooh)~give, neverZgiveM(GV/g;
s/V/iveU up)M/g;
s/U/ you/g;
s/+/ and /g;
s/K/ know/g;
s/~/MNeverZ/g;
s/Z/ gonna /g;
s/M/\n/g
"<<Q
We're no strangers to love
YouK the rules+so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guyT
LAnd ifU ask me how I'm feeling
Don't tell meU're too blind to seeRRM M(Ooh, gV(Ooh, gVEEL TRR
share|improve this answer
    
This is great, but your output contains an extra space character on the blank lines. That may be an issue with the cut-and-paste from the pastebin? Also, you should be able to save a byte by replacing the \0 with &. –  breadbox May 30 '12 at 16:11
    
This is both the shortest so far, and my favourite. I was wondering how long it'd be before someone came up with a sed solution :) –  Polynomial May 30 '12 at 17:21
    
@breadbox, Cut&paste indeed brought this space. I removed it, saved 4 chars. With your & it makes 5. –  ugoren May 31 '12 at 6:41
2  
@r.e.s., added a better explanation. –  ugoren Jun 3 '12 at 13:40
1  
Thanks, esp for the "more detailed explanation" link ;o)))) –  r.e.s. Jun 3 '12 at 13:46

JavaScript, 590 588 bytes

f="WeP nTstrangersZTloMX^Zhe rules[sTdTIqA fuFcommitment'sEhat I'mZhinkQofXEouldn'tJetZhis from anyRguy{Sn}AH ifCask me_Don'tZeFmexPZoTbliHZTsee~~qU,J`)U,Jzz`)S}{~~~q|g`|letCdown|run arouH[desertx|Lcry|sayJoodbye|teFa lie[hurtx} eachRfor sTlongXr hearVachQbutXPZoTshyZTsKInsideEe both^EhaVgoQonqWe^ZheJame[weP]plK|qNeMr]{qI justEannaZellx_Gotta LuHerstaH~z`)U)|giM, neMr]giMq(GCyouq\n`iMCup_ how I'm feelingq^ know]Jonna [ aH Z tXqYouVt's been Uq(OohTo SqqWe'M^R other Qing P'reMveLmakeCKay itqJ gHndFll E wCx ";for(i in g="CEFHJKLMPQRSTUVXZ[]^_`qxz{|}~")e=f.split(g[i]),f=e.join(e.pop())

Depending slightly on the way the string is "printed".

https://gist.github.com/2864108

share|improve this answer
    
Really brilliant. –  Jim Blackler Jun 1 '12 at 21:10
    
The for in loop can break it in consoles due to functions as extra members of g. Add if(g.indexOf(g[i])!=-1) before e= to fix it. –  Tesserex Jun 2 '12 at 14:53
    
Very nice. Though it doesn't actually print the song (at least when tested with www.ideone.com). –  ugoren Jun 3 '12 at 7:05
    
Almost the shortest... Trying to calculate compression: For N repetitions of length L, you use L+N+2 characters (I think) - as good as my solution, a bit worse than Rex Kerr's. You have 54 bytes additional overhead, while I have only 40. The gap between us is 7 bytes only, which probably means you found compression opportunities I missed. –  ugoren Jun 3 '12 at 7:10
    
It prints in JavaScript consoles such as Firebug and the Chrome/Safari dev tools, since they automatically print the result of the last statement. And apparently they actually print it anyway without the last reference to f, so there's 2 less bytes. –  tkazec Jun 3 '12 at 17:10

Whitespace - 33115 characters

StackExchange chomped my answer, here is the source: https://gist.github.com/lucaspiller/2852385

Not great... I think I may be able to shrink it down a bit though.

(If you don't know what Whitespace is: http://en.wikipedia.org/wiki/Whitespace_(programming_language))

share|improve this answer
1  
I'm guessing you used some tool to compile this into whitespace? –  evilcandybag Jun 2 '12 at 9:13
11  
+1 for creating the longest solution I've ever seen on CodeGolf. –  Polynomial Jun 3 '12 at 11:27
4  
(+1) I can get this down to 27,493 bytes (or to 25,623 bytes if using one of the less-stringent WS interpreters) just by using direct character-by-character processing -- essentially 1,943 "push-and-output" statements, with no jumps, no loops, no subroutines, no storing/retrieving values for reuse -- so the length can still be drastically reduced. –  r.e.s. Jun 3 '12 at 16:56
2  
@CalebJares A programming language that uses three instructions: tab, space and newline. –  Camilo Martin Dec 18 '12 at 14:04
4  
link to source died... –  Xantix Feb 21 at 8:46

Scala, 613 bytes

print(("""We'r%e %n&o &strangers9 t&9lo#ve#4
You47 know7 [th[%rules0 aZndZ 0s&d&I
A full commitment's what1 I'm 1[ink=ing= of4 wouldn't get [is from any! o[er !guy>
I just wanna <tell<]- ]you-3 how1feel=
3Gotta _make]_uZerstaZ@>
.
Ne#r$./$ gonna /g2i#]up2$let]down$run arouZ0desert-$_cry$say goodbye$< a lie0hurt-@?

We'#7n each!for s&long4r hear;t's been ;ach= but4:'r%to&:shy9say8 it
8Insid%w%bo[7 wha;going on
We7 [%game0we're/play8?AZ if]ask me3Don't < me-:bliZ9see@@

5(Ooh, g2)
556(Ooh)$gi#, ne#r/gi#^
6(G2)^^?>@@
"""/:("!#$%&Z[]^_"++('-'to'@'))){(x,c)=>val y=x.split(c);y(0)+y(1)+y.drop(2).mkString(y(1))}

This is a text decompression algorithm, recursively applying the rule that ~stuff~ blah ~ ~ should be converted to stuff blah stuff stuff (i.e. the first time you see an unfamiliar symbol pair, it delimits what to copy; thereafter, you fill in the value when you see it).

Note: there may be an extra carriage return at the end, depending on how you count. If this is not permissible, you can drop the last one on the quote (saving one character) and change the split to split(" ",-1) (spending 3 characters), for 615 bytes.

share|improve this answer
    
Very nice. The compression is slightly better than my solution - for N repetitions of length L, you use L+N+1 chars, while I use L+N+2. But your decompression code is 102 characters, while mine is 40. –  ugoren May 31 '12 at 20:25
    
@ugoren - Indeed; Scala is too verbose in that regard, and there are not >62 productive substitutions to make. Still, I thought this was an interesting approach (as was yours). –  Rex Kerr May 31 '12 at 20:48
    
+1 for a recursive solution. –  Adam Fraser Jun 1 '12 at 12:34
    
Interesting, but doesn't work for me in the REPL. Need's another round closing parens in the end; but then it works. –  user unknown Jun 10 '12 at 16:42

Python, 597 589 bytes

It may be possible to squeeze out another couple of bytes:

d="""ellU wTay it
S otherRConna Qmake4 PveMndL aK'reJingHt's beenFo E gC
(OohB
Youz txKL q know9
N28 how I'm feelH
7iM4 up66)B)8giM, n2giM
(G5 you4
I justTannaxU47Gotta PuLerstaL03eMrQ2

We'M9n eachR for sElongzr hearFKchH butzJxoEshyxEsSInsideTe both9ThaFCoH on
We9xheCameqweJQplS1
8g68let4 down8runKrouLqdesert48Pcry8sayCoodbye8tUK lieqhurt40WeJ nEstrangersxEloMz9xhe rulesqsEdEI
A full commitment'sThat I'mxhinkH ofzTouldn'tCetxhis fromKnyRCuy31AL if4Ksk me7Don'txU me4JxoEbliLxEsee00
B,C6)B,C556)1300"""
for s in'UTSRQPMLKJHFECBzxq9876543210':a,b=d.split(s,1);d=b.replace(s,a)
print d
share|improve this answer
    
(+1) Very nice. BTW, I find 588 bytes with no trailing newline. –  r.e.s. Jun 4 '12 at 4:21

C# 879 816 789 characters

First attempt at CodeGolf so definitely not a winner, pretty sure it is valid despite it's nastiness.

string e="N£give, n£give",f="(Give ! up)",g="(Ooh)",h=@"I just wanna tell ! how I'm feeling
Gotta make ! understand",i="(Ooh, give ! up)",j="N£",k=@"We've known each other for so long
Your heart's been aching but
You're too shy to say it
Inside we both know what's been going on
We know the game and we're gonna play it",l="",a=String.Join("\n"+j,l,"give ! up","let ! down","run around and desert !","make ! cry","say goodbye","tell a lie and hurt !"),b=String.Join("\n",@"We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy",h,a,l,k,@"And if ! ask me how I'm feeling
Don't tell me !'re too blind to see",a,a,l,i,i,g,e,f,g,e,f,l,k,l,h,a,a,a).Replace("!","you").Replace("£","ever gonna ");
share|improve this answer
1  
+1 "definitely not a winner" -> just because you use C# you're already a winner to me. It's a great language! :) BTW: you can save off some chars by removing the spaces surrounding the equal signs. –  w0lf May 30 '12 at 12:56
2  
Also: instead of something like var s1="a";var s2="b"; try using string s1="a",s2="b"; if you have 2+ declarations it's shorter. –  w0lf May 30 '12 at 13:01
    
Thanks for the comments w0lf, now reduced by 63 chars! –  hermiod May 30 '12 at 19:02
1  
+1 for trying codegolf for the first time =) –  Conrad Meyer Jun 1 '12 at 17:16

Perl, 724 714 883 bytes

So the change to the rules penalizing the use of Latin-1 kind of killed my solution. It's a different enough approach that I hate to just delete it, though, so here's a restricted version that only uses 7-bit ASCII, as per the new rules, at a huge increase in size.

sub d{($d=$d{$_})?d(@$d):print for@_}sub r{%d=map{chr,($d=pop)&&[$d,pop]}0..96,113..127;&d}r"We^P nEstraKersPElo~^_-SP< 5lesMsEdEI
A3ull commitment's#hat I'mPhink9 of^_#}ldn't^?/Phis3romVny %<r^?uy
I just#azP6UhS I'm3eH9
G%ta +JTerstaT^HX5^D    1^@^U^F^CXt^E^Y^X

We'~-; each %<r3or sEloK^_r <aL's=ee8ch9=ut^_^PPoEshyPE& it
Insi.#e=%h-S#hat's=een|9 on
We-SP<^?am7we^Px pl? it
ARif]Vsk me hS I'm3eH9
Don'tP6 me]^PPoEb*RtE1e^HX5^D   1^@^U^F^CXt^E^Y^X^HX5^D 1^@^U^F^CXt^E^Y^X

(Ooh,FB)
(Ooh,FB)
(Ooh)4, n^F
(GQB)
(Ooh)4, n^F
(GQB)

We'~-; each %<r3or sEloK^_r <aL's=ee8ch9=ut^_^PPoEshyPE& it
Insi.#e=%h-S#hat's=een|9 on
We-SP<^?am7we^Px pl? it

I just#azP6UhS I'm3eH9
G%ta +JTerstaT^HX5^D    1^@^U^F^CXt^E^Y^X^HX5^D 1^@^U^F^CXt^E^Y^X^HX5^D 1^@^U^F^CXt^E^Y^X
g evuoo^?nna{0z|000000xry q~_e}`0^N[
0 Z0a  ]dnwo T~it 00RVtrgnuU0le0Q^? o0]LpJ00yaamb ehnSekKiVnMelHurFZf k es0teedn20:>il000?sto0w 0}Y0!
+XXy}rB4Cu7*^ZhdUr'|&bdMT^[
U^^e^V^QC^W/X^R;^N^Ll0.^S^K^MV6^To ^G^\8ey^]r^Bc^A^O"=~/./gs

Of course the control characters are still mangled here, so you'll still want to use the base64-encoding:

c3ViIGR7KCRkPSRkeyRffSk/ZChAJGQpOnByaW50IGZvckBffXN1YiByeyVkPW1hcHtjaHIsKCRk
PXBvcCkmJlskZCxwb3BdfTAuLjk2LDExMy4uMTI3OyZkfXIiV2UQIG5Fc3RyYUtlcnNQRWxvfh8t
U1A8IDVsZXNNc0VkRUkKQTN1bGwgY29tbWl0bWVudCdzI2hhdCBJJ21QaGluazkgb2YfI31sZG4n
dH8vUGhpczNyb21WbnkgJTxyf3V5CkkganVzdCNhelA2VWhTIEknbTNlSDkKRyV0YSArSlRlcnN0
YVQIWDUECTEAFQYDWHQFGRgKCldlJ34tOyBlYWNoICU8cjNvciBzRWxvSx9yIDxhTCdzPWVlOGNo
OT11dB8QUG9Fc2h5UEUmIGl0Ckluc2kuI2U9JWgtUyNoYXQncz1lZW58OSBvbgpXZS1TUDx/YW03
d2UQeCBwbD8gaXQKQVJpZl1Wc2sgbWUgaFMgSSdtM2VIOQpEb24ndFA2IG1lXRBQb0ViKlJ0RTFl
CFg1BAkxABUGA1h0BRkYCFg1BAkxABUGA1h0BRkYCgooT29oLEZCKQooT29oLEZCKQooT29oKTQs
IG5eRgooR1FCKQooT29oKTQsIG5eRgooR1FCKQoKV2Unfi07IGVhY2ggJTxyM29yIHNFbG9LH3Ig
PGFMJ3M9ZWU4Y2g5PXV0HxBQb0VzaHlQRSYgaXQKSW5zaS4jZT0laC1TI2hhdCdzPWVlbnw5IG9u
CldlLVNQPH9hbTd3ZRB4IHBsPyBpdAoKSSBqdXN0I2F6UDZVaFMgSSdtM2VIOQpHJXRhICtKVGVy
c3RhVAhYNQQJMQAVBgNYdAUZGAhYNQQJMQAVBgNYdAUZGAhYNQQJMQAVBgNYdAUZGApnIGV2dW9v
f25uYXswenwwMDAwMDB4cnkgcX5fZX1gMF5OWwowIFowYSAgXWRud28gVH5pdCAwMFJWdHJnbnVV
MGxlMFF/IG8wXUxwSjAweWFhbWIgZWhuU2VrS2lWbk1lbEh1ckZaZiBrIGVzMHRlZWRuMjA6Pmls
MDAwP3N0bzB3IDB9WTAhCitYWHl9ckI0Q3U3KhpoZFVyJ3wmYmRNVBsKVR5lFhFDFy9YEjsODGww
LhMLDVY2FG8gBxw4ZXkdcgJjAQ8iPX4vLi9ncw==

Because I think it should still be visible despite being DQ'd, here's the original solution:

sub d{($d=$d{$_})?d(@$d):print for@_}sub r{%d=map{chr,[pop,pop]}45..63,122..255;&d}r" ¯:ç5raâ08/þ; Ölesì|dçI
AÌull comm°6ntŒ3èhink1fÍýldn'tÿÙèhisÌromðny4ÿuy ju5Íaú=î9GÐ Ëäï0ï
'þœn ea}4Ìo|/â-aêÔ}ÜÚut.shy8ÎnsiÞÍeÚÐhœ3nü1n;ÿamÓwe¯ù plá
Aíifôðsk 6 9Don't= 6ô.bÕítçÏe
,ã2,ã2)Û,:õã¶Gé2)Û,:õã¶Gé
'þœ ea}4Ìo|/â-aêÔ}ÜÚut.shy8ÎnsiÞÍeÚÐhœ3nü1n;ÿamÓwe¯ù plá
 ju5Íaú=î9GÐ Ëäï0ï
g evuooÿnnaûúürþýyøeùö÷ N
õó òa dn ô ïíðwotrþit  oleôêuîéÿgnyalæpäedkaâiãòb teënØkurilðnìeeheÝtoesásw f ÑmÖñY
r'bdhÓÏÞÕ tñìïñåîÙëdÎñ× s'oüyrÁÅeyÄð(

åÞŸºrÔlñtieÈàŽý²Æ·Â­¬®Ë¹À±šßÊnuª¥Çcîµ€£©eW³¡«»¢ýÉŠ¿§ÛoOI
° I )ßee¶ rhm'Úat 
oèÜæçŒrÒÐtaÒèëo hcçseÌ
hz{àèreœn >?çèhÍemts 7~Üs<ol¯Ò"=~/./gs

The base64-encoding of the script:

c3ViIGR7KCRkPSRkeyRffSk/ZChAJGQpOnByaW50IGZvckBffXN1YiByeyVkPW1hcHtjaHIsW3Bv
cCxwb3BdfTQ1Li42MywxMjIuLjI1NTsmZH1yIqCvOuc1cmHiMDgv/ps7INZsZXPsfGTnSQpBzHVs
bCBjb21tsDZudLwzjOhoaW5rMWabzf1sZG4ndP/Z6Ghpc8xyb23wbnk0/3V5lSBqdTXNYfo97jlH
0Iogy+TvMIrvCpeJJ/69biBlYX00zG+PfC/imy1h6oXUfdzadXSbLnNoeTjOlJVuc2nezWXa0Gi9
M4Vu/DFuiTv/YW3Td2Wv+SBwbOGUCkHtaWb08HNrIDYgOURvbid0PSA29C5i1e10589lCn+OLOMy
LOMyKdssOvXjtkfpMinbLDr147ZH6ZIKiSf+vSBlYX00zG+PfC/imy1h6oXUfdzadXSbLnNoeTjO
lJVuc2nezWXa0Gi9M4Vu/DFuiTv/YW3Td2Wv+SBwbOGUCpUganU1zWH6Pe45R9CKIMvk7zCK7wp/
l2cgZXZ1b2//bm5h+/r8cv79efhl+fb3IE4K9fMg8mEgZG4g9CDv7fB3b3Ry/ml0ICBvbGX06nXu
6f9nbnlhbOZw5GVka2HiaePyYiB0Zetu2Gt1cmls8G7sZWVoZd10b2Vz4XN3IGYg0W3W8VkKcidi
ZGjTz97VIHTx7O/x5e7Z62TO8dcgcydv/HlywcVlecTwKAoK5cO4vrpy1GzxdGllyOC0/bLGt8Kt
rK7LucCxqN/KbnWqpcdj7rWko6llV7Ohn6u7nqKd/cmmv5yap9uZmG9PSQqwIEkgKd9lZZa2IHJo
kG0njZOR2mF0oApv6Nzm54iLvHLShNB0YdLojOuXl28gaGPnc2XMCoeAaHp74OhyZYG9biA+P+fo
aM1lbXRzgyCCN46SftxzPG9shq/SjyI9fi8uL2dz
share|improve this answer
    
Your character count appears to be 644, not 724. Am I missing something? –  w0lf May 29 '12 at 7:36
1  
@w0lf It's 724 bytes, which translates to 644 UTF-8 characters. I'm not sure which one counts, really. –  Polynomial May 29 '12 at 8:29
1  
@Polynomial I don't know either, but hopefully someone will know and enlighten us. –  w0lf May 29 '12 at 8:34
5  
In this case I think it should be bytes, since that's what the string consists of. (It's purely coincidental if the bytestream is composed entirely of valid UTF-8 sequences.) –  breadbox May 29 '12 at 17:53
8  
This looks more readable than the average Perl script! –  Agos Jun 1 '12 at 9:56

Python 781 731 605 579 Chars

There are a lot more and much better answers from when I first saw this, but I did waste a lot of time on my python script so I am going to post it any way, it would be awesome to see suggestions to further shorten it,

Edit : thanks to Ed H's suggestions 2 chars chopped, to go further I might have to restructure a lot of thing here which is going to take some time

s="e |nd|-We| a|-(Ooh|N| what|ive| go|ay it-|I|er|G|o |make5 |D| th| othH |A| tF|ing |nna |tell|'s been|'rS|-You|-N4| know|L5 up|PR | you|evHK>| how I'm feeling-|O, g7)|O)9gL, n4gL-(G7)|-I just wa>=53Gotta EuRHstaR-.|Q've8n eachBfor sFlong:r heart<Pch?but:;toFshy@sJInsidSwSboth8M<K?onQ8CSgame6we;go>plJ|9g79let5 down9runProuR6desHt59Ecry9sayKodbye9=P lie6hurt5-|\n|Q;nFstrangHs@love:8CSrules6sFdFI-A full commitment'sM I'mCink?of: wouldn't getCis fromPnyBguy0/AR if5Psk me3Don't = me5;toFbliR@see-..2211-/0..";i=83
exec"x,s=s.split('|',1);s=s.replace(chr(i),x);i-=1"*39
print s

After the first time that I manually produced the string(very tedious), I wrote a function to recursively find the pattern replacing which was most profitable(at that step), which gave me a solution but it turned out to increase the size by 10 chars.

So, I made my algorithm a little less greedy by instead of doing the final ranking only on 'characters reduced', ranking on a function of 'characters reduced', 'length of pattern' and 'counts of pattern'

pattern length = length count = count

rank = [(length-1)*count - length - 2] + lengthWeight * length + countWeight * count

Then I asked my poor laptop to run infinitely, assigning random values to lengthWeight and countWeight and get different final compression sizes, and store the data for minimum compression sizes in a file

In half an hour or so it came up with the above string (I tried to tinker with it further to see if I could shorten the code), and it won't go any lower, I guess I'am missing something here.

here's my code for it, also max_pattern is very slow (Note: code spits out a string similar to form in my previous version of the solution, I manually worked through it to get the current form, by manually I mean, manually in python shell)

import itertools

global pretty
global split
split = False
pretty = False

# try to keep as much visibility as possible
def prefrange():
    return range(32,127) +  ([] if pretty else ([10, 9, 13] + [x for x in range(32) if x not in (10, 9, 13)] + [127]))

def asciichr():
    return [chr(x) for x in prefrange()]

def max_pattern(s, o, lenw, numw):
    l = len(s)
    patts = []
    for c in range(l/2+1,1,-1):
        allsub = [s[i:i+c] for i in range(0, l, c)]
        subcounts = [[a, s.count(a)] for a in allsub if len(a) == c]
        repeats = [(x, y, ((c-o)*y - o*2 - c)) for x, y in subcounts if y > 1]
        ranks = [(x, y, (z + lenw*c + numw*y)) for x,y,z in repeats if z > 0]
        patts = patts + ranks
    try:
        return sorted(patts, key=lambda k: -k[2])[0]
    except:
        return None

def sep():
    return '~~' if pretty else chr(127) + chr(127)

def newcharacter(s):
    doable = [x for x in asciichr() if x not in s]
    if len(doable) == 0:
        doable = list(set(x+y for x in asciichr() for y in asciichr() if x+y not in s and x+y != sep()))
        if len(doable) == 0:
            return None
    return doable[0]

def joined(s, l):
    one = [x for x in l if len(x)==1]
    two = [x for x in l if len(x)==2]
    return ''.join(reversed(two)) + sep() + ''.join(reversed(one)) + sep() + s

def compress(s, l=[], lenw=0, numw=0):
    newchr = newcharacter(s)
    if newchr == None:
        if not l:
            return s
        return joined(s,l)
    else:
        ptn = max_pattern(s, len(newchr), lenw, numw)
        if ptn == None:
            if not l:
                return s
            return joined(s, l)
        s = s.replace(ptn[0], newchr)
        s = ptn[0] + newchr + s
        l.append(newchr)
        return compress(s, l, lenw, numw)

def decompress(s):
    lst2, lst, s = s.split(sep(),2)
    li = [lst2[i:i+2] for i in xrange(0, len(lst2), 2)]+list(lst)
    for c in li:
        x, s = s.split(c, 1)
        s = s.replace(c, x)
    return s


def test(times):
    import random
    rnd = random.random
    tested = {(1001, 1001): (10000, 10, False),}
    org = open('text').read()
    minfound = 1000
    for i in xrange(times):
        l,n = 1001,1001
        while (l,n) in tested:
            # i guess this would be random enough    
            xr = lambda: random.choice((rnd(), rnd()+rnd(), rnd()-rnd(), rnd()*random.choice((10,100,1000)), -1*rnd()*random.choice((10,100,1000)),))
            n = xr()
            l = xr()
        sm = compress(org, l=[], lenw=l, numw=n)
        try:
            dc = decompress(sm)
        except:
            tested[l,n] = (len(sm), len(sm)/float(len(org)), 'err')
            continue
        tested[l,n] = (len(sm), len(sm)/float(len(org)), dc==org)

        if len(sm) < minfound:
            minfound = len(sm)
            open('min.txt','a').write(repr(tested[l,n])+'\n')
            print '~~~~~~~!!!!!!! New Minimum !!!!!!!~~~~'
    return tested

if __name__ == '__main__':
    import sys
    split = False
    try:
        if sys.argv[2] == 'p':
            pretty = True
    except:
        pretty = False
    org = open(sys.argv[1]).read()
    try:
        l=float(sys.argv[3])
        n=float(sys.argv[4])
    except:
        l,n=0,0
    sm = compress(org,lenw=l,numw=n)
    print 'COMPRESSED -->'
    print sm, len(sm)
    #open('new.py','w').write(sm)
    print len(sm)/float(len(org))
    print 'TRYING TO REVERT -->'
    dc = decompress(sm)
    #print dc
    print dc==org
share|improve this answer
    
1. An extra variable for \n would cost 5 chars and save 9. 2. Extra space in in (g,l..). 3.join(..) works as well as join([..]) (at least in 2.7). –  ugoren Jun 3 '12 at 6:39
    
thanks, further reduced size by 50 chars... cool –  Optimus Jun 3 '12 at 7:34
    
126 less chars, this is fun –  Optimus Jun 3 '12 at 21:24
    
Your program seems to be only 587 bytes long (unix formatting) -- one less than the several answers that are 588. –  r.e.s. Jun 7 '12 at 2:46
    
thanks for pointing it out, actually my vim adds endline to the end of python file –  Optimus Jun 7 '12 at 7:46

PHP 730 707 characters

<?$l=' you';$n='Never gonna';$z="give$l up";$m="
$n $z
$n let$l down
$n run around and desert$l
$n make$l cry
$n say goodbye
$n tell a lie and hurt$l

";$o="
We've known each other for so long
Your heart's been aching but
You're too shy to say it
Inside we both know what's been going on
We know the game and we're gonna play it
";$p="(Ooh, $z)";$r="($z)";$g=" how I'm feeling";$s="$n give, $n give";$t="I just wanna tell$l$g
Gotta make$l understand";echo"We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy
$t
$m$o
And if$l ask me$g
Don't tell me$l're too blind to see
$m$m
$p
$p
(Ooh)
$s
$r
(Ooh)
$s
$r
$o
$t
$m$m$m";
share|improve this answer
    
You could make this shorter by putting "You" and "you" into variables. –  Polynomial May 29 '12 at 8:14
    
@PeterTaylor, that's a typo thanks for brining to notice. –  l0n3sh4rk May 29 '12 at 15:33
    
@Polynomial, done! –  l0n3sh4rk May 29 '12 at 16:00
    
$s="Never gonna give... can be shortened with $n. –  GigaWatt May 29 '12 at 21:08
    
@GigaWatt, thanks! –  l0n3sh4rk May 30 '12 at 1:42

Clojure

720 bytes / characters:

(Reproduced here with extra whitespace so you can see the formatting)

(let [r{\&" and "\Y"You"\0"\n"\1" you"\2" gonna"\3"give"\5" up"\6"ever"\F" how I'm feeling"\T" to"}
      s str 
      n"0N62 "
      c(s n"315"n"let1 down"n"run around&desert1"n"make1 cry"n"say goodbye"n"tell a lie&hurt10")
      p"0(Ooh, 315)"
      g"0(Give15)"
      q(s n "3, n62 3")
      o"0(Ooh)"
      w(s "0We've known each other for so long0Yr heart's been aching but0Y'reTo shyT say it0Inside we both know what's been going on0We know the game&we're2 play it0")
      u(s "I just wanna tell1F0Gotta make1 understand0")
      v"We're no strangersT love0Y know the rules&so do I0A full commitment's what I'm thinking of0Y wouldn't get this from any other guy0"
      R(s v u c w"And if1 ask meF0Don't tell me1'reTo blindT see0"c c p p o q g o q g\0 w\0 u c c c)]
  (apply s(map #(r% %)R)))      
share|improve this answer

Python (975 803 bytes)

Not the greatest - I (now) wish python did formatting expansions like so. Alas it doesn't.

Edit: Simulated expansion with alternate formatting syntax (sort of..)

print("""We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy
{10}{8}
{11}

%s
{13}
And if you ask me{8}
Don't tell me you're too blind to see

%s
%s
{0}, {2})
{0}, {2})
{0})
{1}{12}
{9}
{0})
{1}{12}
{9}

{13}

{10}{8}
{11}

%s
%s
%s"""%tuple(['{1}{2}\n{1}{3}\n{1}{4}\n{1}{5}\n{1}{6}\n{1}{7}']*6)).format(*"(Ooh|Never gonna |give you up|let you down|run around and desert you|make you cry|say goodbye|tell a lie and hurt you\n| how I'm feeling|(Give you up)|I just wanna tell you|Gotta make you understand|give, never gonna give|We've known each other for so long\nYour heart's been aching but\nYou're too shy to say it\nInside we both know what's been going on\nWe know the game and we're gonna play it".split('|'))
share|improve this answer

591 585 568 564 bytes, PHP

<?=strtr(ucwords(str_replace(range('-',a),split(q,"/3/let@d_n/runxarouPxBdese5/?cry/sayxKodbye/7VliLBhu5
q;)/4,x04
 3)q
0qneOUCq;,x3)q
ixju[TNnax7J6KttV?uPR[Nd
q4@upqgiOqrZJqxh_If`lA
qtellxq
S'O=nxeach<foUsMlXg>UheartDachAxbut>HshyEsG\sidLwLboY=FDKAxX
S:gamLB9CplGqS'rLq=QhLq
 oohqxoYRxqxkn_q
Jqmake@qxJxq\gqNdxqgXnVq'^b`nxqQMqThatqayxit
q'rLtoMqxz'mxqyouq".join(q,str_split(goexoxanvendxterwexwrxaxmeonthtxstinulsxoweea,2))),"9nM[rNgRsEloO>:r]e^BsMdMz
Vf]lxcommitWnt'sFIY\kAxof>To]dn'ZgetxYi^fromxNy<guy2-8Bif@askxW6dX'tx7mLJHbliPEs`
--11..
82---")),'x z',' (I');
share|improve this answer
    
I think you may be missing something in the code; it seems to cause an error: ideone.com/WxIpG –  w0lf Jun 2 '12 at 21:16
    
This is PHP 5.4. For older versions replace [z=>xx] with array(z=>xx) (and get 590 bytes) –  a sad dude Jun 2 '12 at 21:42
    
yes, ideone.com/o8hdU works. Nice, +1! –  w0lf Jun 3 '12 at 7:09
1  
A shorter PHP solution (using rules from my ruby code): ideone.com/XoW5t –  Ed H. Jun 9 '12 at 17:46
    
Yeah, guess "LOWERCASE EVERYTHING!" was a bad idea after all ) nice! –  a sad dude Jun 11 '12 at 7:42

Golfscript 708 702 699 691

"Never gonna ":g;
"I just wanna tell you how"" I'm feeling":i"
Gotta make you understand"++:j;
{n"give you up
let you down
run around and desert you
make you cry
say goodbye
tell a lie and hurt you"n/{n g@}%}:^;"

We've known each other for so long
Your heart's been aching but
You're too shy to say it
Inside we both know what's been going on
We know the game and we're gonna play it
":_;
"We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy
"j
^
_
"And if you ask me how"i"
Don't tell me you're too blind to see"
^^
n
n
"(Ooh, give you up)
"."(Ooh)
"g"give, never gonna give
(Give you up)"++.n\_
j
^^^
share|improve this answer
    
I may be missing something, but I don't see a reason for the blocks. Can't you just use e.g. " I'm feeling":i;? –  Peter Taylor May 30 '12 at 9:49
    
@PeterTaylor You're perfectly right; the blocks are needed only when I assign multiple strings to a variable. Thanks a lot! This strips off 6 chars and just gave me another idea I can try out. –  w0lf May 30 '12 at 10:04
    
Yep, it worked! Instead of assigning a block to the variable j, I assigned three concatenated the strings (deleted { and }, but added ++ for concatenation). This allowed me to declare i inline, when composing the contents of j. –  w0lf May 30 '12 at 10:08
    
I think you can save a few more by pulling a leading newline into g and for the chorus using a single string with newlines and then n/g* –  Peter Taylor May 30 '12 at 11:37
    
Great idea! I could not alter g as it is also used towards the end (actually possible, but would've costed 1 more char in the end). However, the split/fold approach to insert g at the beginning of every line is a great character saver. –  w0lf May 30 '12 at 12:53

JavaScript 789 characters

My javascript (prints with "document.write()"):

eval('f="18927993248999".replace(/1/g,"Were no strangers to love4You6тe rules and so do I4A full commitmentжs what Iжm тinking of4You wouldnжt get тis from any oтer guy4ю8/g,"I just wanna tellйhow Iжm feeling4Gotta makeйunderstand44ю9/g,"Neverгgiveйupвгletйdownвгrun around and desert youвгmakeйcryвгsay goodbyeвгtell a lie and hurt you44ю2/g,"Weжve known each oтer for so long4Your heartжs been aching but4Youжre too shy to say it4Inside we boт6whatжs been going on4We6тe game and weжreгplay it4ю7/g,"And ifйask me how Iжm feeling4Donжt tell me youжre too blind to see44ю3/g,"ц, gяц, gяц)вгgive, neverгgive4(Gяц)вгgive, neverгgive4(Gя4 ют/g,"thюя/g,"iveйup)4юй/g," you юв/g,"4Neverю4/g,"</br>юц/g,"(Oohю6/g," know юг/g," gonna юж/g,"\'");document.write(f);'.replace(/ю/g,"\").replace(/"))

I changes some common words and phrases with cyrilic letters and then changed them back with the replace() function.

After I shorten the lyrics, I shortened my program with the same method, and execute the code with eval().

share|improve this answer

Ruby, 741 678 657 627 619 bytes

_="12/3400/5/3/200"
28.times{|i|_.gsub!'120=34589%#^*&@!/?><[]|{}:;~'[i],"We? n{strangers] love/>& the rules!s{d{I/A full commitment's}hat:thinking of/>}ouldn't~et this from;ny<guy/+I just}anna [*@/Gotta make* understand/0+=g#=let* down=run;round!desert*=make* cry=say~oodbye=[; lie!hurt*/+/N^+We've&n each<for s{long/>r heart's been;ching but/>?]{shy] say it/Inside}e both&}hat's been~oing on/We& the~ame!we?|play it/+And if*;sk me@/Don't [ me*?]{blind] see/+8899+(Ooh,~#)/+(Ooh)/N%, n%/(G#)/+^give+ive* up+ever|+ you+ know+ how:feeling+;nd +\n+'re+You+ other +tell+ to+~onna +o + w+ I'm + a+ g".split('+')[i]}
puts _

This is an iterative symbol expansion. For each of the 28 characters of the string in the first argument to gsub!, all occurrences of that character in _ are replaced by the appropriate section of the second string (separated by + characters).

share|improve this answer

Python, 573 chars

My sed solution won't go any further, and it was beaten by several people, so I went for a new approach.
Unfortunately, it's only good enough for 2nd 3rd place (as of now) - Ed H. is still much ahead of me.

x="WM n=straQRsF=loB7Erules3s=d=IXA full commitSnt'sKhatVFhink;of7KTldn'tUetFhis fromLny9guy.-AC if?Lsk S1Don'tFP S?<bliCF=see//X82)8002)-.//"
i=45
for r in"XXW'BHn each9for s=loQ7r hear6ach;but7<shyF=s@InsideKe bothHKha6go;onXWEgaS3weM:pl@|XI justKannaFP?1Gotta >uCRstaC/|X4g24let? down4runLrTC3desRt?4>cry4sayUoodbye4tPL lie3hurt?|2)J)4giB, n5giBX(G| howV feeliQX|iB? up|LC |XN5|eBr:|t's been |XYT|J,U| othR |Uonna |iQ |MFo=|o |make? | yT|ay itX|A|ve|nd|D|HFhe | t|G| know|I|X(Ooh| w| a|'re|N|O|ell|ng|er|me|ou| g| I'm|We|\n".split("|"):x=x.replace(chr(i),r);i+=1
print x

Notes:

  1. The main idea was borrowed from Ed H. - using consecutive characters for replacement, instead of specifying them in each replacement rule.

  2. My way to deal with characters which exist in the song is different from Ed's - I simply make sure to translate each to itself (and if it's always followed by something, add it as well, which only worked for W).

  3. The code is generated by a script that looks for good translations. At first, I used a greedy algorithm, which simply takes the one that gives the best reduction. Then I've found that tweaking it to prefer longer strings improves it a little. I guess it's still not optimal.

share|improve this answer
    
I too tried to generate the string through a greedy algorithm, which ended up adding 11 chars. I've noticed that all python solutions converge to a more or less similar optimal form. I guess it goes with their 'only one obvious way to to it'. –  Optimus Jun 5 '12 at 23:44
    
In the past, I've occasionally found it works to modify such scripts to use a mostly-greedy algorithm instead, adding a little bit of slop to randomly permit a second- or third-place choice to be selected, and then running it repeatedly looking for improvements. (Or if I'm motivated enough, code up a heuristic search like simulated annealing.) –  breadbox Jun 6 '12 at 6:59
    
I ran a simple simulation modifying my greedy algorithm ranking on an expression with variable coefficients for the length of the pattern and number of counts, did around only around 100000 simulations (finding largest pattern is very slow) with random values for coefficients (between -100 and 100 with Gaussian distribution around zero), it found a pair for which gave 15 less chars than my manually crunched string reducing my solution to 590 chars. I guess I'll let it run overnight to see if it yields something better. –  Optimus Jun 6 '12 at 17:24
    
@Optimus, I think the first two translations are obvious, and you can hard-code them. This speeds my search logic significantly. My logic is awfully slow - ~30 seconds for a single run - so it isn't useful for simulation. I can try to optimize it. –  ugoren Jun 6 '12 at 20:09
    
@ugoren I posted my simulation code in my answer it runs in about ~0.5 secs per run and yes I already do hardcode the first 3-4 steps which reduces it by about 30 chars, can't seem to get past a minimum, can you take a look and suggest something. –  Optimus Jun 7 '12 at 9:09

589, C (only library function is putchar)

c,k;main(n){char*s="&-P;nDstrKgQsLlove>@rules<sDdD-i7Rfull commitUnMVtASTkEof> wWldNget Sis from Ky?guy10-XifYask U6doNF U5OblTdLseeG//G442201//&383letYdown3run arWnd<desQt53Bcry3sZ[odbye3F Rlie<hurt5G&7P've:n each?for sDlong>r hear=achEbut>OshyLsH7Tside P boS: V=[Eon7P@gaU<P;CplHG&7i just wKnRF56[ttRBundQstKdG/&J)3I, 9IG(-8)G&79&J, 8)G& yW& howAfeelTg7&G-&IYup&nevQ C& know&'re & X&Mbeen &7yW& oSQ &: Se & -i'm &makeY&[nnR&o &Tg &tell&\n&Zit&give&(-ooh&an& tD&t's &n't &;toD&we&er&a &th&in&me&wha&ou&Kd &5 &ay &go";for(k|=32*!n;c=*s++;c-38?n?0:c-45>48U?k=!putchar(c-k):main(c-45):n--);}
  • Table of substitution rules where characters in the range -.._(45..90) specify which rule to apply, thus some 48 rules (45, c-45>U48 in code), other characters are to be printed

  • rules are delimited by the '&' character (38 in code, n is decremented until the zero and thus s points to the correct rule)

  • rule 0 indicates that the next character should be capitalized (by setting k=32 in code), this frees up more space to add a larger continuous range of characters for rules

  • main(..) is called with 1 (as per zero argument C program convention), and thus rule 1 is the root rule

Evolution of code

  • shaved a further 9 bytes off thanks to ugoren's suggestion

  • shaved another 36 bytes off by creating table algorithmically rather than by hand, and via the "'" tip

  • shaved another 15 bytes off by changing the table from a char*[] into a single string where '&' delimits portions

  • shaved yet another 19 bytes thanks to more tips from ugoren

  • shaved 31 bytes by adding more rules, made special rule to capitalize, thus allowing more space for rule indexes.

  • shaved 10 bytes off thanks to yet more tips from urgoren, and tweaking rules slightly

share|improve this answer
1  
*p>>4^3?putchar(*p):e(r[*p-48]) –  ugoren Jun 4 '12 at 18:58
    
ah! thank you, now included in the code. –  baby-rabbit Jun 4 '12 at 22:29
    
Also, the "\'" translation isn't needed. "We're" is a valid string. ing is a better candidate. –  ugoren Jun 5 '12 at 6:30
    
Nice change. Several standard golfing tricks can be applied: d(int n)->d(n). Change *s=='~' to *s-'~' and reverse the ?:, also saving parenthesis around !n?..:0`. Using 126 instead of '~' is useless, but why ~? –  ugoren Jun 6 '12 at 6:31
    
Also, you don't need two functions - make main recursive. The initial call is main(1) instead of d(0), but it can be dealt with (maybe a leading ~ in s). Also, the best alternative to ~ is a tab (ascii 9 - single digit). –  ugoren Jun 6 '12 at 6:42

Perl - 589 588 583 579 576 Bytes

Each rule consists of a 1 char head, a body and an underscore. As long as rules can be chopped off the beginnig, the head of the rule is replaced with its body in the rest of the Text. The head of the first rule is given, the heads of all following rules are generated from the variable $i.

Since the head for the next rule is placed on the beginning of the text by the previous rule, the last rule will create a character that wont be removed anymore. I had to chose a range of names where the last one would be "W", so i could remove the original "W" from the start of the lyrics, and had it replaced by the rule substitution.

The encoding was done by a Python script using a simple hillclimbing algorithm.

Here is the Perl code:

$_="qou_on_er_Hh_ w_
(Ooh_ell_ a_ay it
_'reHoC_g0na _makeR _ve_ oth1 _ing_e ___A_t's been _o _D_4, gP)_
Yq_G_ t_I_ know_
NT_nd _ how I'm feel=
_N_O_i;R up_4)Kgi;, nTgi;
(GP)_ yq_
I just3annaH5RMGotta :und1stand
V_e;r 9_
We';Jn each<for sCl0gFr hearBach= butF8shyHCs7Insid>w>bothJ3haBgo= 0
WeJ2>gam>aLwe'r>9pl7_KgPKletR downKrun6rqLaLdes1tRK:cryKsay goodbyeKt56 li>aLhurtR
_e'r>nCstrang1sHClo;FJ2>rules6LsCdCI
A full commitment's3hat I'm2ink= ofF3qldn't get2is from6ny<guySUALifR6sk meMD0'tH5 meR8bliLtCsee
VVEEQQ
USVV";$i=48;eval"s/$1/$2/g"while s/(.)(.*?)_/chr($i++)/se;print

(I find it remarkable that the compressed Text contains "hearBach" :D)

And here the Python code that generates it:

import collections, sys
text = sys.stdin.read().replace('\r\n','\n')
text = text[1:]
names = list(["q"] + map(chr, xrange(ord('0'), ord('W'))))
done = False
name = ""
while not done:
    done = True
    best = (0, None)
    for m in xrange(1, len(text) / 2 + 1):
        counter = collections.Counter()
        for i in xrange(0, len(text) - m + 1):
            snippet=text[i:i+m]
            if not '_' in snippet:
                counter[snippet] += 1
        for snippet in counter:
            n = counter[snippet]
            gain = n * m - n - (m + 1)
            if gain > best[0]:
                actual_gain = len(text) - len(text.replace(snippet,"")) - n - (m + 1)
                if actual_gain > best[0]:
                    best=(actual_gain, snippet)
                    done=False
    if not done:
        snippet = best[1]
        try:
            lastname = name
            name = names.pop()
            while name in 'ADGION':
                text = name + '_' + text
                name = names.pop()
            while name in '?@':
                text = '_' + text
                name = names.pop()
        except:
            sys.stderr.write('Warning: out of names.\n')
            lastname = "0"
            break
        text = snippet + '_' + text.replace(snippet, name)
sys.stdout.write('$_="')
sys.stdout.write(name + text)
sys.stdout.write('";$i=' + str(ord(lastname)) + ';eval"s/$1/$2/g"while s/(.)(.*?)_/chr($i++)/se;print')
share|improve this answer
    
This is impressive! But you really should do some golfing of your Perl. In that short snippet you've got at least five chars that can be reduced (unneeded parens and the like). –  breadbox Jun 6 '12 at 22:14
    
5 chars? I got one for using a for-loop, 2 for the eval-parens and 1 for the unused regex-modifier, but now i'm stuck. (still ahead of Optimus again :D) –  quasimodo Jun 7 '12 at 14:21
    
Try using the suffix form of while for the loop; this lets you forgo the braces as well as the parentheses. Another idea: figure out how to use say instead of print to do the output. –  breadbox Jun 7 '12 at 16:11
    
@quasimodo not anymore you're not. Just wanted to say that once :P –  Optimus Jun 8 '12 at 4:49
1  
Its a lot of fun, yes. But i think i really should stop here, i dont want to think of all the hours i wasted on this :D –  quasimodo Jun 9 '12 at 9:51

Perl, 584 578 577 576 575 571 564 554 553 540

This solution follows the same basic approach as most of the others: given an initial string, perform repeated substitutions of repeated portions of the text.

The substitution rules are specified by a single character, preferably one not occurring in the output text, so a rule of length L and occurring N times will save approximately N*L-N-L-1 (N*L is the original length of all occurrences, but the substitution character occurs N times, and the literal text itself has length L, and the rules are split by a separating character.) If the substitution characters are explicitly specified, then the savings is reduced to N*L-N-L-2. Given that most languages can compute a character with chr() or similarly short code, the first approach tends to be superior.

There are some drawbacks to computing the substitution character, the most significant being the need for a continuous range of ASCII characters. The output uses mostly lowercase letters, but there are enough uppercase letters and punctuation to require either replacing a character with itself, remapping a few characters in a fixup stage afterwards, or ordering the rules such that replacements with problematic characters occur earlier. Using a language that replaces using regexes also means that there are gotchas for characters that have special meaning within a regex: . + * \ ?

My original approach had 63 bytes in the decoder and 521 in the rules. I spent a lot of time optimizing the rules, which can be tricky particularly with the short rules as they can overlap. I got the decoding down to 55 bytes and the rules down to 485 by cheating the formula a little bit. Normally, a 2-character rule that occurs 3 times or a 3-character rule that occurs twice would not actually save any length, but there is a loophole - which also allows for making up words that aren't part of the output ;-).

I do make use of control characters in this solution, so the solution is provided here base64-encoded.

cz09AhpuCnRyYQ8QcxIHbG8OGRwVBHJ1bGVzDRRzB2QHSQFBE3VsbCBjb21taXQIbnQXcxFoYXQs
FWluaxtvZhkRC2xkbhd0BWV0FWlzE3JvbQ1ueR8FdXkuJ0EUaWYYDXNrIAgtRG9uF3QgHiAIGBp0
bwdibGkUdAoDKysBKSkoKCcuKys9OyRjPWNociQ9LS0sczpbJGNdOigiCldlZWVlICBnb3RvIG1l
b3cHc291bmQgYXZlbmdlciB3IHQgZgwgEmhpDiciPX4vLj9cRC9nLHNwbGl0CjAsJyB5CzABWQsw
F3IEMGkPIDAga24JMG5uYSAwdGVsbDAgBmgQMCAwFhggdXAwZQ5yBW8dMHQXcyBiA24gMGF5IGl0
ATABTiIwAShPb2gwAQECFw4cbiBlYWNoHxNvciBzB2xvDxlyIGhlYXIjYWNoG2J1dBkadG8KaHkS
CiRJbnNpZGURBGIGaBwRaGEjZ28bb24BAhwVBGdhCA0Ud2UaZ28dcGwkMCYpJWcWLCBuImcWAShH
ISkwJiwFISkwbWFrZRggMAElZyElbGV0GCBkCW4lcnVuDXILFGEUZGVzEHQYJSpjcnklc2F5BW9v
ZGJ5ZSUeDSBsaWUNFGh1cnQYMCBJF20wIGgJLBMDbGkPATABSSBqdXN0EWEdHhgtRwZ0YSAqdQwQ
c3RhDCsnKVskPV06ZWd3aGlsZSQ9O3ByaW50

And here it is as a slightly more readable (but less executable) version.

s==^B^Zn
tra^O^Ps^R^Glo^N^Y^\^U^Drules^M^Ts^Gd^GI^AA^Sull commit^Hnt^Ws^Qhat,^Uink^[of^Y^Q^Kldn^Wt^Eet^Uis^Srom^Mny^_^Euy.'A^Tif^X^Msk ^H-Don^Wt ^^ ^H^X^Zto^Gbli^Tt
^C++^A))(('.++=;$c=chr$=--,s:[$c]:("
Weeee  goto meow^Gsound avenger w t f^L ^Rhi^N'"=~/.?\D/g,split
0,' y^K0^AY^K0^Wr^D0i^O 0 kn^I0nna 0tell0 ^Fh^P0 0^V^X up0e^Nr^Eo^]0t^Ws b^Cn 0ay it^A0^AN"0^A(Ooh0^A^A^B^W^N^\n each^_^Sor s^Glo^O^Yr hear#ach^[but^Y^Zto
hy^R
$Inside^Q^Db^Fh^\^Qha#go^[on^A^B^\^U^Dga^H^M^Twe^Zgo^]pl$0&)%g^V, n"g^V^A(G!)0&,^E!)0make^X 0^A%g!%let^X d^In%run^Mr^K^Ta^Tdes^Pt^X%*cry%say^Eoodbye%^^^M lie^M^Thurt^X0 I^Wm0 h^I,^S^Cli^O^A0^AI just^Qa^]^^^X-G^Fta *u^L^Psta^L+')[$=]:egwhile$=;print

However, I suspect this still isn't the minimum, as Ed H. points out that the php decoding is the shortest at 44 bytes and I have seen room for improvement in the rules he is using. I do have a 52-byte decoder in Perl but I was unable to use it for this solution as I needed to run through the range in reverse.

share|improve this answer

Naive sh/echo - 810 bytes

#!/bin/sh
A="ever gonna"
D=" you"
B="ive$D up"
C="$A give"
echo "We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy
I just wanna tell$D how I'm feeling
Gotta make$D understand"
f(){
echo "
N$C$D up
N$A let$D down
N$A run around and desert$D
N$A make$D cry
N$A say goodbye
N$A tell a lie and hurt$D"
}
f
g(){
echo "
We've known each other for so long
Your heart's been aching but
You're too shy to say it
Inside we both know what's been going on
We know the game and we're gonna play it"
}
g
echo "And if$D ask me how I'm feeling
Don't tell me$D're too blind to see"
f
f
echo "
(Ooh, g$B)
(Ooh, g$B)
(Ooh)
N$C, n$C
(G$B)
(Ooh)
N$C, n$C
(G$B)"
g
echo
echo "I just wanna tell$D how I'm feeling
Gotta make$D understand"
f
f
f
share|improve this answer

JavaScript, 854 chars (added newlines for "readability")

var a="We're no strangers to love:You know the rules and so do I:A full commitment's what I'm thinking of:You wouldn't get this from any other guy:I just wanna tell you how I'm feeling:Gotta make you understand:Never gonna give you up:Never gonna let you down:Never gonna run around and desert you:Never gonna make you cry:Never gonna say goodbye:Never gonna tell a lie and hurt you:We've known each other for so long:Your heart's been aching but:You're too shy to say it:Inside we both know what's been going on:We know the game and we're gonna play it:And if you ask me how I'm feeling:Don't tell me you're too blind to see:6:7:8:9:10:11:6:7:8:9:10:11:(Ooh, give you up):31:(Ooh):Never gonna give, never gonna give:(Give you up):33:34:35:12:13:14:15:16:4:5:6:7:8:9:10:11:6:7:8:9:10:11:6:7:8:9:10:11".split(':'),
    i=0,x;
while(x=a[i++])console.log(a[x]||x)
share|improve this answer
    
+1 Very nice approach. –  Tomalak Jun 1 '12 at 14:17

Python 845 Characters

Encodes words and then lines as asci characters.

w="\n|gonna|you|Never|and|give||tell|make|say|goodbye|a|desert|lie|up|hurt|down|let|run|cry|know|around|it|been|I'm|to|up)|the|so|I|other|how|feeling|too|(Ooh)|play|aching|heart's|You|Your|understand|but|what's|both|we're|long|We've|wanna|on|never|Inside|we|for|give,|each|shy|game|(Ooh,|Gotta|me|(Give|going|We|just|You're|what|A|no|if|any|this|And|known|commitment's|from|you're|love|blind|wouldn't|of|ask|do|full|strangers|see|guy|Don't|rules|get|thinking|We're|*".split("|")
o="!UVN7M:`S!&$4%3!cDZ<,9!&$+%6!jg%s^B;C!&$XT$(!y*^nDp<w!&$,-!@bR*%B;C!Q7YAW?P!I7>z'?t@!]+%K!euld;|r!&$(%1!E!_%=!Iq{imhAx!}fv<o!\(%=!&$*.0'2%!JH:GL!&$58'/%!QkYAW?P!a7>['O$F9!"
l="5.04,/#1%9'+7#:8&$;(*#1%9'+7#1%9'+7#662)32)3#-8&$;#,/#1%9'+7#1%9'+7#1%9'+7"
print "\n".join([[" ".join(["".join(w[ord(p)-35]) for p in k]) for k in o.split("!")][ord(m)-35] for m in l])
share|improve this answer
    
I think this is incomplete; it seems to miss the first two paragraphs –  w0lf Jun 1 '12 at 20:42
    
@w0lf. Thanks fixed. –  Matthew Snape Jun 1 '12 at 21:24

Ruby, 1014 bytes

I am just learning programming, so I'm not going to break any records here. But, this was a fun task.

def c
  wonts = ['give you up', 'let you down', 'run around and desert you', 'make you cry', 'say goodbye', 'tell a lie and hurt you']
  wonts.each do |w|
    puts "Never gonna #{w}"
  end
  b
end

def b
  puts "\n"
end

def never
  puts "Never gonna give, never gonna give
(Give you up)"
end

def v1
puts "We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy
I just wanna tell you how I'm feeling
Gotta make you understand"
b
end

def v2
  puts "We've known each other for so long
Your heart's been aching but
You're too shy to say it
Inside we both know what's been going on
We know the game and we're gonna play it"
end

def s1
puts "And if you ask me how I'm feeling
Don't tell me you're too blind to see"
end

def s2
b
puts "I just wanna tell you how I'm feeling
Gotta make you understand"
b
end

def soul
2.times {puts "(Ooh, give you up)"}
puts "(Ooh)"
never
puts "(Ooh)"
never
end

v1
c
v2
s1
b
c
c
soul
b
v2
s2
c
c
c
share|improve this answer

1054 1047 bytes, CoffeeScript

Uses a Burrows-Wheeler transform and simple run-length encoding and prints out the lyrics to the console.

c=d='';n=1
for b in "w3tol6nnd6e6seemn6us4oeegglu6d6ou6wnm3rrsAeet,,a10nnr22eer18y6r3euud7y4IIe3uhhea12o3a8kl,,eg3hhyaaea12o5drroa6taaw3mtsyyde3u12tteeddswwufe6t6lle13t12I4e3u3t5nnee/6p4h4e4)3/utuedudu)uItg3/ytt/6))p6u6n6y6e6nn//efttgg/3((/4 5/40(4//|/8n16 6n6ttn22ee  m8gg 15ttrww 7ee h3s6llss 9d6a4 7n25o6iinn 6l 7i6mmwwhhrrmvWWvrhr3ddk8v10mwwW3v4ey6v  hhsf3b4e3t9e4mhhv40hgdds6ld6gl6N8nnN30io 7n10  n 64ttcco4w3t3  t3cctt 9s4l6 lhhkool3hh 4mgGgGg10  sa8n 7l10ppuu 12be9ue3 3o'4 8aa  tmoeeu6weedow6oon44u6a12Aaia4uu  i8ooaio42aa k7IIeados3t4oono6 O4ggrcD  llg42t3g6ffbb 3GGy15Yy12YyYYy11wr6YYylh3n7d6u10  e43uuoot'6fa6e3u5e6uaa 7c6e'4ir' 9e6  nna 3uurr a''esse6r14aani4uuttss 9oo 3o3  i 7so46rfr6o6 12ooh6jjbbgo''i14oe40o9 9o7 a10nhhur6b6 40u"
 x=b.charCodeAt 0
 if x<48||x>57
  d+=c for r in [1..n]
  c=b;n=1
 else if n==1
  n=b
 else
  n+=b
d+=c for r in [1..n]
t=[];l=d.length
for i in [1..l]
 t[j]=d[j]+(t[j] ? '') for j in [0...l]
 t.sort()
for i in [0...l]
 if t[i][l-1]=='|'
  console.log t[i][0..-2].replace /\//g,"\n"
share|improve this answer

JavaScript, 1428 1451 883* characters

Definitely not the shortest solution, but here it goes.

d="(Give you up):(Ooh):(Ooh, give you up):A full commitment's what I'm thinking of:And if you ask me how I'm feeling:Don't tell me you're too blind to see:Gotta make you understand:I just wanna tell you how I'm feeling:Inside we both know what's been going on:Never gonna give you up:Never gonna give, never gonna give:Never gonna let you down:Never gonna make you cry:Never gonna run around and desert you:Never gonna say goodbye:Never gonna tell a lie and hurt you:We know the game and we're gonna play it:We're no strangers to love:We've know each other for so long:We've known each other for so long:You know the rules and so do I:You wouldn't get this from any other guy:Your heart's been aching but:You're too shy to say it:".split(/:/);"hk3l76o9bdcefojmn8g45o9bdcefo9bdcefo221a01a0oimn8go76o9bdcefo9bdcefo9bdcef".split("").map(function(i){return d[parseInt(i,25)]}).join("\n")

Solution logic is pretty simple:

d="dictionary:of:uniqe:lines".split("/:/");
"012345".split("").map(function(i){return d[parseInt(i,25)]}).join("\n")

*Of course the solution becomes a lot shorter when taking unique lines instead of unique words.

share|improve this answer

Delphi/Pascal. Some issues with casing though. WIP. 1018 characters, including unnecessary whitespace.

program X;
{$APPTYPE CONSOLE}
const
 w:array[32..114] of string = (#10,'(Give','(Ooh)','(Ooh,','A','aching','and','any','around','ask','been','blind','both','but','commitment''s','cry','desert','do','Don''t','down','each','feeling','for','from','full','game','get','give','give,','going','gonna','goodbye','Gotta','guy','heart''s','how','hurt','I','if','I''m','Inside','it','just','know','known','let','lie','long','love','make','me','Never','no','of','on','other','play','rules','run','say','see','shy','so','strangers','tell','the','thinking','this','to','too','understand','up','up)','wanna','we','We''re','We''ve','what','what''s','wouldn''t','You','Your','You''re');
 c='S>;pg S>Mp3 S>Z(&0p S>Qp/ S>[? S>`$N&Dp  ';
 x='kT_dP pKaY&^1E $8.mGbU po:c7''WA EJi`pCG5 @Qpf  '+c+'lL4W6^O qB*%- re]d[I Hj,Kn*=V jKa9&k>XI &Fp)RCG5 2`Rre+d\  '+c+c+  '#;ph #;ph " S><S>; !ph " S><S>; !ph  lK4W6^O qB*%- re]d[I Hj,Kn*=V jKa9&k>XI  EJi`pCG5 @Qpf  '+c+c+c;
var i: Integer;
begin
 for i := 1 to Length(x) do
  write(w[Ord(x[i])]+' ');
end.
share|improve this answer

Java - 903 Bytes

Here is my Java take at it, no compression algorithms used, just a dictionary.

In a single line:

class R {static String n(String w){return "Never gonna "+w+"\n";}public static void main(String[] args){String d[]={"(Ooh, give you up)\n","(Ooh)\n",n("give you up")+n("let you down")+n("run around and desert you")+n("make you cry")+n("say goodbye")+n("tell a lie and hurt you")+"\n","(Give you up)\n",n("give, never gonna give"),"We've known each other for so long\nYour heart's been aching but\nYou're too shy to say it\nInside we both know what's been going on\nWe know the game and we're gonna play it\n","\nI just wanna tell you how I'm feeling\nGotta make you understand\n\n","We're no strangers to love\nYou know the rules and so do I\nA full commitment's what I'm thinking of\nYou wouldn't get this from any other guy","And if you ask me how I'm feeling\nDon't tell me you're too blind to see\n\n","\n"};int n[]={7,6,2,5,8,2,2,0,0,1,4,3,1,4,3,9,5,6,2,2,2};for(int i:n){System.out.print(d[i]);}}}

And pretty printed for readability

class R {
    static String n(String w) {
        return "Never gonna " + w + "\n";
    }

    public static void main(String[] args) {
        String d[] = {"(Ooh, give you up)\n",
                "(Ooh)\n",
                n("give you up") +
                        n("let you down") +
                        n("run around and desert you") +
                        n("make you cry") +
                        n("say goodbye") +
                        n("tell a lie and hurt you") +
                        "\n",
                "(Give you up)\n",
                n("give, never gonna give"),
                "We've known each other for so long\nYour heart's been aching but\nYou're too shy to say it\nInside we both know what's been going on\nWe know the game and we're gonna play it\n",
                "\nI just wanna tell you how I'm feeling\nGotta make you understand\n\n",
                "We're no strangers to love\nYou know the rules and so do I\nA full commitment's what I'm thinking of\nYou wouldn't get this from any other guy",
                "And if you ask me how I'm feeling\nDon't tell me you're too blind to see\n\n",
                "\n"
        };
        int n[] = {7, 6, 2, 5, 8, 2, 2, 0, 0, 1, 4, 3, 1, 4, 3, 9, 5, 6, 2, 2, 2};
        for (int i : n) {
            System.out.print(d[i]);
        }
    }
}
share|improve this answer

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.