We're no strangers to code golf, you know the rules, and so do I



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


  • Must output the lyrics exactly as they appear in the above pastebin*. Here's the raw dump: http://pastebin.com/raw/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, Peter Taylor's GolfScript answer is winning, so get cracking on some improvements if you want to beat him! :)

*There is a typo in the Pastebin (line 46, "know" should be "known"). You may either replicate it or not at your discretion.


Posted 2012-05-28T23:18:56.757

Reputation: 4 082

I think there may be a typo in the pastebin text. In the second to last paragraph before the final chorus (first line): "We've know each other for so long" I think should be "We've known each other for so long" – Cristian Lupascu – 2012-05-29T06:55:53.963

4@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 – 2012-05-29T07:30:35.077

1I would recommend adding a list of languages to be used (as a link to a list of popular or sth) because I have seen people w defining a language that prints "hello world" with 0 bytes of code :) – naugtur – 2012-06-01T11:45:22.400

Do you count newlines? – Josh Smeaton – 2012-06-01T14:36:06.253

Maybe next time it would be more fun to define "shortest" as "minimum lines of code", "minimum number of characters" or something like this. When people start hacking away at character encoding level, then the result is just not readable so easily, thus destroying some degree of fun. – erikbwork – 2012-06-01T15:11:40.597

Lines of code is pointless, because in most languages you can just stick everything into one line. If your solution is ASCII, count the characters excluding newlines. If your solution is non-ASCII (i.e. it uses character encoding to shorten the result) you count the bytes. – Polynomial – 2012-06-01T15:47:45.967

1026k+ views in just 3 days. WOW... – Gaffi – 2012-06-01T21:30:26.437

4It seems a bit counter-intuitive to have the source code of a non-Unicode-based language be measured as if it were UTF-8-encoded. But it's your problem, so you call the shots! – breadbox – 2012-06-02T02:45:04.950

9How in the world did this generate so many views and votes? Whatever he did, I'm going to reverse engineer it. – PhiNotPi – 2012-06-02T21:27:32.143

41@PhiNotPi Good luck reverse engineering "Jeff Atwood tweeting you". – breadbox – 2012-06-03T08:04:52.863


@PhiNotPi It looks like it was posted on Hacker News.

– Gareth – 2012-06-03T08:22:19.380

3It got tweeted via the CodeGolf SE twitter account, then Jeff Atwood and Wrox Press tweeted it too. From there it got onto THN. I got a gold and two silver badges in the space of 5 minutes :) – Polynomial – 2012-06-03T11:24:14.487


I think Ed H.'s 555-byte solution is still the front-runner, actually.

– breadbox – 2012-06-07T07:47:25.767

@breadbox So it is! Missed that one. – Polynomial – 2012-06-07T08:23:04.693

There seems to be some confusion about scoring wrt newlines ... You say "If your solution is ASCII, count the characters excluding newlines", so wouldn't that make Ed.H's solution score 554? (His solution has 556 bytes including a newline at the end of each of its two lines of code.)

– r.e.s. – 2012-06-07T12:23:37.673

@r.e.s. I just copied the value from his post, I didn't manually check the length. You're right, it's 554, not 556. I've updated the question to reflect this. – Polynomial – 2012-06-07T12:28:23.517

Waaait a second. Newlines are not counted? If so, I can shave about 50 bytes off my solution with ease, so you might want to rethink that. – a sad dude – 2012-06-07T12:32:37.417

I'm talking about newlines that are part of code structure. You certainly can't ignore instances where you've used \n, or had newlines as part of the song's text. Also, I only see 14 newlines in your solution. – Polynomial – 2012-06-07T12:36:27.937

Oh, ok. Still, if, say, newlines in ruby/python are not counted, how about not counting semicolons in php? ) wouldn't it be simpler to just always count the bytes? – a sad dude – 2012-06-07T12:45:20.440


Also, I only see 14 newlines in your solution.

...and 30 "q"s, plus about 20 more saved by str_split. Which I could easily change to newlines (and newlines to "q"). Because newline is just a character like every other, why treat it differently? – a sad dude – 2012-06-07T12:49:51.227

If the newlines later become part of the output, they count towards the size of your code. – Polynomial – 2012-06-07T12:50:29.637

+1 for actually accepting the shortest solution on a [code-golf] question. :-) – Gareth – 2012-06-08T16:13:32.973

I'd like to see a seed answer. – MCMastery – 2016-10-02T21:58:10.107

1Never gonna give PPCG up, Never gonna let PPCG down, Never gonna turn around and desert PPCG – Matthew Roh – 2017-03-25T02:20:25.353

1https://www.youtube.com/watch?v=63qtYi1nwcs – Steadybox – 2017-03-27T18:59:58.007

You can technically just make an infinite loop that prints a letter each time around. Eventually, the song will be I. There somewhere – jeremy – 2013-12-27T23:09:27.543

9The restriction with UTF-8 makes no sense. What if my code is shorter when encoded as UTF-16 or as Latin-1? You should either count the number of bytes or the number of characters, but leave the encoding up to the author. – Timwi – 2014-01-25T00:22:01.333

1Update, 1st June 2012: You suck. :P But seriously, everyone disagrees with that restriction. – MD XF – 2018-03-09T02:10:54.117

I love that there are 42 gonna-s in the song – seadoggie01 – 2018-09-05T14:08:24.683

_A function or program is what I'm thinking of. You wouldn't get this on any other site. I just want to tell you how I'm golfing. Gotta make you understand. Never gonna beat Dennis. _ – Lyxal – 2020-01-22T09:43:58.897



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.

s="We; n7trangMsL8loT63Ke rules5s8d8I
AJull commit4nt'sChatFKink: of6CHldn'tRetKisJrom<ny@Ruy-/A= if?<sk 42DS'tLE 4?;Lo8bli=L7ee..
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|
(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.

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

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

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
(OohqeTrQqRSna q gqonqve"),"We; n7trangMsL8loT63Ke rules5s8d8I
AJull commit4nt'sChatFKink: of6CHldn'tRetKisJrom<ny@Ruy-/A= if?<sk 42DS'tLE 4?;Lo8bli=L7ee..

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

Ed H.

Posted 2012-05-28T23:18:56.757

Reputation: 956

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 – 2012-06-03T19:50:50.863

I find 555 bytes in your program (with no trailing newline). – r.e.s. – 2012-06-05T01:03:19.083

1The OP's scoring method is to exclude newline separators in ascii source code, so it seems this should score 554. – r.e.s. – 2012-06-07T12:35:07.597

Great solution! :) – Polynomial – 2012-06-08T15:55:21.903

Looks like the shortest decompression code was in PHP. Here's a 543 byte solution (my rules, using code snippets from "a sad dude") http://ideone.com/XoW5t

– Ed H. – 2012-06-09T17:38:58.353

I suggest putting the PHP solution in your answer. It's a pity if the shortest solution won't be shown, just because neither you nor "a sad dude" can claim full ownership. – ugoren – 2012-06-10T06:26:12.753

Kudos... I got to 641 in Python trying to automate the finding of which substrings to replace, and yours is 90 less than that! – Claudiu – 2014-11-18T06:18:30.987


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

Luca Spiller

Posted 2012-05-28T23:18:56.757

Reputation: 849

2I'm guessing you used some tool to compile this into whitespace? – evilcandybag – 2012-06-02T09:13:42.080

54+1 for creating the longest solution I've ever seen on CodeGolf. – Polynomial – 2012-06-03T11:27:34.967

7(+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. – 2012-06-03T16:56:01.130


Bash / Sed, 705 650 588 582 chars

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.


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
K know
@ay itM
U you
= I'm 
C go
2 to
z a
x w
- s
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

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/Z/ gonna /g;
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


Posted 2012-05-28T23:18:56.757

Reputation: 16 527

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 – 2012-05-30T16:11:57.740

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 – 2012-05-30T17:21:41.443

@breadbox, Cut&paste indeed brought this space. I removed it, saved 4 chars. With your & it makes 5. – ugoren – 2012-05-31T06:41:39.853

This is impressive. Only 179 more bytes than a pure gzip! – Polynomial – 2012-06-01T10:02:11.043

This is more like a contextual grammar :) AS for huffman codes - you can generate them outside and apply in the program, but you are operating on characters, not bits, so it can't change anything. – naugtur – 2012-06-01T12:57:24.447

@naugtur, Saying I can't do something like Huffman, I actually meant that I operate on characters. Without using the fact that a small subset of the 256 chars is used, it would be hard to close the gap with zip. – ugoren – 2012-06-02T09:54:52.037

Very impressive, even though execution generated some warnings. As a sed-newbie, I just don't see how you actually constructed your program, which looks impossibly complex ;o)) Would you consider adding a bit more explanation? (Maybe an example of how it would look if the song were just a few words?) – r.e.s. – 2012-06-03T13:17:23.240

2@r.e.s., added a better explanation. – ugoren – 2012-06-03T13:40:45.567

1Thanks, esp for the "more detailed explanation" link ;o)))) – r.e.s. – 2012-06-03T13:46:02.567

One more byte to save: the semicolon in s#$#/g;# is redundant with the newlines. – breadbox – 2012-06-03T19:16:23.617

nice case of human driven compression. humans can replace all the silicon after all, we just need more humans – None – 2012-06-03T23:30:37.853

@RocketSurgeon MORE!? :P – kaoD – 2012-06-05T03:27:27.107

@breadbox, right about ;, thanks. – ugoren – 2012-06-05T11:51:34.930


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


Teddy Cross

Posted 2012-05-28T23:18:56.757

Reputation: 491

1Really brilliant. – Jim Blackler – 2012-06-01T21:10:34.340

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 – 2012-06-02T14:53:09.440

Very nice. Though it doesn't actually print the song (at least when tested with www.ideone.com). – ugoren – 2012-06-03T07:05:17.650

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 – 2012-06-03T07:10:46.630

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. – Teddy Cross – 2012-06-03T17:10:19.797

How did you make this code? – Rich Bradshaw – 2012-06-03T17:12:51.220

To make it work everywhere, you can just add this after the for() part (before the e=): if(+i==i) – Ry- – 2012-06-12T04:13:34.027

Can we have the tutorial? (about did you make this work) – Mars Robertson – 2014-01-02T13:40:52.683

1using with(f.split(g[i]))f=join(pop()) in the for..in loop saves a byte – Oki – 2017-08-21T16:04:46.600


@Spedwards likely done with this program from js1k http://js1k.com/2012-love/demo/1189

– Oki – 2017-08-21T16:07:01.667

3I don't even have the slightest idea on how this works... Can we get an explanation? – Spedwards – 2014-06-18T11:57:20.537


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 ");


Posted 2012-05-28T23:18:56.757

Reputation: 321

2+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. – Cristian Lupascu – 2012-05-30T12:56:39.167

3Also: 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. – Cristian Lupascu – 2012-05-30T13:01:46.243

You can shave off a lot of characters by putting a leading space on ! and taking it out of everywhere else. – Stackstuck – 2019-03-07T13:33:45.010


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
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
8g68let4 down8runKrouLqdesert48Pcry8sayCoodbye8tUK lieqhurt40WeJ nEstrangersxEloMz9xhe rulesqsEdEI
A full commitment'sThat I'mxhinkH ofzTouldn'tCetxhis fromKnyRCuy31AL if4Ksk me7Don'txU me4JxoEbliLxEsee00
for s in'UTSRQPMLKJHFECBzxq9876543210':a,b=d.split(s,1);d=b.replace(s,a)
print d


Posted 2012-05-28T23:18:56.757

Reputation: 171

2(+1) Very nice. BTW, I find 588 bytes with no trailing newline. – r.e.s. – 2012-06-04T04:21:08.513


BrainFuck - 9905


Pretty sure I can get a bit better by tuning it, but This is pretty good for now. Assuming you have no problem with this being much large than the original text.


Posted 2012-05-28T23:18:56.757

Reputation: 4 373

1I think you can golf a little bit by using Unary instead. – Roman Gräf – 2017-07-19T13:32:18.920

This seems golfable... – MilkyWay90 – 2019-05-24T01:30:49.147


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#^
"""/:("!#$%&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.

Rex Kerr

Posted 2012-05-28T23:18:56.757

Reputation: 903

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 – 2012-05-31T20:25:40.097

@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 – 2012-05-31T20:48:13.910

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 – 2012-06-10T16:42:07.667


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)4, n^F
(Ooh)4, n^F

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!
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:


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
'þœ 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Äð(

° 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:



Posted 2012-05-28T23:18:56.757

Reputation: 6 893

Your character count appears to be 644, not 724. Am I missing something? – Cristian Lupascu – 2012-05-29T07:36:05.943

1@w0lf It's 724 bytes, which translates to 644 UTF-8 characters. I'm not sure which one counts, really. – Polynomial – 2012-05-29T08:29:48.903

1@Polynomial I don't know either, but hopefully someone will know and enlighten us. – Cristian Lupascu – 2012-05-29T08:34:46.447

5In 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 – 2012-05-29T17:53:53.793

11This looks more readable than the average Perl script! – Agos – 2012-06-01T09:56:53.580

@breadbox In cases where non-ASCII encoding is used to reduce size, I think bytes should be the counter. In ASCII, we should just count characters excluding newlines. – Polynomial – 2012-06-01T15:56:29.420

@Polynomial I'm not using non-ASCII encoding to reduce size. Perl still treats each non-ASCII character as a single character. Anyway, if you're going to count bytes and not characters in Unicode text, then you need to state whether you're counting bytes in UCS-2 or UTF-8, or something else, because they each give completely different byte counts. – breadbox – 2012-06-01T17:22:06.307

@breadbox UTF-8, since that's what SE uses. – Polynomial – 2012-06-01T17:25:26.553

2(You know, I wouldn't complain if APL was handicapped by having to count bytes instead of characters....) – breadbox – 2012-06-02T00:21:15.380


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


Posted 2012-05-28T23:18:56.757

Reputation: 1 623

1*p>>4^3?putchar(*p):e(r[*p-48]) – ugoren – 2012-06-04T18:58:58.740

ah! thank you, now included in the code. – baby-rabbit – 2012-06-04T22:29:41.473

Also, the "\'" translation isn't needed. "We're" is a valid string. ing is a better candidate. – ugoren – 2012-06-05T06:30:09.177

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 – 2012-06-06T06:31:10.147

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 – 2012-06-06T06:42:29.053

Thank you for the tips! This is my first time golfing, time wasting but educational :-) – baby-rabbit – 2012-06-07T00:17:18.950

I didn't try this one with C, because I thought you can't write a good solution without good string manipulation tools. Well, you can, and you wrote a good solution without knowing the basic golfing tricks. Two more things: c,k don't need int, and k=!putchar(c-k). – ugoren – 2012-06-07T07:00:09.257

Also you can use c-48>48U. Another char can be saved, as I said before, by using tab instead of & for separation. You'll have to use real tabs, not \t in the string, which is ugly, but you'll be able to compare with 9, not 38. – ugoren – 2012-06-07T07:51:55.013

tab is tempting but for one byte it feels too ugly :P – baby-rabbit – 2012-06-07T20:24:21.963

This is really cool. I'm trying to understand it How did you generate the optimal list of substrings? – 2501 – 2017-05-10T16:58:08.043

It may be possible to use int* (sorry, no backticks on this device) instead of char* to golf one byte. – None – 2018-08-07T08:21:01.127


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
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
        return sorted(patts, key=lambda k: -k[2])[0]
        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)
        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
        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)
            dc = decompress(sm)
            tested[l,n] = (len(sm), len(sm)/float(len(org)), 'err')
        tested[l,n] = (len(sm), len(sm)/float(len(org)), dc==org)

        if len(sm) < minfound:
            minfound = len(sm)
            print '~~~~~~~!!!!!!! New Minimum !!!!!!!~~~~'
    return tested

if __name__ == '__main__':
    import sys
    split = False
        if sys.argv[2] == 'p':
            pretty = True
        pretty = False
    org = open(sys.argv[1]).read()
    sm = compress(org,lenw=l,numw=n)
    print 'COMPRESSED -->'
    print sm, len(sm)
    print len(sm)/float(len(org))
    print 'TRYING TO REVERT -->'
    dc = decompress(sm)
    #print dc
    print dc==org


Posted 2012-05-28T23:18:56.757

Reputation: 509


  • 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 – 2012-06-03T06:39:09.040

    126 less chars, this is fun – Optimus – 2012-06-03T21:24:26.407

    Your program seems to be only 587 bytes long (unix formatting) -- one less than the several answers that are 588. – r.e.s. – 2012-06-07T02:46:56.547

    thanks for pointing it out, actually my vim adds endline to the end of python file – Optimus – 2012-06-07T07:46:52.523

    I added some Info on how I am getting my solution, I must be doing something wrong somewhere, minimum gets stuck at some point but obviously Ed. H did better so there is scope for improvement. – Optimus – 2012-06-07T09:01:32.530

    I think I found the source of your 1-byte advantage: you omitted 1 newline from the text of the song. The text should be "We know the game and we're gonna play it\n\nI just wanna tell you how I'm feeling", with two newlines in there. – r.e.s. – 2012-06-07T11:58:44.600

    yup, there is was a mistake in my local lyrics file, I will correct it. – Optimus – 2012-06-07T16:07:19.053

    @r.e.s. I corrected the code with one char less :) turns out missing a space wasn't really a source of advantage – Optimus – 2012-06-07T21:30:13.987

    I believe you can compress your rules (and save 4 characters) by removing the useless N and O substitutions. As an example, you want to replace O => O and H => "-(Ooh" with the single rule O => "-(Ooh". To do this and maintain contiguous ASCII character substitutions, you'll have to reorder your rules. See my comment on ugoren's Python solution for more reordering details. – Ed H. – 2012-06-08T06:26:26.440

    Can you explain how you determined "the most profitable replacement" in your initial greedy search that produced a solution 10 bytes longer than your manual search? I'm guessing your metric was not the best one. The rules I got from a simple greedy search we're pretty good, though not optimal. I think the best "most profitable replacement" rule needs to compare the total ruleset size before the replacement with the ruleset size after the replacement. This includes the length of the current text + length of rules and the separator characters between the rules. – Ed H. – 2012-06-08T06:44:03.463

    "most profitable replacement" means phrase, on replacing which provides the maximum reduction in chars – Optimus – 2012-06-08T06:51:45.987

    it already includes all what you said, just the code and formula below are older, for last version of code. thanks for the tip I can see how that will chop off some chars. – Optimus – 2012-06-08T07:02:38.827

    If I understand your "most profitable replacement" strategy, you were optimizing for the rules that included the head replacement character (and did not assume contiguous ascii). My initial greedy search ranking assumed contiguous ascii, and did not count a head replacement character. I believe this corresponds to using (length-1)*count - length - 1. I suppose the overall ranking of any substitution would be the same though. – Ed H. – 2012-06-08T13:47:04.423

    yes exactly so, previously I had an additional head of 1 char as I had to specify the order of chars, I had some work so I did't yet try modifying the equation, I guess that's how your greedy algorithm got better results than mine. – Optimus – 2012-06-09T06:33:49.550

    @r.e.s. If you have some spare time could you please help me with question http://codegolf.stackexchange.com/questions/6309/list-of-first-n-prime-numbers-most-efficiently-and-in-shortest-code, it's the first CodeGolf problem I've ever posted, but I seems that I made scoring a little too complicated.

    – Optimus – 2012-06-11T08:57:01.400


    Malbolge, 12735 bytes


    Try it online.

    Generated using the tools here.

    a spaghetto

    Posted 2012-05-28T23:18:56.757

    Reputation: 10 647

    Woah! A Malbolge answer? Awesome! – MilkyWay90 – 2019-03-31T20:39:52.510


    JavaScript 666 Bytes

    Inspired by tkazec's solution.

    Check out the blog post I wrote about it, it contains all the sources and explains how I built that code.

    You can copy and paste the code into your browser's console. Or try it at http://jsfiddle.net/eikes/Sws4g/1/

    t="We're no strangers to love|YouSrules;so do I|A full commitment's what?think7f|You wouldn't get this from anyLguy^zQnqAnd if:ask me[Don'tEme yRblind=ee{HUH_]|Qq^{x<br>{zxz||xxZKVlet:downVrun around;deseBVMcryVsay goodbyeV8a liFhuB||q eachLfor so long|Your hearPaching but|YRshy=@Inside we bothCwhaPgo7n|WeSgamFwe'reJpl@_U]^|I just wannaEyou[Gotta Munderstand](Ooh)|Z, nX|(GU[ how?feeling|ZNXXTgiveV|NTUiveK)|TeverJSCthe Rou're too QWe've9Pt's been Mmake:L other K:upJ gonna H(Ooh, gFe;E 8C9 Brt you@ay it|? I'm = to s; and : you 9 know8tell 7ing o";c="|{zxq_^][ZXVUTSRQPMLKJHFECB@?=;:987".split("");while(l=c.pop()){t=t.split(l);t=t.join(t.pop())}document.write(t)


    Posted 2012-05-28T23:18:56.757

    Reputation: 221


    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.


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

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


    Posted 2012-05-28T23:18:56.757

    Reputation: 91


    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
    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
    And if$l ask me$g
    Don't tell me$l're too blind to see


    Posted 2012-05-28T23:18:56.757

    Reputation: 1 387

    1You could make this shorter by putting "You" and "you" into variables. – Polynomial – 2012-05-29T08:14:07.923

    @PeterTaylor, that's a typo thanks for brining to notice. – l0n3sh4rk – 2012-05-29T15:33:37.113

    @Polynomial, done! – l0n3sh4rk – 2012-05-29T16:00:05.150

    $s="Never gonna give... can be shortened with $n. – Mr. Llama – 2012-05-29T21:08:29.137

    1Suggest making "give" a variable as well. It's used in 5 places. – Glen Solsberry – 2012-06-01T12:21:04.070

    Make " and " a variable as well... – powtac – 2012-06-06T23:51:21.253

    Can we save some $ chars by using a Constant instead of a Variable? – powtac – 2012-06-06T23:59:40.050


    Python 2.7, 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
    And if you ask me{8}
    Don't tell me you're too blind to see
    {0}, {2})
    {0}, {2})
    %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('|'))

    Josh Smeaton

    Posted 2012-05-28T23:18:56.757

    Reputation: 181


    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
    A full commitment's3hat I'm2ink= ofF3qldn't get2is from6ny<guySUALifR6sk meMD0'tH5 meR8bliLtCsee
    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):
                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)
        if not done:
            snippet = best[1]
                lastname = name
                name = names.pop()
                while name in 'ADGION':
                    text = name + '_' + text
                    name = names.pop()
                while name in '?@':
                    text = '_' + text
                    name = names.pop()
                sys.stderr.write('Warning: out of names.\n')
                lastname = "0"
            text = snippet + '_' + text.replace(snippet, name)
    sys.stdout.write(name + text)
    sys.stdout.write('";$i=' + str(ord(lastname)) + ';eval"s/$1/$2/g"while s/(.)(.*?)_/chr($i++)/se;print')


    Posted 2012-05-28T23:18:56.757

    Reputation: 985

    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 – 2012-06-06T22:14:31.637

    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 – 2012-06-07T14:21:50.007

    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 – 2012-06-07T16:11:31.123

    @quasimodo not anymore you're not. Just wanted to say that once :P – Optimus – 2012-06-08T04:49:11.910

    Ah, there is the fifth byte, thank you, breadbox! Watch out Optimus! :) – quasimodo – 2012-06-08T10:17:23.400

    The search was distorted by overlapping pattern occurrences, fixing this got me 4 byte. – quasimodo – 2012-06-08T12:01:38.917

    Damn... But I still have some squeezing left to do. It really doesn't matter much, that a right answer has been selected, this is fun to do... – Optimus – 2012-06-09T06:44:53.003

    2Its 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 – 2012-06-09T09:51:09.823

    @quasimodo seriously, it did take a lot of time, and the more you compress your solution less chars are reduced per hour spent. Anyways, I think, CodeGolf SE could use more such questions that go viral (I think we need to thank Rick Astley for singing a 1870 character lyrics printable using only 556 bytes). – Optimus – 2012-06-10T20:09:22.183



    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)"
          q(s n "3, n62 3")
          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)))      


    Posted 2012-05-28T23:18:56.757

    Reputation: 1 233

    What's the minimal bytes version of this? – CalculatorFeline – 2016-05-17T15:54:02.617


    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}"
    def b
      puts "\n"
    def never
      puts "Never gonna give, never gonna give
    (Give you up)"
    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"
    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"
    def s1
    puts "And if you ask me how I'm feeling
    Don't tell me you're too blind to see"
    def s2
    puts "I just wanna tell you how I'm feeling
    Gotta make you understand"
    def soul
    2.times {puts "(Ooh, give you up)"}
    puts "(Ooh)"
    puts "(Ooh)"


    Posted 2012-05-28T23:18:56.757

    Reputation: 71

    2Some tips: Change every variable name to a one-character name, remove indentation and remove spaces around operators – TuxCrafting – 2016-06-22T12:39:40.880


    C# - 605 characters | T-SQL - 795 characters | C# - 732 characters | C# - 659 characters

    The inspiration for this came from the sed example. The only major change I made from that was making the lookups consecutive ASCII characters so they didn't have to be declared. Unfortunately, it is C#, so I don't know how to make it smaller. I took the same replace text and did the code in T-SQL using a temp table.

    var f='#';Debug.Print("HWe've0n each o=F forCo long5r hear+@ch>but5E<oChy<C1InsideBe bo=0Bha+;o>onHWe0 =e;ame7weE8pl1|HI justBanna :4*Gotta 2u?Fsta?%|H/93up/let3down/run@rou?7desFt4/2cry/say;oodbye/:@ lie7hurt4|(Ooh)/9,nevF89H(G.|'|(|)| how6feelingH|t's been|, |(Ooh,g.|ive3up)H|HNevF8| know|ay itH|make3|4 | you|HYou| I'm |@? |;onna |give|tell| g| to|th|ing |nd| a|A| w| s|D|'re|er|G|\n"
    .Split('|').Aggregate("WeE noCtrangFs< love50 =e rules7so do IHA full commitment'sBhat6=ink>of5Bouldn't;et =is from@ny o=F;uy$H#A? if3ask me*Don't : me4E<o bli?<Cee%%HH--&&#$%%",(x,t)=>x.Replace(f++.ToString(),t)));


    CREATE TABLE #t(i int IDENTITY(35,1),t varchar(1000) COLLATE Latin1_General_CS_AS) 
    DECLARE @s varchar(4000)
    INSERT #t SELECT ''We"ve0n each o=F forCo long5r hear+@ch>but5E<oChy<C1InsideBe bo=0Bha+;o>on
    We0 =e;ame7weE8pl1|
    I justBanna :4*Gotta 2u?Fsta?%|
    /93up/let3down/run@rou?7desFt4/2cry/say;oodbye/:@ lie7hurt4|(Ooh)/9,nevF89
    (G.|"|(|)| how6feeling
    |t"s been|, |(Ooh,g.|ive3up)
    NevF8| know|ay it
    |make3|4 | you|
    You| I"m |@? |;onna |give|tell| g| to|th|ing |nd| a|A| w| s|D|"re|er|G'''
    INSERT #t SELECT ''')
    SET @s = 'WeE noCtrangFs< love50 =e rules7so do I
    A full commitment''sBhat6=ink>of5Bouldn"t;et =is from@ny o=F;uy$
    #A? if3ask me*Don"t : me4E<o bli?<Cee%%
    SELECT @s = REPLACE(@s, CHAR(#t.i), #t.t) FROM #t
    PRINT @s

    C# - Second Try This was try at a different approach. The compression was done entirely by the computer seeking the best replacements. The lookups are sequential and ordered by size so there is no need for delimted lookup, however, the code to do the lookups was less efficient than I thought so it ended up costing 127 more characters overall! Live and learn.

    static void Main()
    var o="6Gn/tr7g0s,+lo-FJrules.Ds+d+}$z8ull commit9nKLtR1ink:ofF23ldn't4et1is8rom.nyUguy]Xn_zDifC.sk 9[\"5't,I 9CM+bliDt/;^^$N<N\\<X_]^^";
    for(char z='\0',y;z<12;z++)
    {y='_';for(int i=0,f=333,k=65;i<z;k=y-"'?MRTQNL@(} "[i++]){
    for(;y>"^]\\[ZVROB) y"[i];){
    o=o.Replace(y--.ToString(),"AWGINODY\n,&'()e o  tve a+ser,h wou gon{ean fmeH eeS)tCowaDr oti- y3nd $~P$#3'r*ingellQ1*t's2haGtoT%4ache-@V kn> }'mBC up$(!oh Ah0 g5na K b;n $$6'-QmakeC ay it$ h>R8;lH$<T)EgB% nPgB$(|$} just27na,IC[|Ata Yund0st7d^$EgSEle= d>nErun.r3D?des0=EYcryEsay4oodbyeEtI. li*?hur= eOUfo@s+l5gF@hearWO:butFM/hy,/Z}nsid*w*bAhQLWgo:5$6Jgam*?weGVplZ".Substring(f,k));
    if(y==' '){y='~';i++;}}}}

    3rd try at C#. This time I expiremented with \b,\r,\t characters. You can use \rN\n to replace the first character on the line with a capital N, but it didn't actually save characters. I created \b aliases to move the cursor back and then write over existing text. But none of this saved space and in the end I was still worse off than a simple search-and-replace strategy.

    static void Main()
        var f='*';
        Console.Write("C04EC0let8downEC0run arouKJdes>t8EC06cryEC0say goodbyeEC0tePa lie Jhurt8E|CWe'veQn each=for sLlongC7r hear?<achFbutC75HoLshyHLs;Inside we bothQ wha?<goFonCWe3ga@ Jwe51pl;|,|CI just wannaHell82CGotta 6und>stJC|(Ooh)C0:, 91:EC(4)R(GC|(Ooh, 4)C|91| gonna |how I'm feelF|QHhe |:8up|'re|make8|You| you |nev>|give|ay itC|been | oth> |er|t's |me|A|EC0|\n|D|RN|ing |G| t|I|aK|nd |o |n't |N|O|ll | know|\r"
            "We5 nLstrang>sHLloveC73rules JsLdLICA fuPcommit@n?what I'mHhinkFofC7 wouldMgetHhis from any=guy-*C+AKif8ask @ 2CDoMteP@8\b5HoLbliKtLseeC*C*CC//..+-*C*C*",

    Jason Hermann

    Posted 2012-05-28T23:18:56.757

    Reputation: 171

    I like the clever REPLACE approach, especially with the dynamic SQL, but there are lots of ways to golf that more: Use @ as the variable instead of @s, make it a permanent table t instead of #t (you don't have to clean up after yourself), get rid of the 29-character COLLATE statement and simply require it to be run on a server/database with the proper collation, use varchar(999) or varchar(max), tons of unnecessary white space around equals signs and commas, etc. – BradC – 2018-03-15T15:41:33.407

    587 - link is to pastbin due to comment length limitation. – dana – 2019-06-16T18:27:16.540


    PHP, 591 585 568 564 bytes

    82---")),'x z',' (I');

    a sad dude

    Posted 2012-05-28T23:18:56.757

    Reputation: 231

    I think you may be missing something in the code; it seems to cause an error: http://ideone.com/WxIpG

    – Cristian Lupascu – 2012-06-02T21:16:55.387

    This is PHP 5.4. For older versions replace [z=>xx] with array(z=>xx) (and get 590 bytes) – a sad dude – 2012-06-02T21:42:13.683

    yes, http://ideone.com/o8hdU works. Nice, +1!

    – Cristian Lupascu – 2012-06-03T07:09:51.093


    A shorter PHP solution (using rules from my ruby code): http://ideone.com/XoW5t

    – Ed H. – 2012-06-09T17:46:52.147

    Yeah, guess "LOWERCASE EVERYTHING!" was a bad idea after all ) nice! – a sad dude – 2012-06-11T07:42:49.907


    GolfScript (511 bytes)

    This uses a change of base to pack the bits in, so it includes characters which aren't in ASCII. However, it isn't appropriate to score those characters by their UTF-8 encoding because the interpreter treats the program as ISO-8859-1. For this reason I've specified the length in bytes rather than characters.

    Base-64 encoded:


    Hex dump (output from xxd):

    0000000: 278c 350d 3c24 a77d 7b5a f62a f3c0 8543  '.5.<$.}{Z.*...C
    0000010: 29b9 d9d2 0dcc 2dfa a1ba 2924 12ca 0866  ).....-...)$...f
    0000020: 591e ad52 fada 73ef d7b8 fc97 4361 2d9c  Y..R..s.....Ca-.
    0000030: 7489 66f8 b500 459d 70c2 9272 1838 5a81  t.f...E.p..r.8Z.
    0000040: 17e6 35a2 568c eb7c c992 2220 56a2 ffb7  ..5.V..|.." V...
    0000050: 0c01 e2ae 7024 f266 9918 9826 ffee 8806  ....p$.f...&....
    0000060: 4707 d1d5 d574 cfdc 043a 8205 a347 6e75  G....t...:...Gnu
    0000070: ece9 1119 9c59 c27b 5f50 9471 4b15 cf5e  .....Y.{_P.qK..^
    0000080: d272 61bb 4f64 9b4e 7a28 1452 0d8f 3ef2  .ra.Od.Nz(.R..>.
    0000090: d725 bd8b b93d 8854 ccfd a7d6 848e 00ff  .%...=.T........
    00000a0: 0baa a3a8 cf45 ecee 71f1 9083 5c5c be61  .....E..q...\\.a
    00000b0: 2c89 dc53 fa32 8269 8bf7 1a1e 25bd c7cc  ,..S.2.i....%...
    00000c0: 7649 5436 aa9e 406f ed30 356b 934a 5442  vIT6..@o.05k.JTB
    00000d0: 3cf9 0951 5c27 9b98 44b0 0fcd fc10 239b  <..Q\'..D.....#.
    00000e0: 1428 7cce ac16 6bc7 f840 0bd3 0f21 224f  .(|...k..@...!"O
    00000f0: 2804 0b3f 8754 dd8c b5e3 32ff 763a 20a0  (..?.T....2.v: .
    0000100: 1c64 1b50 cd44 ca0f 12dc 0721 9984 3f06  .d.P.D.....!..?.
    0000110: 842d 6b21 0937 52fa f17e cc8e 977a 2ec1  .-k!.7R..~...z..
    0000120: 2f96 ea56 15d9 74a1 aa3c 58c7 4b4f ab41  /..V..t..<X.KO.A
    0000130: f1d4 0d47 e082 dfc0 9081 9f57 f7e8 7249  ...G.......W..rI
    0000140: 6af4 85e6 a883 694b 87ab a13a b308 c2c9  j.....iK...:....
    0000150: 4298 9989 35e6 ee37 6ed7 1aa6 d617 ed4c  B...5..7n......L
    0000160: f12b fd5b 5e04 e0aa 288b 31e7 dea8 fbf6  .+.[^...(.1.....
    0000170: 5a19 18bf a298 e57b 2fe5 d9b9 d98b 867a  Z......{/......z
    0000180: 2fe4 d9b2 a52a ca3e 0f7e 17f8 2458 b0f5  /....*.>.~..$X..
    0000190: afe4 7017 df22 edb2 5a64 0681 239e 1f07  ..p.."..Zd..#...
    00001a0: 3296 508c bcbd bbaa dc35 f821 0ab6 ec9a  2.P......5.!....
    00001b0: e484 c8d6 8456 51ab 1349 d056 8a7d d705  .....VQ..I.V.}..
    00001c0: 078f 0161 16ed da7b aa88 8fd6 8b16 8a27  ...a...{.......'
    00001d0: 3235 3662 6173 6520 3135 3362 6173 655b  256base 153base[
    00001e0: 305d 2f28 3330 2c7b 5c5b 3124 295d 2f5c  0]/(30,{\[1$)]/\
    00001f0: 3224 3d2a 7d2f 5c2c 297b 2d7d 2b25 2b    2$=*}/\,){-}+%+

    As most of the best solutions, this uses a grammar-based approach with string splits and joins to expand the grammar. The grammar has 30 rules and was found by a greedy search.

    Peter Taylor

    Posted 2012-05-28T23:18:56.757

    Reputation: 41 901


    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(':'),


    Posted 2012-05-28T23:18:56.757

    Reputation: 61


    Golfscript, 708 702 699 691 bytes

    "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
    "And if you ask me how"i"
    Don't tell me you're too blind to see"
    "(Ooh, give you up)
    "g"give, never gonna give
    (Give you up)"++.n\_

    Cristian Lupascu

    Posted 2012-05-28T23:18:56.757

    Reputation: 8 369

    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 – 2012-05-30T09:49:08.017

    @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. – Cristian Lupascu – 2012-05-30T10:04:28.257

    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. – Cristian Lupascu – 2012-05-30T10:08:59.807

    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 – 2012-05-30T11:37:22.043

    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. – Cristian Lupascu – 2012-05-30T12:53:11.997


    Naive sh/echo - 810 bytes

    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"
    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"
    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"
    echo "And if$D ask me how I'm feeling
    Don't tell me$D're too blind to see"
    echo "
    (Ooh, g$B)
    (Ooh, g$B)
    N$C, n$C
    N$C, n$C
    echo "I just wanna tell$D how I'm feeling
    Gotta make$D understand"

    Mr. one-liner

    Posted 2012-05-28T23:18:56.757

    Reputation: 51


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

    Bobby Marinoff

    Posted 2012-05-28T23:18:56.757

    Reputation: 159


    Ruby, 741 678 657 627 619 bytes

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


    Posted 2012-05-28T23:18:56.757

    Reputation: 151


    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)-.//"
    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


    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.


    Posted 2012-05-28T23:18:56.757

    Reputation: 16 527

    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 – 2012-06-05T23:44:38.217

    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 – 2012-06-06T06:59:30.563

    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 – 2012-06-06T17:24:28.363

    @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 – 2012-06-06T20:09:12.530

    @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 – 2012-06-07T09:09:32.400

    You can probably reorder your character substitutions to get rid of useless N and O transformations. As an example "reordering", you currently have the rules K => " w" and L => " a". You could swap this to K => " a" and L => " w", as long as you also swap K's and L's in your original text, and in every substitution rule preceding those for K and L. The resulting output should be exactly the same. You probably will be able to apply swapping algorithms to eventually get a rule of the form O => "X(Ooh", and to remove the useless O => O rule. This saves 2 chars. Try to save 2 more with N. – Ed H. – 2012-06-08T06:09:54.750

    maintaining continuous ascii range is the real pain, and if you mess up something somewhere it is hard to debug and Ctrl-z is your only friend, I tried to not assign these redundant rules and got stuck in cyclic dependencies, now that i think of it, O => X(Ooh would not create such issue as Ooh is the only occurence of O. I'll try it out – Optimus – 2012-06-08T07:25:20.843

    Just as a point of comparison ... If we simply take Ed H.'s ruby solution, with one additional rule to substitute U for each newline, and convert it directly into the "python form" that you use above, the result is then a 567-byte python solution (vs. yours at 573 bytes).

    – r.e.s. – 2012-06-09T02:38:51.783

    I thought so, Ruby is giving some advantage to Ed H. – Optimus – 2012-06-09T06:26:47.597


    Java, 858 bytes

    interface a{static void main(String[]A){String b="I just wanna tell you how I'm feeling\nGotta make you understand\n\n",B="Never gonna give you up\nNever gonna let you down\nNever gonna run around and desert you\nNever gonna make you cry\nNever gonna say goodbye\nNever gonna tell a lie and hurt you\n\n",c="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",C="(Ooh, give you up)\n",d="(Ooh)\nNever gonna give, never gonna give\n(Give you up)\n";System.out.print("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\n"+b+B+c+"And if you ask me how I'm feeling\nDon't tell me you're too blind to see\n\n"+B+B+C+C+d+d+"\n"+c+"\n"+b+B+B+B);}}

    Wow. I didn't really think I could compress this hard.

    Ungolfed In a human-readable form:

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


    Posted 2012-05-28T23:18:56.757

    Reputation: 1 242

    I've beaten 14 answers with this. Am I getting really good at golfing in Java, or is it just because this song's lyrics are surprisingly easy to compress? – user8397947 – 2016-06-22T00:15:23.627

    Can't you assign the variables like String a = "1", b = "2"; instead of the way above? Saves a few bytes :P – Mario Ishac – 2016-06-23T02:18:49.377

    @MarDev I created the strings like that in the golfed program. However, doing so hurts the readability, so I did them like String foo; String bar; when ungolfing. – user8397947 – 2016-06-23T23:29:21.063

    All those "Never gonna" could be optimized, too by extracting it into a variable – masterX244 – 2016-12-13T08:48:51.550

    Sorry, I just had to beat it! – Olivier Grégoire – 2019-02-12T12:51:30.343


    ///, 585 bytes

    /?/ve//>/'re//=/ing //</ other //;/
    We'?3//:/o //9/
    (Ooh//8/t's been //7/
    You//6/ t//5/ and //4/ gonna //3/ know//2/ how I'm feeling
    //1/i?- up//-/ you//&/1)9)#gi?, ne?r4gi?
    I just wanna6ell-2Gotta make- understand!//#/
    Ne?r4//"/ each<for s:long7r hear8ach=but7>6o:shy6:say it
    Inside we both3 wha8go=on
    We36he game5we>4play it
    #g1#let- down#run around5desert-#make- cry#say goodbye#tell a lie5hurt-/We> n:strangers6:lo?736he rules5s:d:I
    A full commitment's what I'm6hink=of7 wouldn't get6his from any<guy%;n"And if- ask me2Don't6ell me->6o:blind6:see!!
    9, g1)9, g&&1);"%!!

    Try it online!

    Conor O'Brien

    Posted 2012-05-28T23:18:56.757

    Reputation: 36 228


    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:

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


    Posted 2012-05-28T23:18:56.757

    Reputation: 901


    CoffeeScript, 1054 1047 bytes

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

    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]
     else if n==1
    d+=c for r in [1..n]
    for i in [1..l]
     t[j]=d[j]+(t[j] ? '') for j in [0...l]
    for i in [0...l]
     if t[i][l-1]=='|'
      console.log t[i][0..-2].replace /\//g,"\n"

    Ian Cooper

    Posted 2012-05-28T23:18:56.757

    Reputation: 41


    Befunge-93, 1760 1476 1434 1329 1326 1323 bytes

    >9#*9#5*#24#p9#0*#11#-+#<+00p57*1-10p"vv#"56+6*9p56+6*8p89*4+8p >
    <v"tell a lie and hurt you"*25
    <vp30"<say goodbye"*25  #
     vp40"<make you cry"*25
     vp50"<run around and desert you"*25
     vp60"<let you down"*25 #
     vp70"vgive you up"*25
    ^>" annog reveN"       #^   #1 #<
    >"^ ":::03p04p05p06p07p10g:03g`#^_v$
    v5"Gotta make you understand":*25$<
    >2*"gnileef m'I woh uoy llet annaw tsuj I"25*:"ti yalp an#"65+6v^ <p01*48p<
    v"what's been going on"*52"We know the game and we're gon"p*53*<
    >" wonk htob ew edisnI"25*"ti yas ot yhs oot er'uoY"25*"tub gnih"v
     v*52"We've know each other for so long"*52"Your heart's been ac"<#
    v>25*")pu uoy eviG("25*"evig annog reven ,evig annog reveN"25*")hoO("
    >52*")pu uoy evig ,hoO("52*")pu uoy evig ,hoO("25*">"57*2-:10p1+8p^>65+6*8^
    v"e how I'm feeling"*25"Don't tell me you're too blind to see":*25<^">"*52<
    >"m ksa uoy fi dnA"25*"ti yalp annog er'ew dna emag eht wonk eW"52v>"v'eW"^
    v"too shy to say it"*25"Inside we both know what's been going on"*<^"e kn"<
    >" er'uoY"25*"tub gnihca neeb s'traeh ruoY"25*"gnol os rof rehto hcae nwo"^
    v52"I just wanna tell you how I'm feeling"*52"Gotta make you understand":*52<
    >*"yug rehto yna morf siht teg t'ndluow uoY"25*"fo gnikniht m'I tahw s'tnemtim"v
    v"We're no strangers to love"*52"You know the rules and so do I"*52"A full com"<

    Try it online!

    Golfed 284 bytes by removing Whitespace that I used in my previous attempt

    Golfed 42 bytes by moving a few pointers around.

    Golfed 105 bytes by using the p Instruction more often.

    Golfed 3 bytes by moving p01*48p< 3 lines up.

    Golfed 3 bytes by using the full length on the last 2 lines


    Posted 2012-05-28T23:18:56.757

    Reputation: 95


    JavaScript REPL, 577 559 bytes

    for(_=` w} a|th{erzndo ive're
    (Ooh I'm telling  t youmake ay it
    You know gonna  o{z | , g tot's been  {e 	evz up howfeeling
    N))g, ng
    glet downrun|roudesztcrysay goodbye| liehurt
    I just}anna Gotta uzsta
    We'ven eachfor slongr hearachbutshysInside}e bo{}hagoon
    We	gameweplWe nstrangzslove	rulessdI
    A full commitment's}hat{inkof}ouldn't get {is from|nyguyA if|sk meDon't  meblisee
    ))`;G=/[^\n^ -y]/.exec(_);)with(_.split(G))_=join(shift())

    Playing around with http://siorki.github.io/regPack.html settings

    Alex Pearson

    Posted 2012-05-28T23:18:56.757

    Reputation: 31

    5Welcome to Code Golf! – Dennis – 2019-06-16T01:58:12.740


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

    program X;
     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;
     for i := 1 to Length(x) do
      write(w[Ord(x[i])]+' ');


    Posted 2012-05-28T23:18:56.757

    Reputation: 131


    Python 2.7, 845 bytes

    Encodes words and then lines as ASCII characters.

    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])

    Matthew Snape

    Posted 2012-05-28T23:18:56.757

    Reputation: 131

    I think this is incomplete; it seems to miss the first two paragraphs – Cristian Lupascu – 2012-06-01T20:42:13.070


    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",
                    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") +
                    "(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",
            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) {


    Posted 2012-05-28T23:18:56.757

    Reputation: 131


    Ruby (549) binary chars

    I recently found that you can enter arbitrary binary characters (including those with value between 128 and 255) in ruby strings, as long as you follow some simple ruby escaping rules. Packing information into binary enables more efficient compression. Unfortunately, display of the "code", when written in binary, is problematic; thus, I created a generic program that reads in an existing ruby text program (assumed to not use chars with value > 127), and creates a secondary ruby source code that does exactly the same thing. This secondary code uses one long string with binary characters in it, and can be shorter than the original, in terms of number of bytes.

    Here is the source "code-packer.rb"; it transforms input ruby source code into equivalent "compressed" output ruby source code. All it really does is binary packing of the original source code string, along with printing code for binary unpacking of the binary string.

    Addendum: It appears that the original code-packer produces code that does not represent valid UTF-8 encoded binary strings, and thus is technically invalid according to the rules. To make it valid, we must use only character values up to 128. I recently read the UTF-8 encoding rules, and trying to use all 8 bits and generate UTF-encoded strings is not fruitful because most binary strings (over half of all possibly binary strings of any given length) will not represent valid UTF-8 encodings. So using straight up 7-bit ascii code is more efficient. I've modified the code-packer code below to produce only unreadable 7-bit ascii strings by replacing "256" with "128" and "<<8" with "<<7". This makes the packing compression idea not worthwhile for small programs (< 700 or so bytes), although it does still reduce Actven's 1000+ byte solution down to 937 bytes.

    #!/usr/bin/env ruby
    # This program takes a ruby file as input
    # and outputs an equivalent ruby file as output that
    # is functionally equivalent, but "compressed". 
    # Compression is done by creating a string representing the original program
    # which contains unprintable characters (including chars with value between 128 and 255)
    # The string is just a binary packed version of the input program text.
    # the "decompression" algorithm for the string is written in ruby as part of the output, 
    # along with an eval on the decompressed string. 
    # NOTE: assumes input file doesn't contain any unprintable chars with value > 126, otherwise this will fail.
    DEBUG=false # turn on debug to produce larger code that uses code sequences for the unprintable characters, 
             # and prints debugging information, and ruby code instead of executing it.
    # returns array of frequency counts for str
    def frequency_count(str)
      freq= Array.new(127,0)
      str.bytes {|b| freq[b]+=1}
    # figure out an appropriate contiguous
    # range of characters (via ASCII) to use for representing str. 
    # returns 
    #  1) forward hash of chars, when applied to str, give only chars in the range
    #  2) backward hash of chars for undoing #1
    #  3) start character of range
    #  4) length of range
    def translate_range(str)
      freq = frequency_count(str)
      forward_hash = {}
      backward_hash = {}
      left_index = 0
      right_index = 126
      # ignore unused top range
      while right_index > 0 && freq[right_index] == 0
        right_index -= 1
      if right_index == -1
        raise "Error: empty input string"
      last_char_index = right_index
      # figure out chars to swap to get contiguous range
      # we want to minimize number of swaps, so this
      # naive approach won't always yield the best results.
      while left_index < right_index do
        if freq[left_index] == 0
           left_index += 1
        if freq[right_index] > 0
           right_index -= 1
        # found char on left that can move to empty spot on right
        forward_hash[left_index] = right_index
        backward_hash[right_index] = left_index
        freq[right_index] = 1 # mark it as filled.
        left_index +=1
        right_index -=1
      while freq[left_index]== 0
         left_index +=1
      [forward_hash, backward_hash, left_index, last_char_index - left_index + 1]
    # translates text into big num of given base, assuming all chars in string
    # are in range start_char..(start_char+base-1)
    def text_to_num (str, start_char, base)
       num = 0
       if (str[0] == start_char)
         raise "Sorry.. I can't handle strings that start with #{start_char.chr}"
       str.reverse.bytes {|x| num = num * base + (x - start_char)}
    # translates back from num to text. 
    def num_to_text (num, start_char, base)
       text = ""
       while num > 0 do
          text += (num % base + start_char).chr
          num /= base
    # translates from packed num string to original string, without translation part
    # will be output into code.. present here for testing.
    def packed_num_decode(str, start_char, base)
        while m>0 ; t+=(m%base+start_char).chr;m/=base end
    # takes a string used for input into translate, and escapes
    # chars with special meaning (^ at beginning, '-' between two chars, backslash)
    def tr_escapes(str)
       str.sub("\\","\\\\\\\\").sub(/^\^/,"\\^").sub(/(.)-(.)/m, "\\1\\-\\2")
    # takes a binary string, and escapes out characters problematic
    # when writing the string within single quotes. 
    # this includes ' and \.
    def packed_string_escapes(str)
      chars_to_escape = "\\\'"
      escaped_str = ""
      str.bytes {|b| if chars_to_escape.include?(b.chr) 
           escaped_str += "\\" + b.chr
           escaped_str += b.chr
    #======== Main program ========
    if (ARGV.length != 2)
       puts "Usage: #{__FILE__} <input program> <output program>"
    inputfile = ARGV[0] 
    outputfile = ARGV[1]
    inputtext = File.read(inputfile)
    input_info = translate_range(inputtext)
    from = ""
    to = ""
    input_info[0].each_pair {|x,y| from += x.chr ; to += y.chr }
    input_mod = inputtext.tr(tr_escapes(from), tr_escapes(to))
    input_num = text_to_num(input_mod, input_info[2], input_info[3])
    packed_num = num_to_text(input_num,0,128).reverse # do reverse so decompression code doesn't have to do it.
    if (DEBUG) then 
       packed_num_with_quotes = packed_num.inspect
       operation = "puts \"t=\#\{t.inspect\}\";puts"
       packed_num_with_quotes = "'" +  packed_string_escapes(packed_num) + "'"
       operation = "eval"
    start_char = input_info[2]
    base = input_info[3]
    from = ""
    to = ""
    input_info[1].each_pair {|x,y| from += x.chr ; to += y.chr }
    from_str = tr_escapes(from).inspect
    to_str = tr_escapes(to).inspect
    File.open(outputfile, "w+") {|f|f.puts("#{pretext}m=0;#{packed_num_with_quotes}.bytes{|x|m<<=7;m+=x};" +
                  "t=\"\";while m>0;t+=(m%#{base}+#{start_char}).chr;m/=#{base} end;" +
                  "#{operation} t.tr(#{from_str},#{to_str})")}

    Although the above can be applied to any ruby code (and could be modified to work with other languages), I've applied it to the following short 556 char solution:

    puts"W> n:trangMsL;loT96Ke rules8s;d;I
    AJull commit7nt'sHhatVKink= of9HXldn'tRetKisJrom?nyERuy02A@ ifC?sk 75DS'tLU 7C>Lo;bli@L:ee11
    I justHannaLUC5Gotta Bu@Msta@1|
    Ng4NletC downNrun?rX@8desMtCNBcryNsayRoodbyeNtU? lie8hurtC|
    W'T6n eachEJor s;lSg9r hear<?ch= but9>Lo:hyL:FInsideHe both6Hha<Ro= S
    W6KeRa78we>QplF|4)O)NgiT, nPgiT
    (G|iTC up| howVJeel=
    | know|me|?@ |
    YX|;s|o |t's been|ing|'re| a|nd|A|makeC | yX|D| othM|ay it
    |G| w|I| f|Lh| t|er|
    (Ooh|eTrQ|RSna | g|on|ve|ell| I'm|We|ou".split("|").inject{|m,o|m.gsub((i+=1).chr,o)}

    The short 556 character solution above is essentially my previous solution, with substitution characters changed, so that the binary packing works better.

    If you run the original code-packer program on the above short solution, it will generate a solution that is valid ruby source code that is 549 bytes long. Running this generated ruby source code will print out the required lyrics. Note that although the compressed string is over 100 bytes shorter than the original program, most of the savings is taken up by the decompression code.

    If you run the current code-packer program on the above short solution, you get an expansion to 627 bytes. The packed string itself is about 50 bytes shorter, but adding the decompression code blows up the overall size.

    Thanks to the commenters for pointing out the technicalities of UTF-8 encoding. To me, the "valid UTF-8" restriction seems rather arbitrary-- if you're going to allow unprintable ascii characters in valid code, why shouldn't you also allow "invalidly coded UTF-8 characters?" The original code-packer still does generate valid ruby source code that really takes up only 549 bytes of storage when run on the 556-byte solution presented above.

    Ed H.

    Posted 2012-05-28T23:18:56.757

    Reputation: 956

    Is the packed code valid UTF8? – a sad dude – 2012-06-06T07:33:07.327

    Check the problem description. Your byte values between 128 and 255 have to be measured as UTF-8-encoded -- in other words as taking up two bytes each. (This rule change is why I had to withdraw my solution.) – breadbox – 2012-06-06T12:22:13.187


    ///, 692 682 666 656 bytes

    666 bytes lol.

    /1/ know //+/ you//>/You//=/Never gonna //!/I just wanna tell+ how I'm feeling
    Gotta make+ understand
    //@/=give+ up
    =let+ down
    =run around and desert+
    =make+ cry
    =say goodbye
    =tell a lie and hurt+
    //#/We've1each other for so long
    >r heart's been aching but
    >'re too shy to say it
    Inside we both1what's been going on
    We1the game and we're gonna play it//%/(Ooh, give+ up)//&/(Ooh)//*/=give, never gonna give//-/(Give+ up)/We're no strangers to love
    >1the rules and so do I
    A full commitment's what I'm thinking of
    > wouldn't get this from any other guy
    And if+ ask me how I'm feeling
    Don't tell me+'re too blind to see

    -10 bytes thanks to Flp.Tkc/Erik the Outgolfer

    Try it online!


    Posted 2012-05-28T23:18:56.757

    Reputation: 3 728

    Could you try replacing 'know'? (It's used 4 times, I think) – FlipTack – 2016-12-23T10:42:30.073

    Actually, you should be replacing " know ", not "know". – Erik the Outgolfer – 2016-12-23T14:37:10.803

    I think it would save 2 bytes to replace o. – Comrade SparklePony – 2017-03-24T21:23:51.357


    Windows batch, 975 911 892 bytes

    If I removed the four-space-code-indention, the result will look witty.

    Just some replacement work here. For example, I set Never gonna to a variable, and replace the other Never gonna with the variable.

    @echo off
    set y= you 
    set e=echo(
    set n=ever gonna 
    set g=Gotta make%y%understand
    set o=(Ooh
    set u=ive%y%up
    set i=I just wanna tell%y%how I'm feeling
    set c=call:
    %e%We're no strangers to love
    %e%You know the rules and so do I
    %e%A full commitment's what I'm thinking of
    %e%You wouldn't get this from any other guy
    %e%And if%y%ask me%i:~21%
    %e%Don't tell me you're too blind to see
    %e%%o%, g%u%)
    %e%%o%, g%u%)
    %e%N%n% give, n%n%give
    %e%N%n% give, n%n%give
    %c%n 1
    %e%N%n%run around and desert you
    %e%N%n%say goodbye
    %e%N%n%tell a lie and hurt you
    if %1.==. %e%
    %e%Your heart's been aching but
    %e%You're too shy to say it
    %e%Inside we both know what's been going on
    %e%We know the game and we're gonna play it


    Posted 2012-05-28T23:18:56.757

    Reputation: 539


    Brainfuck, 7497 bytes


    Try it online!

    This is still barely golfed, but a good bit better captncraig's solution. Maybe I'll get back to this later.


    Posted 2012-05-28T23:18:56.757

    Reputation: 339


    JavaScript 616 bytes

    _="cCsole.log(\"We'r:n6strJgKs46lo950P:ruleLQs6d6I*A fuFcommitment'LwhatRPink< of5 wMldn'tEetPiLfrom Jy=guy&>n$A2if?ask me1DC't4eFme-@bli2t6see!!*7,E/)7,E++/)>$&!!\");!*%g/%let?down%run arM2QdesKt-%Hcry%sayEoodbye%teFa li:Qhurt-$ each=for s6lCg5r hear8ach< but5@shy46sBInsid:w:both0 wha8go< C*We0P:gam:Qwe're3plB%*NS&*I just wJna4ell-1Gotta HundKstJd!*\\n+/)7)%gi9, nSgi9*(G?yM/i9?up0 know1 howR feel<*2nd 3ECna 4 t5*YM6o 7*(Ooh8t'Lbeen 9ve:e <ing= othK >**We'90?- @'re4o6Bay it*ConE gFll Hmake?JanKerLs MouP4hQa2R I'mSe9r3";for(Y in $="SRQPMLKJHFECB@?>=<:9876543210/-+*&%$!")with(_.split($[Y]))_=join(pop());eval(_)

    @tkazec, I tip my hat off to you... I don't think I could have brought it any lower...


    Posted 2012-05-28T23:18:56.757

    Reputation: 6 949

    1Try it online! – aloisdg moving to codidact.com – 2017-05-14T17:54:08.233


    Dart. 802b

    Live Online App (press play)


    My approach

    Uses no compression libraries.

    1. The starting string is the lyrics with all duplicate words removed, then split by ' ' into a list.
    2. I create 3 strings (4 in the super optimized version), each char is an ascii lookup in the list.
    3. The final string injects the first two at various points, using string interpolation.
    4. The final string is converted into char codes and used to perform the look ups in the word list.

    Verbose Code

    void main() {
      var x="We're no strangers to love You know the rules and so do I A full commitment's what I'm thinking of wouldn't get this from any other guy just wanna tell you how feeling Gotta make understand Never gonna give up let down run around desert cry say goodbye a lie hurt We've known each for long Your heart's been aching but You're too shy it Inside we both what's going on We game we're play And if ask me Don't you're blind see (Ooh, up) (Ooh) give, never (Give".split(' ');
      var c="DEF>G~DEH>I~DEJK)L>~DEB>M~DENO~DE=PQ)R>~~";
      var d="STU9V*W~XYZ[\\~]^_#N`~abc&dZef~g&'h)iEj`~";
      var a=' !"#\$~%&\'()*+,~-./0123~%456789:~,;<=>?1@~AB>C~~$c${d}kl>mn?1@~o=np^q#r~~$c${c}sF>t~sF>t~u~DEvDEF~x>t~u~DEvDEF~x>t~~$d~,;<=>?1@~AB>C~~$c$c$c';
      var o='';
      a.charCodes().forEach((i) => o += i == 126 ? '\n' : '${x[i-32]} ');

    Minimized Version



    Posted 2012-05-28T23:18:56.757

    Reputation: 21


    Just for fun, here is the start of sub routine for an excel macro that will spit out a text file after building the song into a spreadsheet and then deleting the spreadsheet. Just thought it would be fun. I figure I can reduce the code later. Just make sure you are using 2007 or above and save the initial spreadsheet as an .xlsm

    Sub R()
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Sheets.Add After:=Sheets(Sheets.Count)
    ActiveSheet.Name = "R"
    With Sheets("R")
    .Cells(1, 1) = "We're no strangers to love"
    .Cells(2, 1) = "You know the rules and so do I"
    .Cells(3, 1) = "A full commitment's what I'm thinking of"
    .Cells(4, 1) = "you wouldn't get this from any other guy"
    .Cells(5, 1) = "I just wanna tell you how I'm feeling"
    .Cells(6, 1) = "Gotta make you understand"
    g = "Never gonna"
    .Cells(8, 1) = g & " give you up"
    .Cells(9, 1) = g & " let you down"
    .Cells(10, 1) = g & " run around and desert you"
    .Cells(11, 1) = g & " make you cry"
    .Cells(12, 1) = g & " say goodbye"
    .Cells(13, 1) = g & " tell a lie and hurt you"
    .Cells(23, 1).Resize(7, 1) = .Cells(8, 1).Resize(7, 1).Value
    .Cells(30, 1).Resize(7, 1) = .Cells(8, 1).Resize(7, 1).Value
    .Cells(55, 1).Resize(7, 1) = .Cells(8, 1).Resize(7, 1).Value
    .Cells(62, 1).Resize(7, 1) = .Cells(8, 1).Resize(7, 1).Value
    .Cells(69, 1).Resize(7, 1) = .Cells(8, 1).Resize(7, 1).Value
    .Cells(15, 1) = "We've known each other for so long"
    .Cells(16, 1) = "Your heart's been aching but"
    .Cells(17, 1) = "you're too shy to say it"
    .Cells(18, 1) = "Inside we both know what's been going on"
    .Cells(19, 1) = "We know the game and we're gonna play it"
    .Cells(20, 1) = "And if you ask me how I'm feeling"
    .Cells(21, 1) = "Don't tell me you're too blind to see"
    .Cells(37, 1) = "(Ooh, give you up)"
    .Cells(38, 1) = .Cells(37, 1)
    .Cells(39, 1) = "(Ooh)"
     x = "Never gonna give"
    .Cells(40, 1) = x & "," & x
    .Cells(41, 1) = "(Give you up)"
    .Cells(42, 1) = "(Ooh)"
    .Cells(43, 1).Resize(2, 1) = Cells(40, 1).Resize(2, 1).Value
    .Cells(46, 1).Resize(5, 1) = Cells(15, 1).Resize(5, 1).Value
    .Cells(52, 1).Resize(2, 1) = Cells(5, 1).Resize(2, 1).Value
    End With
    sf = Left(ThisWorkbook.Name, InStr(ThisWorkbook.Name, ".xlsm") - 1) & Format(Now(), "_YYYY_MM_DD") & Format(Now(), "_HH_MM_SS") & ".txt"
    iu = FreeFile
    Open ThisWorkbook.Path & "\" & sf For Output As #iu
        With Sheets("R")
        For rr = 1 To 75
            Print #iu, .Cells(rr, 1).Text
        End With
        Close iu
    sp= ThisWorkbook.Path & "\" & sf
    ro = Shell("notepad.exe " & sp, vbNormalFocus)
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    End Sub


    Posted 2012-05-28T23:18:56.757

    Reputation: 121


    C#, 816 803 741 737 703 chars

    This is the entire class needed to print the lyrics to the console:

    class r{static void Main(){new u(@"]^(Ooh,>-)|£^I just wanna:3%&Gotta 2u+ersta+^*|$(Ooh)!gi<, ne<r_gi<^(G-)^|*!g-!let% down!run1rou+{desert%!2cry!say>oodbye!t31 lie{hurt%^|3ell|2make% |#^We'<4n each o/r for s;long[r hear~1ch? but[.:o;shy:;s=Inside we both}wha~>o? on^We}/>ame{we._pl=|!^Ne<r_|& how I'm feel?^|_>onna |=ay it^|[^You|^
    |-i<% up|% you|{1+ |}4 |4 know|~t's been|: t|;o |<ve|> g|?ing|/the|.'re|+nd|1 a");}class u{public u(string c){var a="We. n;strangers:;love[}/ rules{s;d;I^A full commitment's what I'm:hink? of[ wouldn't>et:his from1ny o/r>uy£#A+ if%1sk me&Don't:3 me%.:o;bli+:;see^**]]^$$#£**";foreach(var b in c.Split('|'))a=a.Replace(b[0]+"",b.Substring(1));System.Console.Write(a);}}}

    And a more readable version:

    class r
        static void Main()
            new u(@"]^(Ooh,>-)|£^I just wanna:3%&Gotta 2u+ersta+^*|$(Ooh)!gi<, ne<r_gi<^(G-)^|*!g-!let% down!run1rou+{desert%!2cry!say>oodbye!t31 lie{hurt%^|3ell|2make% |#^We'<4n each o/r for s;long[r hear~1ch? but[.:o;shy:;s=Inside we both}wha~>o? on^We}/>ame{we._pl=|!^Ne<r_|& how I'm feel?^|_>onna |=ay it^|[^You|^
    |-i<% up|% you|{1+ |}4 |4 know|~t's been|: t|;o |<ve|> g|?ing|/the|.'re|+nd|1 a");
        class u
            public u(string c)
                var a = "We. n;strangers:;love[}/ rules{s;d;I^A full commitment's what I'm:hink? of[ wouldn't>et:his from1ny o/r>uy£#A+ if%1sk me&Don't:3 me%.:o;bli+:;see^**]]^$$#£**";
                foreach (var b in c.Split('|'))
                    a = a.Replace(b[0] + "", b.Substring(1));

    No more optimisation - I had to write myself a quick n dirty zip engine to get it this small!


    Posted 2012-05-28T23:18:56.757

    Reputation: 161

    You can actually inline c to the foreach loop and just take out the class to optimize further. I would link it on TIO but the URL is too long. Gets you down to at least 665 chars/668 bytes. Why are you using £ by the way? – Stackstuck – 2019-03-07T14:38:27.133

    I'll submit an edit. – Stackstuck – 2019-03-07T14:43:02.300


    PHP - 568 570 567 bytes / 552 characters

    first: thank you for the competition, it was a nice challange even if I wount win with this solutions in this stage.

    based on the PHP-ideas obove but even very efficient I think:

    2=5letFdown5run arUndCdese@5:cry5sayVoodbye5Da liAhu@q
    [e'SJn each<for sQlongLr hear;achO but\9shyGK
    ]nside we boTBwha;goEn
    ] just wRna?H1Yotta :understRdq3)2, n4
    (Yq howIfeelO
    Z7qiS=)qeSr>qBTe qUMNQqmakeFqt's been q oTer qFupqVonna q Dqrt HqeCqJ q Rd qtell qO oq H qN sqyUq I'm q knowqay itq\Uq'req toqingq
    (Oohqo qanqveqthqouq gq
    YqI"),"[eM nQstrRgersN loSL8rulesCsQdQ]W full commitment's whatITinkEfL wUldn'tVet Tis from Ry<guy/-.Wnd ifFask me1Xon't?me y9blindGee--

    any hints?

    Sebastian Apprecht

    Posted 2012-05-28T23:18:56.757

    Reputation: 21

    I'm getting a count of < 500 bytes from your entry. You probably have code formatting mistakes with "<" and ">" – Ed H. – 2012-06-07T09:25:34.633

    just fixed the code and tested it again: now it should work :) – Sebastian Apprecht – 2012-06-08T07:48:24.137

    Underscores don't need quotes. range('-',_) will work just fine. Also the trailing ?> is not necessary, instead just use a semi-colon. Unfortunately, that still leaves you at 567 bytes, counting necessary newlines. – primo – 2012-06-08T07:59:16.413

    I'd really like to see a PHP submission win ;) You should be able to extend your range back to range('%',_) which should give you ~4 more usable keys to switch (, ' and one of () would likely need to be replaced with itself). – primo – 2012-06-08T13:26:48.703

    thank you for the ideas primo, I've tried this out in an earlier version but I dont need the more keys (they cost more space than they are eliminating). At the moment I'm playing with another algorithm of replacement (the actual one does not include the efficency of an replacement). The replacement of the capitals is actually very "expensive" - if someone has here a good idea I'll try this out. – Sebastian Apprecht – 2012-06-08T21:07:40.953


    PHP, 1192 bytes:

    (function ($compressed) {
    preg_match_all("#(^.+?)\n(.+$)#us", $compressed, $matches, PREG_SET_ORDER);
    list($schema, $compressed) = [ $matches[0][1] , $matches[0][2] ];
    for ($ix = strlen($schema) - 1; $ix >= 0; $ix--) {
        $char = $schema[$ix];
        $charQuoted = preg_quote($char, '#');
        preg_match_all("#{$charQuoted}(.+?){$charQuoted}#mus", $compressed, $matches1, PREG_SET_ORDER);
        $fullQuoted = preg_quote($matches1[0][0], '#');
        $compressed = preg_replace("#{$fullQuoted}#mus", $matches1[0][1], $compressed);
        $compressed = str_replace($char, $matches1[0][1], $compressed);
    return $compressed;
    We9\'re9 n5o L5sLtrangSerSs2 t25lo<ve<4
    YMouM4/ knowB/2heB rules0C aC>nd> 0s5d5I
    AP fPull commitQmeQnt\'sE wEhatR I\'mR2hink:ingK: Kof4EMldn\'t6 g6et2hisPromCny= othS=6uy%
    I justEanna2FellF1* 1yM*. howRPeel:
    .Gotta Hmake1Hu>Ssta>!%
    N$-e<r?6TonTna ?$g+Ji<J1up+-let1down-runCrM>0desSt*-Hcry-say6oodbye-tFC lie0hurt*!7
    We\'</7n" each=Por s5lTg4r hear8t\'s been8CchKbut492oLhy2L@ay it
    @InsideEe both/Eha86oKT
    WeB6aQ0we9?pl@"A> if1ask Q.DT\'t2F Q*92o5bli>2LeeU!!U
    (Ooh3,6;+);3,6&;3)-gJ, n$gJ

    Live DEMO of arbitrary text (de-)compression

    Agnius Vasiliauskas

    Posted 2012-05-28T23:18:56.757

    Reputation: 125

    2There's a lot of bytes to be saved by removing non-functional whitespace and shortening variable names. There's also no need for <pre> tags, as you can run PHP in the console. The trailing ?> can likewise be removed. – Dennis – 2017-12-30T14:25:48.183

    That and replacing PREG_SET_ORDER with 2 brings your score down to 864. Try it online!

    – Dennis – 2017-12-30T14:31:39.467


    Batch, 930 920 bytes

    (Alternate method)

    Thanks @Aacini for the skip such number of lines and show the rest of this file

    @!! 2>nul||cmd/q/v/c%0&&exit/b
    set l=^
    set u= you 
    set n=ever gonna 
    set g=ive you up
    set f= how I'm feeling
    set w=I just wanna tell you
    set c=N!n!g!g!!l!N!n!let!u!down!l!N!n!run around and desert you!l!N!n!make!u!cry!l!N!n!say goodbye!l!N!n!tell a lie and hurt you!l!
    set u=Gotta make you understand!l!.!l!!c!
    set k=We've know each other for so long!l!Your heart's been aching but!l!You're too shy to say it!l!Inside we both know what's been going on!l!We know the game and we're gonna play it
    for /F "useback skip=15 delims=" %%a in ("%~0")do set v=%%a&echo(!v:.=!
    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
    And if you ask me!f!
    Don't tell me you're too blind to see
    (Ooh, g!g!)
    (Ooh, g!g!)
    N!n!give, n!n!give
    N!n!give, n!n!give


    Posted 2012-05-28T23:18:56.757

    Reputation: 539


    JavaScript, 495 bytes

    for(_="on=er< g;ve:;=na 9e:r98 I'm7ou6o 55s4me3 t22h1\n00(Ooh/ell. w- y6make ay it0 oth<  know00We':ing're at's been i: up/,;)0Y6nd  how7 feel00N8/)gi:, n8gi:0(G)0glet downrunr6ades<tcrysay;oodbyet. liehurt0I just-anna2.Gotta und<stand eachfor s5l=gr hearach but2o4hy24Inside-e both-hago =0We1e;a3we9plWe n4trang<s25lo:1e ruless5d5I0A full commit3nt's-hat71ink of-6ldn't;et1is fromnyguynAifsk 3D='t2. 32o5blit4ee0";G=/[--=-]/.exec(_);)with(_.split(G))_=join(shift())


    Posted 2012-05-28T23:18:56.757

    Reputation: 11

    2Welcome to PPCG! Which programming language is this? – Dennis – 2018-11-24T14:18:51.630

    It's JavaScript – da0 – 2018-11-25T01:03:37.143

    How can I run this? Can you put it on TIO or similar? – dfeuer – 2019-03-05T05:58:47.693


    Java (JDK), 642 bytes

    v->{String s="Bell!@ w!?ay it-!> other!=make+ !<'re!;ing!: a!9ve!8 g!7t's been !6-(Ooh!5o !4-You!3 t!28onna !1 know!0nd !/ how I'm feel;-!.i9+ up!-\n!+ you!*.)6)%gi9, ne9r2gi9-(G!&-I just@anna3B+/Gotta =understand#!%-Ne9r2!$--We'91n each> for s5long4r hear7ach; but4<3o5shy35s?Inside@e both1@ha7go; on-We13he8ame:0we<2pl?!#-%g.%let+ down%run:rou0a0desert+%=cry%say8oodbye%tB: lie:0hurt+!We< n5strangers35lo9413he rules:0s5d5I-A full commitment's@hat I'm3hink; of4@ouldn't8et3his from:ny>8uy&$A0if+:sk me/Don't3B me+<3o5bli0t5see##-6,8.)6,8**.)$&##",x[];for(;(x=s.split("!",2)).length>1;)s=x[1].replace((x=x[0].split("",2))[0],x[1]);return s;}

    Try it online!

    Note: as allowed in the comments, I'm using the "We've known" (twice) version instead of "We've known" then "We've know " version.

    I used this program to generate the text according to the algorithm I wanted to use.


    The longest repeating substring with maximum coverage over the whole string has been extracted and replaced by a single character. The dictionary is done by prepending the replacement character, followed by the replacement string and a bang. This process has been repeated enough times to have the string that is minimised. The search and replacement occurs over the whole string with the dictionary, to compress both the text and the dictionary if needed.


    v->{                                 // null-accepting lambda, unused parameter
     String s="...",                     // The compressed string
            x[];                         // The array containing
                                         //   0: the dictionary to apply at this step
                                         //   1: the rest of the string.
     for(;(x=s.split("!",2)).length>1;)  // Split the string in two on an exclamation mark, and break if the there are none.
      s=x[1].replace(                    // Replace in the rest of the string...
       ""+x[0].charAt(0),                // ... the single-character...
       x[0].substring(1));               // ... with the longer string.
     return s;                           // Return the decompressed string.

    Olivier Grégoire

    Posted 2012-05-28T23:18:56.757

    Reputation: 10 647


    PHP - 737 719 Characters

    <?$m="str_replace";$c="^g% ^let# down^run around and desert#^make# cry^say goodbye^tell a lie and hurt#@";$w="@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@";$o="(Ooh,g%)@";$a="(Ooh)^give, never gonna give@(G%)@";$i="@I just wanna tell# how I'm feeling@Gotta make# understand@";echo$m("@","<br />",$m("#"," you",$m("%","ive# up",$m("^","@Never gonna ","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$c$w And if# ask me how I'm feeling@Don't tell me#'re too blind to see@$c$c@$o$o$a$a$w$i$c$c$c"))));

    Whee for breaking all sorts of rules!


    Posted 2012-05-28T23:18:56.757

    Reputation: 131


    Perl - 706 699 characters.

    Completely safe to cut+paste :)

    Did the encoding by eye, should be possible to get a better ratio if I get around to doing some statistical analysis.

    $_=q{$_="Fn3strSgersMlovez1C P rules ~s3W IzTfull commitmentXwhatNthYkYg ofz1wouldn'UgeUthis from SyOguyDAn5~if 1askL8Wn'U%L9blYdMsee00z22==A5D00zz"V=Qz64, 64q4 1RVDzI jusUwSnT% 18gottTmakZ1understSd0V2Q, 4 1RVQqoohV0z04 1R0leU1Wwn0run aroun_~deserUJ0makZ1cry0say goodbye0% TliZ~hurUJV%tellV0z6V1J V4giveV5 eachOfor s3longzJr heart!achYg butz9shyMsBYsidZK both C what!goYg onzK C P gamZ~F7plBV~S_V6never 7V_d V7gonnTV!Xbeen VX's VWdoV8howNfeelYgzV9J'rZto3VAzzK'vZCVBay itzVCknowVFK'rZVJyouVKweVYinVL mZVM t3V3o VN I'm VO oPr VZe VPtheVRupVSanVTa VUt Eq([^zq])([^zq]+)/"\r\n(".H."$2)"Ez(\(?[^z]?)/"\r\n".HE(^.)/H;};s'H'uc($1)'g;s:V(.):;G$1/:g;s:E:;eG:g;s:(e?)G(.+?)/(.+?);:;s/$2/$3/g$1;:g;eval;print


    Posted 2012-05-28T23:18:56.757

    Reputation: 111


    PHP - 802 bytes and Python - 795 780 bytes

    Below is a PHP script that downloads the lyrics, compresses them using a naive implementation of LZSS and then outputs the compressed string together with some decompression code (802 bytes).

    $in = file_get_contents("http://pastebin.com/raw.php?i=wwvdjvEj");
    $compressed_string = '';
    $inc = true;
    for ($i = 0; $i < strlen($in); $i++) {
        $offset = 0;
        $length = 0;
        for ($j = 1; $j < strlen($in) - $i + 1; $j++) {
            if (($os = strpos(substr($in, 0, $i), substr($in, $i, $j))) !== false) {
                $offset = $os;
                $length = $j;
            } elseif ($length > 0) {
            } else { 
                $length = 0;
        if ($length > 0) {
            $rep = '';
            if (!$inc) {
                $rep = '>';
            $rep .= $offset . '|' . $length;
            if (strlen($rep) < $length) {
                $compressed_string .= $rep;
                $i += $length - 1;
                $inc = false;
        $compressed_string .= substr($in, $i, 1);
        $inc = true;
    echo '<?$f="' . $compressed_string . '";do$f=preg_replace_callback(\'/>?(\d+)\|(\d+)/\',create_function(\'$m\',\'global$f;return substr($f,$m[1],$m[2]);\'),$f,1,$c);while($c);echo$f;';

    And this is the output:

    <?$f="We're no strangers to love
    You know the rules and so do I
    A full commitment's what I'm thinking of26|6wouldn't get this from any other guy
    I just wanna tell you how84|5feeling
    Gotta make you understand
    Never gonna giv192|7p210|14let you down210|14run around46|5desert you210|14>189|9cry210|14say goodbye210|14tell a lie46|5hu294|8
    We've31|5n each132|7for so long26|5r heart's been aching but26|5're too shy to say it
    Inside we both31|6wha437|9go94|5n
    W396|6 the gam374|6w1|5gonna pl477|7And if you ask me165|18Don't156|6me y459|10blind to see208|184>212|180(Ooh,223|12)1002|20
    (Ooh)210|18, n213|15
    (G1031|58>1011|13>390|12>403|165>142|250>644|356";do$f=preg_replace_callback('/>?(\d+)\|(\d+)/',create_function('$m','global$f;return substr($f,$m[1],$m[2]);'),$f,1,$c);while($c);echo$f;

    Based on the same idea, I also made this Python script, which is slightly smaller than the PHP version.

    import re
    s="""We're no strangers to love
    You know the rules and so do I
    A full commitment's what I'm thinking of26|5wouldn't get this from any other guy
    I just wanna tell you how82|5feeling
    Gotta make you understand
    Never gonna giv187|7p204|13let you down204|13run around45|5desert you204|13>184|9cry204|13say goodbye204|13tell a lie45|5hu285|7
    We've30|5n each129|7for so long
    Your heart's been aching but
    You2|4too shy to say it
    Inside we both30|6wha422|9go92|5n
    W382|6 the gam362|6w1|5gonna pl461|6And if you ask me161|17Don't152|6me y443|10blind to see203|175>205|173(Ooh,216|12)967|19
    (Ooh)204|17, n206|15
    while p!=s:p=s;s=re.sub('>?(\d+)\|(\d+)',lambda m:s[int(m.group(1)):int(m.group(1))+int(m.group(2))],s,1)
    print s

    Jorrit Kronjee

    Posted 2012-05-28T23:18:56.757

    Reputation: 11


    C - 890 Characters

    I haven't seen many C ones so I thought I'd do one. This is my first attempt and I know it's not the shortest but was interesting to do and works. This is basic word compression but trying not to have any delimiters in the dictionary to save space. A bit of recursion and a few macros just to mix it up a bit! Unfortunately I now know the lyrics by heart and can't get the tune out of my head!

    char m[20];   char*t="aIAuptoitsoWeweonmeofnoifdoanyyouandsayrunlieletcryup)I'mtoothehowYoushyforbutseeguygetaskAndgivetellmakeknowhurtdownbeenYourplaylongjustgameeachboth(OohwhatthislovefullfromotherNevergonnaWe'vewe'rewannaneverGottagoing(Ooh)(GiveWe'rerulesNeverknownDon'tblinddesertaroundYou'rewhat'sInsideachingyou'regoodbyefeelingheart'swouldn'tthinkingstrangersunderstandcommitment's";
    int l[]={0,3,12,22,20,17,7,3,2,1,1,0,1};
    #define h "i^H3& i^83M i^6n4m3 i^J39 i^5t i^I#74L3"
    #define v "_jT\\A)Q OvNrB o<@'5( q+UKpNd, *K=S4`^P("
    #define n "$RaI3>;u cJ3z"
    char*s="g/y'Y ?K=h4)1$ %Z{W;x. ?wEX[2\\D "n"  "h"  "v" G03F->;u kI-s<l'C  "h"  "h"  VH3: VH3: e ]^Hb^H f3: e ]^Hb^H f3:  "v"  "n"  "h"  "h"  "h" ";
    char*w(int r,int c,int u,int o){m[c]=0;u+l[c]<=r?w(r,c+1,u+l[c],o+l[c]*c):strncpy(m,t+o+(r-u)*c,c);return m;}
    void RA(){while(*s!=0){printf(*s==' '?"\n":"%s ",w(*s-35,1,0,0));s++;}}


    Posted 2012-05-28T23:18:56.757

    Reputation: 11

    Suggest u+l[c]>r?strncpy(m,t+o+(r-u)*c,c):w(r,c+1,u+l[c],o+l[c]*c) instead of u+l[c]<=r?w(r,c+1,u+l[c],o+l[c]*c):strncpy(m,t+o+(r-u)*c,c) and for(;*s;s++)printf(*s-32?"%s ":"\n",w(*s-35,1,0,0)); instead of while(*s!=0){printf(*s==' '?"\n":"%s ",w(*s-35,1,0,0));s++;}. Also you can combine string declarations to eliminate char several times. – ceilingcat – 2016-09-21T18:53:08.433


    626 Bytes, PHP (output as Pastebin link below)

    <?=str_replace(str_split(LCB2Z34516789HJKPQRSTUVX),explode(M,"ever 6M
    I just wanna J9Z
    Gotta U9understand
    BM279up2let 9down2run arouHaHdesert you2U9cry2say goodbye2Ja lie aHhurt youM
    Never 6Mhow I'm feelXM
    We'vePn eachRfor so longQr hearTachX butQ'reKshy to say it
    Inside we bothP whaTgoX on
    WePSgaVaHwe're 6play itM8, 79up)M8)
    N1, n1
    (Give 9up)Mever 6giveMgonna Mgive M
    (OohMyou Mnd Mtell M too M knowM
    YouM other M the Mt's been Mmake Mme Ming"),"We're no strangers to loveQPSrules aHso do I
    A full commitment's what I'm thinkX ofQ wouldn't get this from anyRguyC
    AHif 9ask VZ
    Don't JVyou'reKbliHto see

    To make this easier to verify, here's the output: http://pastebin.com/xzXsw3wQ

    Here's the program that I used to write this program: http://pastebin.com/NGX1Qe0Z. It's pretty hacky, but it should be fairly clear how it works. There's a map array that's used to encode/decode, and the program above is written to program.php. It checks to make sure the output matches the lyrics file (lyrics.txt) and shows the byte count. You could probably do better than my byte count by writing a better map.


    Posted 2012-05-28T23:18:56.757

    Reputation: 11


    PHP 948 Bytes

    $w=array("Never gonna ","Give","give","feeling","understand","goodbye","wanna","str_replace");$s=array("$w[0]$w[2]+up#$w[0]let+down#$w[0]run around@desert+#$w[0]make+cry#$w[0]say $w[5]#$w[0]tell a lie@hurt+","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@we're gonna play it","(Ooh, $w[2]+up)");$t="We're no strangers to love#You know the rules@so do I#A full commitment's what I'm thinking of#You wouldn't get this from any other guy#I just $w[6] tell+how I'm $w[3]#Gotta make+$w[4]*$s[0]*We've known $s[1]#And if+ask me how I'm $w[3]#Don't tell me+'re too blind to see*$s[0]*$s[0]*$s[2]#$s[2]#(Ooh)#$w[0]$w[2], $w[0]$w[2]#($w[1]+up)#(Ooh)#$w[0]$w[2], $w[0]$w[2]#($w[1]+up)*We've know $s[1]*I just $w[6] tell+how I'm $w[3]#Gotta make+$w[4]*$s[0]*$s[0]*$s[0]";echo nl2br($t=$w[7]("#","\n",$t=$w[7]("*","\n\n",$t=$w[7]("+"," you ",$t=$w[7]("@"," and ",$t)))));


    Posted 2012-05-28T23:18:56.757

    Reputation: 11


    PHP:1002 Chars

    Well this is my first CodeGolf, I'm sure I missed some things. It should echo out the lyrics with the line numbers.

    I'll come back to this later, I'm a little sick of looking at these lyrics @.@ .

    $gi=" give";
    $n="Never gonna";
    $yu=" $y up";
    $g=" $gi $yu";
    $l=" let $y down";
    $r=" run around and desert $y";
    $m=" make you cry";
    $s=" say goodbye";
    $t=" tell a lie and hurt $y";
    $n $g
    $n $l
    $n $r
    $n $m
    $n $s
    $n $t";
    $v1e1="I just wanna tell $y how I'm feeling
    Gotta make $y understand";
    $v1="We're no strangers to love
    $u know the rules and so do I
    A full commitment's what I'm $d thinkin' of
    $u wouldn't get this from any other guy
    $v2="We've known each other for so long
    $ur heart's been aching but 
    $u'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";
    $v2e1="And if $y ask me how I'm feeling
    Don't tell me $y're to blind to see";
    $n$gi $n$gi
    $n$gi $n$gi
    foreach($z as $ly){echo $num." ".$ly."<br/>";$num++;}


    Posted 2012-05-28T23:18:56.757

    Reputation: 287


    Swift, 697 bytes

    import Foundation
    var s="We'r!n$str+gers*$love2 6*h!rules 4s$d$I\nA full commitmen8wha&I'm*hink3 of2 wouldn'&get*his from +y70uyJ%\n\nFnH\nAnd if .ask m!<Don't5m!1=blind*$see%%\n\n@@EE\nFH\nJ%%%"
    for(a,b)in zip("JHFECB@?%=<:987654#>-0/.13&2+!*$","\nI jus&w+na5.<Gotta mak-nd/st+d; each7/ for s$long2r hear: ach3 but2=shy*$9it\nInsid!w!both 6 wha: go3 on\nW!6*h!gam!4we'r!goBplay it;We'v!6;?)#C, nev0oBC\n(Giv-p)\n;give;nna ;?, giv-p)\n;(Ooh;\n#giv-p#le&.down#run around 4des/&1#mak!.cry#9goodbye>5a li!4hur&1;'re*o$;how I'm feel3\n;8been;say ;t's ; oth;know;*ell ;+d ;> ;\nNev0onna;!.u;/ g;er;1 ;you;ing;t ;\nYou;an;e ; t;o ;".split{$0==";"}){s=s.replacingOccurrences(of:"\(a)",with:b)}

    Try it online!


    import Foundation                               // Import `replacingOccurrences`
    var s = "<...>"                                 // The compressed text
    for(a,b)in zip("<...>","<...>".split{$0==";"}){ // For every character in the first string,
      s=s.replacingOccurrences(of:"\(a)",with:b)    // replace all occurences of it with its
    }                                               // replacement in the second string
    print(s)                                        // Print the resulting text

    Herman L

    Posted 2012-05-28T23:18:56.757

    Reputation: 3 611


    iX2Web, 2778 bytes

    Just had to make an iX2Web solution ;)

    **iX200196 64378DMwlX ZSdyZSBuby BzdHJhbmdl cnMgdG8gbG 92ZbZZb3Ug a25vdyB0aG UgcnVsZXMg YW5kIHNvIG RvIEm2QSBm dWxsIGNvbW 1pdG1lbnQn cyB3aGF0IE knbSB0aGlu a2luZyBvZr ZZb3Ugd291 bGRuJ3QgZ2 V0IHRoaXMg ZnJvbSBhbn kgb3RoZXIg Z3V5tkkgan VzdCB3YW5u YSB0ZWxsIH lvdSBob3cg SSdtIGZlZW xpbme2R290 dGEgbWFrZS B5b3UgdW5k ZXJzdGFuZL a2TmV2ZXIg Z29ubmEgZ2 l2ZSB5b3Ug dXC2TmV2ZX IgZ29ubmEg bGV0IHlvdS Bkb3dutk5l dmVyIGdvbm 5hIHJ1biBh cm91bmQgYW 5kIGRlc2Vy dCB5b3W2Tm V2ZXIgZ29u bmEgbWFrZS B5b3UgY3J5 tk5ldmVyIG dvbm5hIHNh eSBnb29kYn lltk5ldmVy IGdvbm5hIH RlbGwgYSBs aWUgYW5kIG h1cnQgeW91 trZXZSd2ZS Brbm93biBl YWNoIG90aG VyIGZvciBz byBsb25ntl lvdXIgaGVh cnQncyBiZW VuIGFjaGlu ZyBidXS2WW 91J3JlIHRv byBzaHkgdG 8gc2F5IGl0 tkluc2lkZS B3ZSBib3Ro IGtub3cgd2 hhdCdzIGJl ZW4gZ29pbm cgb262V2Ug a25vdyB0aG UgZ2FtZSBh bmQgd2Uncm UgZ29ubmEg cGxheSBpdL ZBbmQgaWYg eW91IGFzay BtZSBob3cg SSdtIGZlZW xpbme2RG9u J3QgdGVsbC BtZSB5b3Un cmUgdG9vIG JsaW5kIHRv IHNlZba2Tm V2ZXIgZ29u bmEgZ2l2ZS B5b3UgdXC2 TmV2ZXIgZ2 9ubmEgbGV0 IHlvdSBkb3 dutk5ldmVy IGdvbm5hIH J1biBhcm91 bmQgYW5kIG Rlc2VydCB5 b3W2TmV2ZX IgZ29ubmEg bWFrZSB5b3 UgY3J5tk5l dmVyIGdvbm 5hIHNheSBn b29kYnlltk 5ldmVyIGdv bm5hIHRlbG wgYSBsaWUg YW5kIGh1cn QgeW91trZO ZXZlciBnb2 5uYSBnaXZl IHlvdSB1cL ZOZXZlciBn b25uYSBsZX QgeW91IGRv d262TmV2ZX IgZ29ubmEg cnVuIGFyb3 VuZCBhbmQg ZGVzZXJ0IH lvdbZOZXZl ciBnb25uYS BtYWtlIHlv dSBjcnm2Tm V2ZXIgZ29u bmEgc2F5IG dvb2RieWW2 TmV2ZXIgZ2 9ubmEgdGVs bCBhIGxpZS BhbmQgaHVy dCB5b3W2ti hPb2gsIGdp dmUgeW91IH VwKbYoT29o LCBnaXZlIH lvdSB1cCm2 KE9vaCm2Tm V2ZXIgZ29u bmEgZ2l2ZS wgbmV2ZXIg Z29ubmEgZ2 l2ZbYoR2l2 ZSB5b3UgdX AptihPb2gp tk5ldmVyIG dvbm5hIGdp dmUsIG5ldm VyIGdvbm5h IGdpdmW2KE dpdmUgeW91 IHVwKba2V2 UndmUga25v dyBlYWNoIG 90aGVyIGZv ciBzbyBsb2 5ntllvdXIg aGVhcnQncy BiZWVuIGFj aGluZyBidX S2WW91J3Jl IHRvbyBzaH kgdG8gc2F5 IGl0tkluc2 lkZSB3ZSBi b3RoIGtub3 cgd2hhdCdz IGJlZW4gZ2 9pbmcgb262 V2Uga25vdy B0aGUgZ2Ft ZSBhbmQgd2 UncmUgZ29u bmEgcGxheS BpdLa2SSBq dXN0IHdhbm 5hIHRlbGwg eW91IGhvdy BJJ20gZmVl bGluZ7ZHb3 R0YSBtYWtl IHlvdSB1bm RlcnN0YW5k trZOZXZlci Bnb25uYSBn aXZlIHlvdS B1cLZOZXZl ciBnb25uYS BsZXQgeW91 IGRvd262Tm V2ZXIgZ29u bmEgcnVuIG Fyb3VuZCBh bmQgZGVzZX J0IHlvdbZO ZXZlciBnb2 5uYSBtYWtl IHlvdSBjcn m2TmV2ZXIg Z29ubmEgc2 F5IGdvb2Ri eWW2TmV2ZX IgZ29ubmEg dGVsbCBhIG xpZSBhbmQg aHVydCB5b3 W2tk5ldmVy IGdvbm5hIG dpdmUgeW91 IHVwtk5ldm VyIGdvbm5h IGxldCB5b3 UgZG93brZO ZXZlciBnb2 5uYSBydW4g YXJvdW5kIG FuZCBkZXNl cnQgeW91tk 5ldmVyIGdv bm5hIG1ha2 UgeW91IGNy ebZOZXZlci Bnb25uYSBz YXkgZ29vZG J5ZbZOZXZl ciBnb25uYS B0ZWxsIGEg bGllIGFuZC BodXJ0IHlv dba2TmV2ZX IgZ29ubmEg Z2l2ZSB5b3 UgdXC2TmV2 ZXIgZ29ubm EgbGV0IHlv dSBkb3dutk 5ldmVyIGdv bm5hIHJ1bi Bhcm91bmQg YW5kIGRlc2 VydCB5b3W2 TmV2ZXIgZ2 9ubmEgbWFr ZSB5b3UgY3 J5tk5ldmVy IGdvbm5hIH NheSBnb29k Ynlltk5ldm VyIGdvbm5h IHRlbGwgYS BsaWUgYW5k IGh1cnQgeW 91fF8wCTAN Cg===*


    Posted 2012-05-28T23:18:56.757

    Reputation: 12 038


    Dart, 733 bytes

    F(){var e=' give',a='ever gonna',l=" how I'm feeling",h=' you',i='(Give$h up)\n',j=' tell',k='(Ooh)\nN$a$e, n$a$e\n$i',b="""
    N$a$e$h up
    N$a let$h down
    N$a run around and desert$h
    N$a make$h cry
    N$a say goodbye
    N$a$j a lie and hurt$h
    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""",d="(Ooh,$e$h up)",f='I just wanna$j$h$l\nGotta make$h understand\n';return"""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
    And if$h ask me$l
    Don't$j me$h're too blind to see

    Try it online!


    Posted 2012-05-28T23:18:56.757

    Reputation: 913


    C# (.NET Core), 819 816 810 808 806 792 chars/bytes

    class R{static void Main(){string N="Never gonna ",r="\n",H=" how I'm feeling_",n=N+"give! up"+(N=r+N)+"let! down"+N+"run around and desert!"+N+"make! cry"+N+"say goodbye"+N+"tell a lie and hurt!_",b=n+r,w="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_",f="_I just wanna tell!"+H+"Gotta make! understand__"+b,g="(Ooh, give! up)_",o="(Ooh)"+N+"give, never gonna give_(Give! up)_";System.Console.Write(("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"+f+w+"And if! ask me"+H+"Don't tell me!'re too blind to see__"+b+b+g+g+o+o+r+w+f+b+n).Replace("!"," you").Replace("_",r));}}

    Try it online!

    I'm using a mixed approach - some string concatenation, some replacement.

    C# (.NET Core), 664 chars/bytes

    class R{static void Main(){var a="We. n;strangers:;love[}/ rules{s;d;I^A full commitment's what I'm:hink? of[ wouldn't>et:his from1ny o/r>uy`#A+ if%1sk me&Don't:3 me%.:o;bli+:;see^**]]^$$#`**";foreach(var b in @"]^(Ooh,>-)|`^I just wanna:3%&Gotta 2u+ersta+^*|$(Ooh)!gi<, ne<r_gi<^(G-)^|*!g-!let% down!run1rou+{desert%!2cry!say>oodbye!t31 lie{hurt%^|3ell|2make% |#^We'<4n each o/r for s;long[r hear~1ch? but[.:o;shy:;s=Inside we both}wha~>o? on^We}/>ame{we._pl=|!^Ne<r_|& how I'm feel?^|_>onna |=ay it^|[^You|^
    |-i<% up|% you|{1+ |}4 |4 know|~t's been|: t|;o |<ve|> g|?ing|/the|.'re|+nd|1 a".Split('|'))a=a.Replace(b[0]+"",b.Substring(1));System.Console.Write(a);}}

    Try it online!

    I optimized the code of another answer for this - it was using an entire class it didn't need to.

    Output sample here


    Posted 2012-05-28T23:18:56.757

    Reputation: 209

    oh hey I can golf this more. +(N=r+N)+ – Stackstuck – 2019-03-06T13:40:36.530

    Saved 6 bytes with that. – Stackstuck – 2019-03-06T14:06:07.170

    Saved two bytes by adding b to f, saved two bytes by giving f a leading newline. – Stackstuck – 2019-03-07T13:02:59.917

    Saved 14 bytes w/ judicious use of .Replace(). I think it's 14 bytes. It's 14 bytes. – Stackstuck – 2019-03-07T14:22:00.287

    stole someone else's trick and optimized that: saved 39 chars/bytes over their final answer. If they steal it back I'll take this out. – Stackstuck – 2019-03-13T10:12:19.690

    switched ` in in place of £, no change except in the uncounted bytecount. – Stackstuck – 2019-03-13T10:17:13.427

    (to be honest, I am not sure why that worked, only that it did, but I'm not complaining.) – Stackstuck – 2019-03-13T10:23:10.193

    (for the record, I saved 3 bytes by s/£/`ing.) – Stackstuck – 2019-03-13T10:28:30.673

    Oh wait I think I get it now... – Stackstuck – 2019-03-15T05:10:17.290


    ink, 839 777 bytes

    ~temp o="(Ooh, g{g})"
    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
    And if you ask me how I'm feeling
    Don't tell me you're too blind to see
    N{n}give, n{n}give
    N{n}give, n{n}give
    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
    I just wanna tell you how I'm feeling
    Gotta make you understand
    N{n}let you down
    N{n}run around and desert you
    N{n}make you cry
    N{n}say goodbye
    N{n}tell a lie and hurt you
    VAR n="ever gonna "
    VAR g="ive you up"

    Try it online!

    -62 (!!!) bytes why the H E C C did I think functions were the way to go here?

    It's not a very nice solution, but I spent too long on it to just throw it away.

    I'm still not a huge fan of those tunnels, but assigning a multiline strings to a variable in ink is weirder than you'd think.

    Sara J

    Posted 2012-05-28T23:18:56.757

    Reputation: 2 576


    HTML, 1875 bytes

    This has to be done.

    <pre>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
    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
    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
    (Ooh, give you up)
    (Ooh, give you up)
    Never gonna give, never gonna give
    (Give you up)
    Never gonna give, never gonna give
    (Give you up)
    We've know 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
    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
    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
    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


    Posted 2012-05-28T23:18:56.757

    Reputation: 1 242

    Do you really need the pre tag? – Beta Decay – 2016-10-02T09:17:53.280

    @BetaDecay Yes, because without pre the linebreaks get ignored. – user8397947 – 2016-10-03T02:41:28.497

    3this is low quality :| – Christopher – 2018-02-14T03:27:15.143