69
\$\begingroup\$

Write a program that outputs the lyrics to 99 Bottles of Beer, in as few bytes as possible.

Lyrics:

99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.

98 bottles of beer on the wall, 98 bottles of beer.
Take one down and pass it around, 97 bottles of beer on the wall.

97 bottles of beer on the wall, 97 bottles of beer.
Take one down and pass it around, 96 bottles of beer on the wall.

96 bottles of beer on the wall, 96 bottles of beer.
Take one down and pass it around, 95 bottles of beer on the wall.

95 bottles of beer on the wall, 95 bottles of beer.
Take one down and pass it around, 94 bottles of beer on the wall.

....

3 bottles of beer on the wall, 3 bottles of beer.
Take one down and pass it around, 2 bottles of beer on the wall.

2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.

1 bottle of beer on the wall, 1 bottle of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.

Rules:

  • Your program must log to STDOUT or an acceptable alternative, or be returned from a function (with or without a trailing newline).
  • Your program must be a full, runnable program or function.
  • Languages specifically written to submit a 0-byte answer to this challenge are allowed, just not particularly interesting.

    Note that there must be an interpreter so the submission can be tested. It is allowed (and even encouraged) to write this interpreter yourself for a previously unimplemented language.

  • This is different from the output by HQ9+ or 99. Any answers written in these languages will be deleted.

As this is a catalog challenge, this is not about finding the language with the shortest solution for this (there are some where the empty program does the trick) - this is about finding the shortest solution in every language. Therefore, no answer will be marked as accepted.

Catalogue

The Stack Snippet at the bottom of this post generates the catalogue from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 290px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 64198; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 36670; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "//api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "//api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(42), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>

\$\endgroup\$
  • 11
    \$\begingroup\$ Whoever closevoted this, the other one is a popularity contest... \$\endgroup\$ – TheDoctor Nov 18 '15 at 15:19
  • 19
    \$\begingroup\$ This is a subtask of the Create an HQ9+ Interpreter golf. \$\endgroup\$ – Geobits Nov 18 '15 at 15:25
  • 4
    \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ I haven't VTCd it yet, still deciding how I feel about that. Either way, I think some answers (or snippets from them) from the other can be directly copy/pasted while remaining competitive, which is a usual test for dupe-ness. \$\endgroup\$ – Geobits Nov 18 '15 at 15:54
  • 13
    \$\begingroup\$ Note that quartata had already sandboxed a 99BB catalog several weeks ago and was planning to post it. \$\endgroup\$ – Alex A. Nov 18 '15 at 17:07
  • 12
    \$\begingroup\$ @GamrCorps Please do not unnecessarily change the rules after the challenge has started. None of the characters in the output should be optional. \$\endgroup\$ – feersum Nov 18 '15 at 18:42

133 Answers 133

40
\$\begingroup\$

C#, 285 298 289 Bytes

(My first attempt at Code golfing ...)

class d{static void Main(){for(int b=99;b>0;)System.Console.Write("{0}{6}{1}{2}, {0}{6}{1} of beer. {3}, {4}{6}{5}{2}.{7}",b,b==1?"":"s"," of beer on the wall",b==1?"Go to the store and buy some more":"Take one down and pass it around",b==1?99:b-1,b==2?"":"s"," bottle",b--<2?"":"\n\n");}}

A little bit ungolfed:

class d{
    static void Main(){
        for(int b = 99; b > 0;){
            System.Console.Write("{0}{6}{1}{2}, {0}{6}{1} of beer.\n{3}, {4}{6}{5}{2}.{7}", b, b==1 ? "" : "s", " of beer on the wall", b == 1 ? "Go to the store and buy some more" : "Take one down and pass it around", b == 1 ? 99 : b-1, b== 2 ? "" : "s", " bottle", b--<2 ? "" : "\n\n");
        }
    }
}
\$\endgroup\$
  • 10
    \$\begingroup\$ tip - use var instead of string :) \$\endgroup\$ – Belfield Nov 18 '15 at 16:48
  • 2
    \$\begingroup\$ 2 bytes from replacing " bottle" with a format argument though I'm sure there is a better way, having 3 instances of bottle hurts my eyes... \$\endgroup\$ – Sven Writes Code Nov 18 '15 at 18:21
  • 4
    \$\begingroup\$ b==1 can be replaced with b<2. \$\endgroup\$ – LegionMammal978 Nov 18 '15 at 22:48
  • 2
    \$\begingroup\$ Your for loop could be written like this for(int b = 100; b--> 1;) \$\endgroup\$ – Yassin Hajaj Nov 19 '15 at 10:20
  • 2
    \$\begingroup\$ Then maybe we should wait for the challenge author to decide if a trailing newline is allowed or not. \$\endgroup\$ – Florian Bach Nov 28 '15 at 13:24
29
\$\begingroup\$

Motorola MC14500B Machine Code, 46612 bytes

For length reasons, I can not post the program here. However, it can be found here in hexadecimal, and here in binary (padded with 0s).


This is the shortest possible program in Motorola MC14500B machine code. It consists of only 1000 and 1001 (8 and 9, respectively); one opcode for each bit of output.

It uses 93,224 half-byte opcodes, and outputs the song lyrics one bit at a time. This is the only possible output method.

For those interested, the output goes to pin #3 (of 16), the I/O pin.


Explanation

8    Store the register's value
9    Store the logical complement of the register's value

The register starts at 0.


Code Trivia

  • The hexadecimal is 93,224 8s and 9s long.

  • The binary is 745,792 1s and 0s long.

  • I used the Python 2 code below to generate the code. Input 0 for binary and 1 for hexadecimal.

    a,b=["8","9"]if input()else["00001000","00001001"]
    f="""99 Bottles of Beer lyrics"""
    print''.join(b if int(i)else a for i in''.join((8-len(bin(i)[2:]))*'0'+bin(i)[2:]for i in bytearray(f)))
\$\endgroup\$
  • 4
    \$\begingroup\$ Please tell me you didn't just go and write this all out without some sort of string generator... :c \$\endgroup\$ – Addison Crump Nov 20 '15 at 8:16
  • 1
    \$\begingroup\$ See the new "Code Trivia" section :P @VoteToClose \$\endgroup\$ – Zach Gates Nov 23 '15 at 5:24
  • \$\begingroup\$ The links are broken :( \$\endgroup\$ – ETHproductions Dec 23 '15 at 15:58
  • \$\begingroup\$ I'll fix it when I get back home. Sorry about that ): @ETHproductions \$\endgroup\$ – Zach Gates Dec 23 '15 at 16:37
25
\$\begingroup\$

Seriously, 1 byte

N

If the stack is empty (which it is at the start), N pushes the lyrics. Then they're implicitly printed at EOF.

Thanks to @Mego for fixing the Seriously interpreter.

\$\endgroup\$
  • 19
    \$\begingroup\$ Martin said in the Hello World challenge, ">please don't downvote boring (but valid) answers in languages where there is not much to golf - these are still useful to this question as it tries to compile a catalogue as complete as possible. However, do primarily upvote answers in languages where the authors actually had to put effort into golfing the code." This answer is uninteresting, but it is a valid and the shortest solution. \$\endgroup\$ – lirtosiast Nov 18 '15 at 17:17
  • \$\begingroup\$ When reading the question I couldn't wait to see you posting a Serious answer. But it looks like I don't even have to wait. :) \$\endgroup\$ – Hexaholic Nov 18 '15 at 17:35
  • 8
    \$\begingroup\$ Seriusly???????? \$\endgroup\$ – Vajura Nov 19 '15 at 10:59
  • 1
    \$\begingroup\$ I look forward to seeing your solution without the use of N :) \$\endgroup\$ – Mego Nov 19 '15 at 14:34
  • 1
    \$\begingroup\$ Yeah - I have four down votes and my answer is valid. I concur with what is said in the top comment here. \$\endgroup\$ – Addison Crump Nov 19 '15 at 16:06
25
\$\begingroup\$

Vitsy, 0 Bytes



Seriously ain't got nothin' on me. (@Mego I'm so sorry. ;))

Try it online! (Just hit "Run")

\$\endgroup\$
  • 7
    \$\begingroup\$ o_o I need something interesting for Simplex to do in zero bytes :P \$\endgroup\$ – Conor O'Brien Nov 18 '15 at 19:09
  • 3
    \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ I think you mean, "I need something useful for Simplex to do in zero bytes." \$\endgroup\$ – Martin Ender Nov 19 '15 at 11:21
  • 1
    \$\begingroup\$ @VoteToClose - How does this work? I honestly don't know, I'm not a code golfer, but I enjoy coming here and seeing people and languages do it. But I can't comprehend this. +1 because it looks impressive! \$\endgroup\$ – Jonnny Nov 20 '15 at 14:09
  • 1
    \$\begingroup\$ @Jonnny Yeah - it's a work in progress, one day, it'll be better than Seriously. But for now... We wait. If you want a good golfing language, see the Seriously answer, it's got some crazy stuff in it. \$\endgroup\$ – Addison Crump Nov 20 '15 at 14:30
  • 1
    \$\begingroup\$ @Jonnny Also, if you think you might be interested in my language, use is:answer Vitsy in the search bar to find some more interesting answers that are in this language. c: \$\endgroup\$ – Addison Crump Nov 20 '15 at 14:35
18
\$\begingroup\$

JavaScript ES6, 230 218 198 196 192 188 185 bytes

for(x=99,z=(a=' on the wall')=>`${x||99} bottle${1-x?'s':''} of beer`+a;x;)alert(z()+', '+z`.
`+(--x?'Take one down and pass it around, ':'Go to the store and buy some more, ')+z()+'.')

Just just trimming off a few bytes while still keeping it looking clean and understandable.

3 most recent revisions:

for(x=99,z=a=>`${x||99} bottle${1-x?'s':''} of beer${a||' on the wall'}`;x;)alert(z()+', '+z(`.
`)+(--x?'Take one down and pass it around, ':'Go to the store and buy some more, ')+z()+'.')

for(x=99,z=a=>(x||99)+' bottle'+(1-x?'s':'')+' of beer',w=' on the wall';x;)alert(z()+w+', '+z()+(--x?`.
Take one down and pass it around, `:`.
Go to the store and buy some more, `)+z()+w+'.')

for(x=99,o=' bottle',q=b=o+'s',e=' of beer',w=e+" on the wall";x;)alert(x+b+w+', '+x+b+e+(--x?`.
Take one down and pass it around, `+x:`.
Go to the store and buy some more, 99`)+(b=1-x?q:o)+w+'.')
\$\endgroup\$
  • 1
    \$\begingroup\$ 2 bytes saved by putting the variables outside of the loop controls:x=99;w=" on the wall";e=" of beer";o=" bottle";b=o+"s";for(z="Go to the store and buy some more, "+x+b;0<x;)console.log(x+(2>x?o:b)+e+w+", "+x+(2>x?o:b)+e+".\n"+(1>--x?z:"Take one down and pass it around, "+x+(2>x?o:b))+e+w+".") \$\endgroup\$ – Generic User Nov 18 '15 at 22:42
  • \$\begingroup\$ That's not what's saving those 2 bytes in your code. It's actually the removal of the parenthesis around (--x<1). For now I'll leave the variables inside the for statement for readability purposes to keep them all together. \$\endgroup\$ – Adam Dally Nov 18 '15 at 22:57
  • 1
    \$\begingroup\$ @Stefnotch If you are wondering, I found this edit by examining my function calls...but I don't think this was your intent. Your advice is still relevant as a last resort, though. \$\endgroup\$ – Adam Dally Nov 22 '15 at 16:49
  • 1
    \$\begingroup\$ @Paŭlo Ebermann It does execute alert for each verse, but you are free to change it to console.log to execute in the console, which would make it 194 bytes. Plus alerting the entire lyrics in one go doesn't work in Firefox, at least...it trims off a good 5-10 verses. \$\endgroup\$ – Adam Dally Nov 23 '15 at 2:36
  • 1
    \$\begingroup\$ @Stefnotch. Well that 1-x is proving useful at the moment. \$\endgroup\$ – Adam Dally Nov 24 '15 at 19:00
17
\$\begingroup\$

JavaScript ES6, 328 318 307 305 bytes

Is an anonymous function. Add f= at the beginning to make function and f() to execute.

x=>eval('s=o=>v=(o?o:" no more")+" bottle"+(1==o?"":"s");for(o="",i=99;i>0;)o+=`${s(i)}@ on the wall, ${v}@.\nTake one down, pass it around, ${s(--i)}@ on the wall.\n`;o+`No more bottles@ on the wall, no more bottles@.\nGo to the store and buy some more, 99 bottles@ on the wall.`'.replace(/@/g," of beer"))
\$\endgroup\$
  • 2
    \$\begingroup\$ Pretty would be a lot more interesting if it was more than just one long string concatenation \$\endgroup\$ – Sp3000 Nov 18 '15 at 16:50
  • 9
    \$\begingroup\$ Why the random ASCII art copied from another site? \$\endgroup\$ – feersum Nov 18 '15 at 19:07
  • 7
    \$\begingroup\$ Especially since it doesn't work, it alerts:,+No, on the wall,,. Go to the store and buy some more, 99 bottles of beer on the wall. \$\endgroup\$ – Generic User Nov 18 '15 at 22:02
12
\$\begingroup\$

C, 197 196 bytes

main(i){for(i=299;i--/3;printf("%d bottle%s of beer%s%s",i/3?:99,"s"+5/i%2,i%3?" on the wall":i^3?".\nTake one down and pass it around":".\nGo to the store and buy some more",~i%3?", ":".\n\n"));}

I think I have reached the limit of this approach.

\$\endgroup\$
  • 1
    \$\begingroup\$ "%d bottles of beer on the wallTake one down and pass it aroundGo to the store and buy some more,.\n"main(){for(;;)printf();} alone is 126 bytes, so that represents a hard lower bound unless someone finds a way to compress or reuse parts of the strings without significant overhead. I suspect you may have reached the limit of approaches in general, plus or minus a few bytes. \$\endgroup\$ – Ray Nov 19 '15 at 23:31
12
\$\begingroup\$

Java 304 301 300 Bytes

First time posting an answer. I heard we could use enum but could not find how.

class a{public static void main(String[]a){String b=" of beer",c=" on the wall",n=".\n",s;for(int i=100;i-->1;){s=" bottle"+(i>1?"s":"");System.out.println(i+s+b+c+", "+i+s+b+n+(i<2?"Go to the store and buy some more, 99":"Take one down and pass it around, "+(i-1))+" bottle"+(i!=2?"s":"")+b+c+n);}}}

Ungolfed

class a{
    public static void main(String[]a) {
        String b=" of beer",c=" on the wall",n=".\n",s;
        for (int i=100;i-->1;){
            s=" bottle"+(i>1?"s":"");
            System.out.println(i
                    +s+b+c+", "+i
                    +s+b+n
                    +(i<2?"Go to the store and buy some more, 99":"Take one down and pass it around, "+(i-1))
                    +" bottle"+(i!=2?"s":"")+b+c+n);
        }
    }
}

Thanks to quartata and J Atkin

\$\endgroup\$
  • \$\begingroup\$ You can save 2 bytes by using i<2 in place of i==1 and i>2 here: i!=2. \$\endgroup\$ – J Atkin Nov 21 '15 at 19:14
  • \$\begingroup\$ @JAtkin Thank you. For the first one it is ok, the output stays the same. But for the second one, if I make the change, the last line will print 99 bottle and not 99 bottles \$\endgroup\$ – Yassin Hajaj Nov 21 '15 at 19:26
  • \$\begingroup\$ Actually I had just noticed that, since I'm trying to rework your (very nice) code into groovy to see if its sorter than mine. \$\endgroup\$ – J Atkin Nov 21 '15 at 19:28
  • 1
    \$\begingroup\$ As it turns out, this is good for java, but this doesn't work well for groovy (213 vs 245 bytes). \$\endgroup\$ – J Atkin Nov 21 '15 at 19:37
  • 1
    \$\begingroup\$ Not really, groovy is one of the JVM languages. Fo most applications groovy code is shorter than the java code that does the same thing. goovy-lang.org \$\endgroup\$ – J Atkin Nov 21 '15 at 20:47
11
\$\begingroup\$

Templates Considered Harmful, 667 bytes

Ap<Fun<Ap<Fun<Cat<Cat<Cat<Cat<Ap<A<1,1>,A<1>>,A<2,1>>,St<44,32>>,Ap<A<1,1>,A<1>>>,If<A<1>,Cat<Cat<Cat<Cat<St<46,10,84,97,107,101,32,111,110,101,32,100,111,119,110,32,97,110,100,32,112,97,115,115,32,105,116,32,97,114,111,117,110,100,44,32>,Ap<A<1,1>,Sub<A<1>,T>>>,A<2,1>>,St<46,10,10>>,Ap<A<0>,Sub<A<1>,T>>>,Cat<Cat<Cat<St<46,10,71,111,32,116,111,32,116,104,101,32,115,116,111,114,101,32,97,110,100,32,98,117,121,32,115,111,109,101,32,109,111,114,101,44,32>,Ap<A<1,1>,I<98>>>,A<2,1>>,St<46>>>>>,I<98>>>,Fun<Cat<Cat<Cat<Add<A<1>,T>,St<32,98,111,116,116,108,101>>,If<A<1>,St<'s'>,St<>>>,St<32,111,102,32,98,101,101,114>>>,St<32,111,110,32,116,104,101,32,119,97,108,108>>

Sort of expanded:

Ap<
    Fun<
        Ap<
            Fun<
                Cat<
                    Cat<Cat<Cat< Ap<A<1,1>,A<1>> , A<2,1> >, St<44,32> >, Ap<A<1,1>,A<1>> >,
                    If<A<1>,
                        Cat<Cat<Cat<Cat< St<46,10,84,97,107,101,32,111,110,101,32,100,111,119,110,32,97,110,100,32,112,97,115,115,32,105,116,32,97,114,111,117,110,100,44,32> , Ap<A<1,1>,Sub<A<1>,T>> >, A<2,1> >, St<46,10,10> >, Ap<A<0>,Sub<A<1>,T>> >,
                        Cat<Cat<Cat< St<46,10,71,111,32,116,111,32,116,104,101,32,115,116,111,114,101,32,97,110,100,32,98,117,121,32,115,111,109,101,32,109,111,114,101,44,32> , Ap<A<1,1>,I<98>> >, A<2,1> >, St<46> >
                    >
                >
            >,
            I<98>
        >
    >,
    Fun< Cat<Cat<Cat< Add<A<1>,T> , St<32,98,111,116,116,108,101> >, If<A<1>,St<'s'>,St<>>  >, St<32,111,102,32,98,101,101,114> > >,
    St<32,111,110,32,116,104,101,32,119,97,108,108>
>
\$\endgroup\$
10
\$\begingroup\$

///, 341 bytes

/-/\/\///+/ bottle-)/\/&\/<\/
-(/\/\/?\/ ->/+s of beer-^/> on the wall-!/^,-$/>.
-@/$Take one down and pass it around,-#/^.
-*/?1@?0#<0!?0@-%/99!?9@?8#<8!?8@?7#<7!?7@?6#<6!?6@?5#<5!?5@?4#<4!?4@?3#<3!?3@?2#<2!?2@?1#<1!-&/?9#
%*-</
9(9/%*/</
8(8)7(7)6(6)5(5)4(4)3(3)2(2)1(1)0(0-
0/
- 0/ /#/1+s/1+/
% 01$Go to the store and buy some more, 099^.

It would need 99 years to write a proper explanation of this code.

I would probably just include the result of every stage...

Basically, this compresses the lyrics repeatedly (as is every answer in ///).

Try it online!

Each step of decompression

Since replacements followed by replacements will have the string //, it will appear often.

It appears often enough that I decided to compress // into -.

When this is decompressed, the result is as follows:

/+/ bottle//)/\/&\/<\/
//(/\/\/?\/ //>/+s of beer//^/> on the wall//!/^,//$/>.
//@/$Take one down and pass it around,//#/^.
//*/?1@?0#<0!?0@//%/99!?9@?8#<8!?8@?7#<7!?7@?6#<6!?6@?5#<5!?5@?4#<4!?4@?3#<3!?3@?2#<2!?2@?1#<1!//&/?9#
%*//</
9(9/%*/</
8(8)7(7)6(6)5(5)4(4)3(3)2(2)1(1)0(0//
0/
// 0/ /#/1+s/1+/
% 01$Go to the store and buy some more, 099^.

The string bottle only appeared three times, but I compressed it to + anyways:

/)/\/&\/<\/
//(/\/\/?\/ //>/ bottles of beer//^/> on the wall//!/^,//$/>.
//@/$Take one down and pass it around,//#/^.
//*/?1@?0#<0!?0@//%/99!?9@?8#<8!?8@?7#<7!?7@?6#<6!?6@?5#<5!?5@?4#<4!?4@?3#<3!?3@?2#<2!?2@?1#<1!//&/?9#
%*//</
9(9/%*/</
8(8)7(7)6(6)5(5)4(4)3(3)2(2)1(1)0(0//
0/
// 0/ /#/1 bottles/1 bottle/
% 01$Go to the store and buy some more, 099^.

Then, ) corresponds to /&/</ followed by a newline, and ( corresponds to //?/ , which are patterns that will be often used later:

/>/ bottles of beer//^/> on the wall//!/^,//$/>.
//@/$Take one down and pass it around,//#/^.
//*/?1@?0#<0!?0@//%/99!?9@?8#<8!?8@?7#<7!?7@?6#<6!?6@?5#<5!?5@?4#<4!?4@?3#<3!?3@?2#<2!?2@?1#<1!//&/?9#
%*//</
9//?/ 9/%*/</
8//?/ 8/&/</
7//?/ 7/&/</
6//?/ 6/&/</
5//?/ 5/&/</
4//?/ 4/&/</
3//?/ 3/&/</
2//?/ 2/&/</
1//?/ 1/&/</
0//?/ 0//
0/
// 0/ /#/1 bottles/1 bottle/
% 01$Go to the store and buy some more, 099^.

Now, we would decompress some useful strings:

  • > decompresses to bottles of beer
  • ^ decompresses to bottles of beer on the wall
  • ! decompresses to ^,, where ^ is the one above.
  • $ decompresses to >.\n, where > is the first rule and \n is a newline.
  • @ decompresses to $ followed by Take one down and pass it around,, where $ is the rule above.

The decompressed code now becomes:

/*/?1 bottles of beer.
Take one down and pass it around,?0 bottles of beer on the wall.
<0 bottles of beer on the wall,?0 bottles of beer.
Take one down and pass it around,//%/99 bottles of beer on the wall,?9 bottles of beer.
Take one down and pass it around,?8 bottles of beer on the wall.
<8 bottles of beer on the wall,?8 bottles of beer.
Take one down and pass it around,?7 bottles of beer on the wall.
<7 bottles of beer on the wall,?7 bottles of beer.
Take one down and pass it around,?6 bottles of beer on the wall.
<6 bottles of beer on the wall,?6 bottles of beer.
Take one down and pass it around,?5 bottles of beer on the wall.
<5 bottles of beer on the wall,?5 bottles of beer.
Take one down and pass it around,?4 bottles of beer on the wall.
<4 bottles of beer on the wall,?4 bottles of beer.
Take one down and pass it around,?3 bottles of beer on the wall.
<3 bottles of beer on the wall,?3 bottles of beer.
Take one down and pass it around,?2 bottles of beer on the wall.
<2 bottles of beer on the wall,?2 bottles of beer.
Take one down and pass it around,?1 bottles of beer on the wall.
<1 bottles of beer on the wall,//&/?9 bottles of beer on the wall.

%*//</
9//?/ 9/%*/</
8//?/ 8/&/</
7//?/ 7/&/</
6//?/ 6/&/</
5//?/ 5/&/</
4//?/ 4/&/</
3//?/ 3/&/</
2//?/ 2/&/</
1//?/ 1/&/</
0//?/ 0//
0/
// 0/ / bottles of beer on the wall.
/1 bottles/1 bottle/
% 01 bottles of beer.
Go to the store and buy some more, 099 bottles of beer on the wall.
\$\endgroup\$
10
\$\begingroup\$

Haskell, 228 223 bytes

o=" of beer on the wall"
a n=shows n" bottle"++['s'|n>1]
b 1="Go to the store and buy some more, "++a 99
b n="Take one down and pass it around, "++a(n-1)
f=[99,98..1]>>= \n->[a n,o,", ",a n," of beer.\n",b n,o,".\n\n"]>>=id

Function f returns a string with the lyrics.

\$\endgroup\$
8
\$\begingroup\$

JavaScript ES6, 237 217 208 203 195 193 189 186 bytes

It is getting pretty hard to golf this...
Edit 1: Somebody totally outgolfed me, looks like I have to try harder if I want to have the best Javascript answer.
Edit 2: I honestly can't believe that I managed to golf it that much!

for(i=99,Y=" on the wall",o=k=>k+(i||99)+` bottle${i==1?'':'s'} of beer`;i;)alert(o``+Y+o`, `+o(--i?`.
Take one down and pass it around, `:`.
Go to the store and buy some more, `)+Y+`.`)

Did I mess up somewhere? I also apologize for using alert, if you want to test my code, replace it with console.log.

Currently, there is one other notable Javascript answer: "99 Bottles of Beer". Check it out! :D

\$\endgroup\$
  • \$\begingroup\$ I would re-examine your conditions and you should be able to trim off a couple bytes. Good effort keeping up, though! \$\endgroup\$ – Adam Dally Nov 22 '15 at 16:56
  • \$\begingroup\$ @AdamDally Ok!! :D But I don't like copying other people's stuff...(I would feel guilty if I just copied your code...though it would be "acceptable", if I found some improvements) :D \$\endgroup\$ – Stefnotch Nov 23 '15 at 17:01
  • \$\begingroup\$ @AdamDally Yay, I messed around with my functions and I saved quite a bunch of bytes! (The crossed out line is getting longer and longer..) \$\endgroup\$ – Stefnotch Nov 23 '15 at 18:06
  • \$\begingroup\$ Excellent! Unless there is some alternate path I've completely overlooked I feel like we are both nearing the end. \$\endgroup\$ – Adam Dally Nov 24 '15 at 2:15
8
\$\begingroup\$

Vim, 139 bytes

Saved 6 bytes due to xsot.

i, 99 bottles of beer on the wall.<ESC>YIGo to t<SO> store and buy some more<ESC>qa
3P2xgJX$12.+<CAN>YITake one down a<SO> pass it around<ESC>o<ESC>q98@adk?s
xn.n.ZZ

This is my first attempt at golfing Vim commands, although apparently it's quite popular. I've included the final ZZ in the byte count (write to file and exit) as it seems to be the accepted norm.

Side note: mission accomplished.


Explanation

Command                                    Effect
-------------------------------------------------------------------------------------------
i, 99 bottles of beer on the wall.<ESC>    insert text at cursor
Y                                          copy this line into buffer
IGo to t<SO> store and buy some more<ESC>  insert text at beginning of line
                                           auto-complete "the" (<Ctrl-N>, searches forward)
qa                                         begin recording macro into "a"
<LF>                                       move down one line (if present)
3P                                         paste 3 times before cursor
2x                                         delete 2 characters at cursor
gJ                                         join this line with next (without space between)
X                                          delete character before cursor
$                                          move to last non-whitespace character of line
12.                                        repeat the last edit command (X) 12 times
+                                          move to column 0 of next line
<CAN>                                      numeric decrement (<Ctrl-X>)
Y                                          copy this line into buffer
ITake one down a<SO> pass it around<ESC>   insert text at beginning of line
                                           auto-complete "and" (<Ctrl-N>, searches forward)
o<ESC>                                     insert text on new line
q                                          stop recording macro
98@a                                       repeat macro "a" 98 times
dk                                         delete upwards (this line and the one above it)
?s<LF>                                     move to previous /s/
x                                          delete character at cursor
n.n.                                       repeat last match and delete 2 times
ZZ                                         write to file and exit
\$\endgroup\$
  • 1
    \$\begingroup\$ Slight improvement: i99 bottles of beer on the wall.<ESC>Yqa3P$r,J5wDr.+<CAN>YITake one down and pass it around, <ESC>o<ESCjq98@aiGo to the store and buy some more, <ESC>kdk?s<LF>xnxnxZZ \$\endgroup\$ – xsot Feb 23 '16 at 3:29
  • \$\begingroup\$ @xsot thanks for that. I somehow completely overlooked / and ?. \$\endgroup\$ – primo Feb 23 '16 at 6:06
  • \$\begingroup\$ btw it's possible to reach 153 on anagol with this improvement \$\endgroup\$ – xsot Feb 23 '16 at 6:17
  • \$\begingroup\$ @xsot got it ;) \$\endgroup\$ – primo Feb 23 '16 at 6:53
7
\$\begingroup\$

JavaScript ES6, 210 209 205 199 198 196 bytes

s=""
for(i=299;--i>1;s+=`${i/3|0||99} bottle${5/i^1?"s":""} of beer`+(i%3?" on the wall":i^3?`.
Take one down and pass it around`:`.
Go to the store and buy some more`)+(~i%3?", ":`.

`));alert(s)

This is a crude translation of my C submission. I don't actually know javascript so there is definitely room for improvement.

Edit: Neat, I discovered backticks

\$\endgroup\$
  • \$\begingroup\$ you could replace the console.log with alert and you could use ` instead of the ". Then you can replace \n with a newline. (The ticks are used for template strings, those strings can have newlines...) Also, congrats for beating me! \$\endgroup\$ – Stefnotch Nov 19 '15 at 16:06
  • 1
    \$\begingroup\$ I think I'll leave the output alone unless someone else beats me as console.log is easier to test. Anyway, thanks for exposing me to backticks! \$\endgroup\$ – xsot Nov 19 '15 at 16:14
  • \$\begingroup\$ Wohoo, outgolfed yours! Also, thanks for using || in your code, it sure came in handy... (Meh, you can change the console.log, and my victory will be reduced to nothing.. XD ) \$\endgroup\$ – Stefnotch Nov 19 '15 at 16:37
  • 1
    \$\begingroup\$ You're proving challenging to keep up with! Alas, it would be interesting to see a breakdown of your code. \$\endgroup\$ – Adam Dally Nov 20 '15 at 3:55
  • 1
    \$\begingroup\$ @AdamDally Basically, each verse is split into 3 parts with the following structure: %d bottle%s of beer%s%s. The index of each verse (number of bottles) is calculated as i/3|0 while the index of each substring is simply i%3. \$\endgroup\$ – xsot Nov 20 '15 at 12:11
6
\$\begingroup\$

Python 2, 204 bytes

n=198
while n:s="bottle%s of beer"%"s"[:n^2>1];print n%2*"GToa kteo  otnhee  dsotwonr ea nadn dp absusy  isto maer omuonrde,,  "[n>1::2]+`n/2or 99`,s,"on the wall"+[", %d %s."%(n/2,s),".\n"[:n]][n%2];n-=1

The spec is quite underspecified in terms of whitespace, so here I'm assuming that the last line needs to have a single trailing newline. If the spec clarifies otherwise I'll update this answer.

I'm pretty happy with this, but looking at anarchy golf I feel like this can be golfed still, possibly with a different approach.

\$\endgroup\$
6
\$\begingroup\$

Windows Batch, 376 bytes

Very very long and ugly:

@echo off
setlocal enabledelayedexpansion
set B=bottles
set C=on the wall
set D=of beer
for /l %%* in (99,-1,1) do (
set A=%%*
if !A! EQU 1 set B=bottle
echo !A! !B! !D! !C!, !A! !B! !D!.
set /a A=!A!-1
if !A! EQU 1 set B=bottle
if !A! EQU 0 (
echo Go to the store and buy some more, 99 bottles !D! !C!.
) else (
echo Take one down and pass it around, !A! !B! !D! !C!.
echo.
))
\$\endgroup\$
6
\$\begingroup\$

Brainfuck, 743 bytes

++++++++++>>--->++++>------>-->>++>+>>+>->++[[>+++++++[>++>+>+<<<-]<-]+<+++]>>>>>--
>>-->>++>->+++[<]>[-<<+[<->-----]<---[<[<]>[->]<]+<[>-]>[-<++++++++++<->>>]-[<->---
--]<+++[<[<]>[+>]<]<->>>[>[[>]<<<<.<<<<---.>>>-.<<<++++.<.>>>.-.<<.<.>-.>>+.<+++.>-
.<<<.>---.>>.<<+++.<.>>>++.<<---.>----..<<.>>>>--.+++<<+.<<.>.>--.>-.<+++.->-.+<<++
+.<<.>.<<<<-<]>[[>]<<<-.<<<.<<<.>>.>.<<< . > > .<++++.---.<.>>-.+.>.<--.<.<.>----.>
>-.<<+++.<.>--.>+++.++++.<<.>>------.>+.--.<<+++.<.>>>.++.<-.++<.-<<.>.<<<<-<<<++++
+++++.>>>]<+>]<++[<<[<]>[.>]>>>>>>.>--.>>.<..->>.<<<+++.<<<<-[>>>>>.[<]]<[>]>+>>>.>
>>.<<+.<.>----.+++..->-.++[<<]<-[>>>>>.>>>.-.+<<<.>>.<++++.---.<.>>+++.---<----.+++
>>>..[<<]]<<[>]>-[>>>>++.--<.<<<+[>>>.<<<<]>[>]<-<]>>[>>.>.<<<<]>[<<++>]<[>]<-]>+>]

Try it online!

The above uses wrapping cells in a few places to save instructions. I've also made a non-wrapping version in 755 instructions.


Uncompressed

The following is a polyglot in Brainfuck Annotation Language.

; byte sequence
; \n _ _ _ _ c \n comma space d t o l T G
++++++++++>>
--->++++>------>-->>++>+>>+>->++
[[>+++++++[>++>+>+<<<-]<-]+<+++]
>>>>>-->>-->>++>->+++[<]

c = 0
n = 100

>
while(n)
[
  n = n minus 1
  -<<
  N = str(n)
  ; first time \n _ becomes 9 9
  +[<->-----]<---[<[<]>[->]<]
  +<[>-]>[-<++++++++++<->>>]
  -[<->-----]<+++[<[<]>[+>]<]

  <->>>
  if(c)
  [
    >
    if(n)
    [
      'Take one down and'
      [>]<<<<.<<<<---.>>>-.<<<++++.<.>>>.-.<<.<.>-.>>+.<+++.>-.<<<.>---.>>.<<+++.
      ' pass it around' comma space
      <.>>>++.<<---.>----..<<.>>>>--.+++<<+.<<.>.>--.>-.<+++.->-.+<<+++.<<.>.<<<<-<
    ]>
    else
    [
      'Go to the store and'
      [>]<<<-.<<<.<<<.>>.>.<<<.>>.<++++.---.<.>>-.+.>.<--.<.<.>----.>>-.<<+++.
      ' buy some more' comma space
      <.>--.>+++.++++.<<.>>------.>+.--.<<+++.<.>>>.++.<-.++<.-<<.>.<<<<-
      N = '9'
      N
      <<<+++++++++.>>>
    ]
    <+>
  ]

  c = c plus 2
  <++

  while(c)
  [
    N
    <<[<]>[.>]>>>
    ' bottle'
    >>>.>--.>>.<..->>.<<<+++.<<<<
    if(n minus 1) 's'
    -[>>>>>.[<]]<[>]>+
    ' of beer'
    >>>.>>>.<<+.<.>----.+++..->-.++

    [<<]<-
    if(c minus 1)
    [
      ' on the wall'
      >>>>>.>>>.-.+<<<.>>.<++++.---.<.>>+++.---<----.+++>>>..[<<]
    ]

    <<[>]>-
    if(c minus 2)
    [
      period newline
      >>>>++.--<.<<<+
      if(c minus 1) newline
      [>>>.<<<<]>[>]<-<
    ]>>
    else
    [
      comma space
      >>.>.<<<<
    ]

    if(not n) c = c minus 2
    >[<<++>]

    c = c minus 1
    <[>]<-
  ]

  c = 1
  >+>
]
\$\endgroup\$
5
\$\begingroup\$

Python, 254 bytes

b,o,s,t="bottles of beer","on the wall","bottle of beer",".\nTake one down and pass it around,"
i=99;exec'print i,b,o+",",i,b+t,i-1,b,o+".\\n";i-=1;'*97
print"2",b,o+", 2",b+t+" 1",s,o+".\n\n1",s,o+", 1",s+".\nGo to the store, buy some more, 99",b,o+"."

Pretty straightforward, assign some of the most common phrases, print each bit from 99 to 3, then print the last lines by adding together the variables and some strings.

\$\endgroup\$
5
\$\begingroup\$

Labyrinth, 1195 1190 932 bytes

"{"9"
^ }
 ""
 <
 713.101.801..:611.111.89.23}!:({.23.44.001.011.711.111.411.79.23.611.501.23..:511.79.211.23.001.011.79.23.011.911.111.001.23.101.(.:111.23.101.701.79.48\.411..:101.89.23.201.111.23.511.101.801..:611.111.89.23}!:{.23.44..:801.79.911.23.101.401.611.23.(.:111.23.411..:101.89.23.201.111.23.511.101.801..:611.111.89.23}!:{
 _
 3`<
 _ ( 
""""
"
{(32.111.102.32.98.101:..114.32.111:.(.32.116.104.101.32.119.97.108:..46.\\49.32.98.111.116:..108.101.32.111.102.32.98.101:..114.32.111:.(.32.116.104.101.32.119.97.108:..44.32.49.32.98.111.116:..108.101.32.111.102.32.98.101:..114.46.\71.111.32.116.111.32.116.104.101.32.115:.).111.114.101.32.97.110.100.32.98.117.121.32.115.111.109.101.32.109.111.114.101.44.32.9!9!32.98.111.116:..108.101.115.32.111.102.32.98.101:..114.32.111:.(.32.116.104.101.32.119.97.108:..46.@
 )
 }
 <
 87\\.64..:801.79.911.23.101.401.611.23.(.:111.23.411..:101.89.23.201.111.23.511
 _
 3`<
 _ ( 
v"""

This is a bit excessive...

While Labyrinth isn't particularly good at printing strings (because you need to push all the character codes), I think it should be possible to do better than this by using more but shorter long lines and getting even crazier with the grid rotation.

As I think any golfing improvements will substantially change the structure of this code, I'll wait with an explanation until I'm out of ideas how to golf it further.

\$\endgroup\$
5
\$\begingroup\$

Python 2, 195

i=198
while i:s=`i/2or 99`+' bottle%s of beer'%'s'[1<i<4:];print['%s, '+s+'.','Take one down and pass it around, %s.\n',"Go to the store and buy some more, %s."][i%2+1/i]%(s+' on the wall');i-=1

Took the i/2 idea from Sp3000's answer.

\$\endgroup\$
5
\$\begingroup\$

JavaScript ES6, 214 bytes

Edit: Deleted all previous code, view edits if you want to see the older code.

Limited popups:

p='.';o=" of beer";e=o+" on the wall";i=99;u=m=>i+" bottle"+(i==1?'':'s');while(i>0){alert(u()+e+", "+u()+o+p+(--i>0?"Take one down and pass it around, "+u()+e:"Go to the store and buy some more, 99 bottles"+e)+p)}

Expanded:

p='.';
o=" of beer";
e=o+" on the wall";
i=99;
u=m=>i+" bottle"+(i==1?'':'s');
while(i>0){
    alert(u()+e+", "+u()+o+p+(--i>0?"Take one down and pass it around, "+u()+e:"Go to the store and buy some more, 99 bottles"+e)+p)
}

@commenters: Thanks for the idea of arrow functions, saved 15 bytes

For infinite beer just use this code here, 212 bytes

p='.';o=" of beer";e=o+" on the wall";i=99;u=m=>i+" bottle"+(i==1?'':'s');while(i>0){alert(u()+e+", "+u()+o+p+(--i>0?"Take one down and pass it around, "+u()+e:"Go to the store and buy some more, "+u(i=99)+e)+p)}
\$\endgroup\$
  • 1
    \$\begingroup\$ I can't get the code to run, what browser/environment are you using? "SyntaxError: missing ; before statement" Also, have a look at arrow functions! \$\endgroup\$ – Stefnotch Nov 18 '15 at 19:03
  • \$\begingroup\$ Took me a moment to find the syntax error +o' as it were then changed to +o+'. Also saw opportunity for changing the loop and answer. Will be checking out arrow functions now :) \$\endgroup\$ – ŽaMan Nov 18 '15 at 19:45
  • 1
    \$\begingroup\$ 232 bytes for the last solution: b=a=>a+" bottle"+(1<a?"s":"");for(i=100;100>--i;)l="\n",p="."+l,o=" of beer",e=o+" on the wall",alert(l+b(i)+e+", "+b(i)+o+p+(1<i?"Take one down and pass it around, "+b(i-1)+e:"Go to the store and buy some more, "+b((i=100)-1)+e)+p) \$\endgroup\$ – Generic User Nov 18 '15 at 22:48
  • \$\begingroup\$ After some playing around, I'm sticking to my while loop and I'll soon now post the resulting code. Thank you for the code review! :) \$\endgroup\$ – ŽaMan Nov 19 '15 at 4:21
5
\$\begingroup\$

CJam, 149 148 146 144 138 137 134 bytes

00000000: 39 39 7b 5b 22 2c 2e 22 22 01 bd 8f 2d b4 49 b5 f5  99{[",.""...-.I..
00000011: 9d bd 21 e8 f2 72 27 df 4d 4f 22 7b 32 36 39 62 32  ..!..r'.MO"{269b2
00000022: 35 62 27 61 66 2b 27 6a 53 65 72 28 65 75 5c 2b 2a  5b'af+'jSer(eu\+*
00000033: 7d 3a 44 7e 4e 4e 32 24 32 3e 29 34 24 4a 3c 5c 4e  }:D~NN2$2>)4$J<\N
00000044: 5d 73 27 78 2f 39 39 40 2d 73 2a 7d 2f 27 73 2d 5d  ]s'x/99@-s*}/'s-]
00000055: 22 07 9c 4b a2 4e 15 d7 df d5 82 88 c9 d9 a7 ad 37  "..K.N..........7
00000066: 16 7e 76 22 44 33 35 2f 28 5d 22 41 90 1d b1 f3 69  .~v"D35/(]"A....i
00000077: ba 3d 05 45 81 50 af 07 e4 1b 38 f7 19 22 44        .=.E.P....8.."D

The above hexdump can be reversed with xxd -r. Try it online in the CJam interpreter.

At the cost of 9 extra bytes, for a total of 143 bytes, we can avoid unprintable characters:

99{[", X bottles of beer on the wall."NN2$2>)4$J<\N]s'X/99@-s*}/'s-]"Take one down and pass it around"*35/("Go to the store and buy some more"\

How it works

99{         e# For each I in [0 ... 98]:
  [         e# 
    ",."    e#     Push that string.
    "…"     e#     Push a string.
    {       e#     Define a decoder function:
      269b  e#       Convert the string from base 269 to integer.
      25b   e#       Convert from integer to base 25.
      'af+  e#       Add 'a' to each base-25 digit.
      'jSer e#       Replace j's with spaces.
      (     e#       Shift the first character from the resulting string.
      eu    e#       Convert it to uppercase.
      \+    e#       Prepend it to the remaining string.
      *     e#       Join the string/array on the stack, using the 
            e#       generated string as delimiter.
    }:D~    e#     Name the function D and execute it.
            e#     This pushes ", x bottles of beer on the wall.".
    NN      e#     Push two linefeeds.
    2$      e#     Push a copy of the generated string.
    2>)     e#     Discard the first two characters and pop the dot.
    4$      e#     Push another copy of the generated string.
    J<      e#     Discard all but the first 19 characters.
            e#     This pushes ", x bottles of beer on the wall".
    \N      e#     Swap the string with the dot and push a linefeed.
  ]s        e#   Collect in an array and cast to string.
  'x/       e#   Split at occurrences of 'x'.
  99@-      e#   Rotate I on top of 99 and compute their difference.
  s*        e#   Cast to string and and join.
            e#   This replaces x's with 99-I.
}/          e#
's-         e# Remove all occurrences of 's' for the last generated string.
]           e# Wrap the entire stack in an array.
"…"D        e# Join the array with separator "Take one down and pass it around".
35/(        e# Split into chunks of length 35 and shift out the first.
            e# This shifts out ", 99 bottles of beer on the wall.\n\n".
]           e# Wrap the modified array and shifted out chunk in an array.
"…"D        e# Join the array with separator "Go to the store and buy some more".
\$\endgroup\$
  • \$\begingroup\$ Base 259? Interesting. \$\endgroup\$ – lirtosiast Nov 22 '15 at 21:42
  • \$\begingroup\$ Base 256 had carriage returns, which do not work with the online interpreter. Luckily, base 259 produces no characters outside the ISO 8559-1 range. \$\endgroup\$ – Dennis Nov 22 '15 at 21:44
  • \$\begingroup\$ I assumed CJam would be at least 2 bytes shorter than GolfScript - almost trivially. Wasn't expecting 137 though! \$\endgroup\$ – primo Nov 23 '15 at 5:00
  • 1
    \$\begingroup\$ @primo To be fair, most of the savings are from base conversion. Sadly, using base twice already adds 8 bytes in GolfScript... \$\endgroup\$ – Dennis Nov 23 '15 at 5:30
5
\$\begingroup\$

C, 303 299 297 bytes

#define B"%d bottle%s of beer"    
#define O" on the wall"
#define P printf(
#define V(n,m,S)q(n);P O);P", ");q(n);P S);q(m);P".\n");
*s[]={"","s"};q(n){P B,n,s[n>1]);}main(){for(int i=99;--i;){V(i+1,i,".\nTake one down and pass it around, ")P"\n");}V(1,99,".\nGo to the store and buy some more, ");}

Compile with gcc -std=c99 -w.

\$\endgroup\$
  • 1
    \$\begingroup\$ Golf down to 300 bytes: ...for(int i=99;--i;){V(i+1,i,".... \$\endgroup\$ – Glenn Randers-Pehrson Nov 21 '15 at 21:51
  • \$\begingroup\$ @GlennRanders-Pehrson Thanks. I also removed the linebreak before main(). \$\endgroup\$ – firefrorefiddle Nov 23 '15 at 9:00
5
\$\begingroup\$

GolfScript, 143 bytes

[99.{[', '\.' bottle''s of beer'@(:i!>' on the wall''.
'n].1>~;5$4<\'Take one down and pass it around'i}**'Go to the store and buy some more'](

May still be room for improvement. Getting close to the final revision, I think.

\$\endgroup\$
5
\$\begingroup\$

Mathematica, 238 226 222 224 bytes

Saved several bytes thanks to Martin Büttner.

a={ToString@#," bottle",If[#<2,"","s"]," of beer"}&;b=a@#<>" on the wall"&;Echo[{b@n,", ",a@n,".
"}<>If[n<2,"Go to the store and buy some more, "<>b@99<>".","Take one down and pass it around, "<>b[n-1]<>".
"]]~Do~{n,99,1,-1}
\$\endgroup\$
5
\$\begingroup\$

Brainfuck, 4028 bytes

This is quite hideous. Lots of duplication, and very inefficient, so it won't win any prizes. However, I started it, and was determined to finish it.

I may try and improve this, but probably wont, because frankly, my brain is fucked.

Golfed

>>+++[-<+++<+++>>]>>++++++[-<++++++++++<++++++++++>>]<---<--->>>+++++[-<++++++>]
<++>>++++++++++[-<++++++++++>]<-->>++++++++++[-<+++++++++++>]<+>>++++++++++[-<++
++++++++>]<+>>++++++++++[-<++++++++++>]<++>>++++++++++[-<+++++++++++>]<++++++>>+
+++++++++[-<++++++++++>]<++++>>++++++++++[-<+++++++++++>]<-->>++++++++++[-<+++++
++++++>]<++++>>++++++++++[-<+++++++++++>]<+++++>>++++++++++[-<+++++++++++>]>++++
++++++[-<+++++++++++>]<+++++++++>>++++++++++[-<++++++++++>]<--->>+++++[-<++++++>
]<++>>++++[-<++++++++++++>]<---->>++++[-<++++++++++++>]<-->++++++++++>>+++++++++
+[-<+++++++++++>]<--->>++++++++++[-<++++++++++>]>++++++++++[-<+++++++++++>]<++>>
++++++++++[-<++++++++++>]<+++++>>++++++++++[-<+++++++++++>]<+++++++<<<<<<<<<<<<<
<<<<<<<<<<<<[>[->.>.>.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.<
<<<<<<<.>>.>>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<<<<..>>>>>>>.<.<<<<<<
<<<<<<<<<.>.->.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.>>>>>>>.
>.<<<<<<<<<<<.>>>>>>>.>>>>>.<<<<<<<<<<<<<<.<<<.>>.>>>>>>>>.<<<<<<<.<<<.>>>>>>>>>
>>>>>>>>>.<<<<<<<<<<<<<<<<.>>>>>>>>>.<.>>>.<.<<.>>>>>>>>.<<<<<.>>>>>>.<<<<<<<.<<
<..>>>>.>>>>>>>.<<<<<<<<<<<<<<<.>>>>>>>>.<.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<
<<<<<<.>>>>>>>>.<<<<.<.<<<<<<<<<<<<<<<.>.>.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.
>>.<<<<.>.>>..>>>>>.<<<<<<<<.>>.>>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<
<<<..>>>>>>>>.>..<<<<<<<<<<<<<<<<<<<]<->+++++++++>.>.>.>.>.>>>..>>.<<<<.>>>>>>.<
<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.<<<<<<<<.>>.>>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>
>>>>>>>.>.<<<<<..>>>>>>>.<.<<<<<<<<<<<<<<<.->.+++++++++>.>.>.>>>..>>.<<<<.>>>>>>
.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.>>>>>>>.>.<<<<<<<<<<<.>>>>>>>.>>>>>.<<<<<<<<<<
<<<<.<<<.>>.>>>>>>>>.<<<<<<<.<<<.>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<.>>>>>>>>>.<
.>>>.<.<<.>>>>>>>>.<<<<<.>>>>>>.<<<<<<<.<<<..>>>>.>>>>>>>.<<<<<<<<<<<<<<<.>>>>>>
>>.<.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<.>>>>>>>>.<<<<.<.<<<<<<<<<<<<<<<
.>.>.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.<<<<<<<<.>>.>>>>>>
>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<<<<..>>>>>>>>.>..<<<<<<<<<<<<<<<<<<<<]
>--[->>.>.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.<<<<<<<<.>>.>
>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<<<<..>>>>>>>.<.<<<<<<<<<<<<<<.->.
>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.>>>>>>>.>.<<<<<<<<<<<.>
>>>>>>.>>>>>.<<<<<<<<<<<<<<.<<<.>>.>>>>>>>>.<<<<<<<.<<<.>>>>>>>>>>>>>>>>>>.<<<<<
<<<<<<<<<<<.>>>>>>>>>.<.>>>.<.<<.>>>>>>>>.<<<<<.>>>>>>.<<<<<<<.<<<..>>>>.>>>>>>>
.<<<<<<<<<<<<<<<.>>>>>>>>.<.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<.>>>>>>>>
.<<<<.<.<<<<<<<<<<<<<<.>.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>
>.<<<<<<<<.>>.>>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<<<<..>>>>>>>>.>..<
<<<<<<<<<<<<<<<<<<]>>.>.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>
.<<<<<<<<.>>.>>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<<<<..>>>>>>>.<.<<<<
<<<<<<<<<<.->.>.>.>>>..>>.<<<<.>>>>>>.<<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.>>>>>>>.>
.<<<<<<<<<<<.>>>>>>>.>>>>>.<<<<<<<<<<<<<<.<<<.>>.>>>>>>>>.<<<<<<<.<<<.>>>>>>>>>>
>>>>>>>>.<<<<<<<<<<<<<<<<.>>>>>>>>>.<.>>>.<.<<.>>>>>>>>.<<<<<.>>>>>>.<<<<<<<.<<<
..>>>>.>>>>>>>.<<<<<<<<<<<<<<<.>>>>>>>>.<.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<<
<<<<<.>>>>>>>>.<<<<.<.<<<<<<<<<<<<<<.>.>.>.>>>..>>.<<<<.<<<.>>.>>.<<<<.>.>>..>>>
>>.<<<<<<<<.>>.>>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<<<<..>>>>>>>>.>..
<<<<<<<<<<<<<<<<<.>.>.>.>>>..>>.<<<<.<<<.>>.>>.<<<<.>.>>..>>>>>.<<<<<<<<.>>.>>>>
>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>>>>>>>>.>.<<<<<..>>>>>>>.<.<<<<<<<<<<<<<<.++++++
++>.>.>.>>>..>>.<<<<.<<<.>>.>>.<<<<.>.>>..>>>>>.>>>>>>>.>.>---->>+++++++++>++++<
<<.<<<<<<<<<<<<<<<.<<.>>>>>.<<<.<<.>>>>>.>.<<<.<<<.>>>>>>>>>.<<<<.<<<.>>>>>>.<<<
<<.<<<.>>>>>>>>>>>>.<<.>>>>>>>>.<<<<<.<<<<<<<<<<<<.>>>>>>>>>>>>>>>>>>>>.<<.<<<<<
<.<<<<.<<<<<<<.>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<<.>>>>>>>>>>.>>>>>>>.<<<<<<<<<
<<<<<<<<<.>>>>>>.<<<<<.>>>>>>>>>>>.<.<<<<<<<<<<<<<<..>.>.>.>>>..>>.<<<<.>>>>>>.<
<<<<<<<<.>>.>>.<<<<.>.>>..>>>>>.<<<<<<<<.>>.>>>>>>>>.>>>.<<<<<<<<.>.<<<.<<<.>>>>
>>>>>>>.>.<<<<<..>>>>>>>>.>.

Ungolfed

# SETUP COUNTERS
>>+++[-<+++<+++>>]
>>++++++[-<++++++++++<++++++++++>>]<---<--->>

# SETUP CONSTANTS
>+++++[-<++++++>]<++>
>++++++++++[-<++++++++++>]<-->        # B
>++++++++++[-<+++++++++++>]<+>        # O
>++++++++++[-<++++++++++>]<+>         # E
>++++++++++[-<++++++++++>]<++>        # F
>++++++++++[-<+++++++++++>]<++++++>   # T
>++++++++++[-<++++++++++>]<++++>      # H
>++++++++++[-<+++++++++++>]<-->       # L
>++++++++++[-<+++++++++++>]<++++>     # R
>++++++++++[-<+++++++++++>]<+++++>    # S
>++++++++++[-<+++++++++++>]           # N
>++++++++++[-<+++++++++++>]<+++++++++># W
>++++++++++[-<++++++++++>]<--->       # A
>+++++[-<++++++>]<++>                 # SPACE
>++++[-<++++++++++++>]<---->          # Comma
>++++[-<++++++++++++>]<-->            # Stop
++++++++++>                           # Newline
>++++++++++[-<+++++++++++>]<--->      # K
>++++++++++[-<++++++++++>]            # D
>++++++++++[-<+++++++++++>]<++>       # P
>++++++++++[-<++++++++++>]<+++++>     # I
>++++++++++[-<+++++++++++>]<+++++++   # U

# BACK TO START
<<<<<<<<<<<<<<<<<<<<<<<<<
[>
    [
        -> # Dec x0 counter
        .> # Print 0x char
        .> # Print x0 char
        .>
        .>.>>>..>>.<<<<.>>>>>>. # Bottles
        <<<<<<<<<.
        >>.>>.       # Of
        <<<<.
        >.>>..>>>>>. # Beer
        <<<<<<<<.
        >>.>>>>>>>>. # On
        >>>.
        <<<<<<<<.>.<<<. # The
        <<<.
        >>>>>>>>>>>.>.<<<<<.. # Wall
        >>>>>>>.     # Comma
        <.
        <<<<<<<<<<<<<<<.>.- # Counter with decrement
        >.
        >.>.>>>..>>.<<<<.>>>>>>. # Bottles
        <<<<<<<<<.
        >>.>>.       # Of
        <<<<.
        >.>>..>>>>>. # Beer
        >>>>>>>.     # Stop
        >.           # Newline
        <<<<<<<<<<<.>>>>>>>.>>>>>.<<<<<<<<<<<<<<. # Take
        <<<.
        >>.>>>>>>>>.<<<<<<<. # One
        <<<.
        >>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<.>>>>>>>>>.<. # Down
        >>>. 
        <.<<.>>>>>>>>.  # And
        <<<<<.
        >>>>>>.<<<<<<<.<<<..    # Pass
        >>>>.
        >>>>>>>.<<<<<<<<<<<<<<<. # It
        >>>>>>>>.
        <.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<.>>>>>>>>. # Around
        <<<<. # Comma
        <.
        <<<<<<<<<<<<<<<.>. # 0x and x0
        >.
        >.>.>>>..>>.<<<<.>>>>>>. # Bottles
        <<<<<<<<<.
        >>.>>.  # Of
        <<<<.
        >.>>..>>>>>. # Beer
        <<<<<<<<.
        >>.>>>>>>>>. # On
        >>>.
        <<<<<<<<.>.<<<. # The
        <<<.
        >>>>>>>>>>>.>.<<<<<.. # Wall
        >>>>>>>>.    # Stop
        >..   # Newline x2
        <<<<<<<<<<<<<<<<<<<      # Reset loop
    ]
    <-
    >+++++++++
    >.>.
    >.
    >.>.>>>..>>.<<<<.>>>>>>. # Bottles
    <<<<<<<<<.
    >>.>>.       # Of
    <<<<.
    >.>>..>>>>>. # Beer
    <<<<<<<<.
    >>.>>>>>>>>. # On
    >>>.
    <<<<<<<<.>.<<<. # The
    <<<.
    >>>>>>>>>>>.>.<<<<<.. # Wall
    >>>>>>>.     # Comma
    <.
    <<<<<<<<<<<<<<<.- # 0x with decrement
    >.+++++++++ # x0 with increment
    >.
    >.>.>>>..>>.<<<<.>>>>>>. # Bottles
    <<<<<<<<<.
    >>.>>.       # Of
    <<<<.
    >.>>..>>>>>. # Beer
    >>>>>>>.     # Stop
    >.           # Newline
    <<<<<<<<<<<.>>>>>>>.>>>>>.<<<<<<<<<<<<<<. # Take
    <<<.
    >>.>>>>>>>>.<<<<<<<. # One
    <<<.
    >>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<.>>>>>>>>>.<. # Down
    >>>. 
    <.<<.>>>>>>>>.  # And
    <<<<<.
    >>>>>>.<<<<<<<.<<<..    # Pass
    >>>>.
    >>>>>>>.<<<<<<<<<<<<<<<. # It
    >>>>>>>>.
    <.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<.>>>>>>>>. # Around
    <<<<. # Comma
    <.
    <<<<<<<<<<<<<<<.>. # Counter
    >.
    >.>.>>>..>>.<<<<.>>>>>>. # Bottles
    <<<<<<<<<.
    >>.>>.  # Of
    <<<<.
    >.>>..>>>>>. # Beer
    <<<<<<<<.
    >>.>>>>>>>>. # On
    >>>.
    <<<<<<<<.>.<<<. # The
    <<<.
    >>>>>>>>>>>.>.<<<<<.. # Wall
    >>>>>>>>.    # Stop
    >..   # Newline x2
    <<<<<<<<<<<<<<<<<<<<      # Reset outer loop
]
>-- # Decrement counter to only count from 7
# Last 8 loop
[
    -> # Dec counter
    >. # Print x0 char    
    >.
    >.>.>>>..>>.<<<<.>>>>>>. # Bottles
    <<<<<<<<<.
    >>.>>.       # Of
    <<<<.
    >.>>..>>>>>. # Beer
    <<<<<<<<.
    >>.>>>>>>>>. # On
    >>>.
    <<<<<<<<.>.<<<. # The
    <<<.
    >>>>>>>>>>>.>.<<<<<.. # Wall
    >>>>>>>.     # Comma
    <.
    <<<<<<<<<<<<<<.- # x with decrement
    >.
    >.>.>>>..>>.<<<<.>>>>>>. # Bottles
    <<<<<<<<<.
    >>.>>.       # Of
    <<<<.
    >.>>..>>>>>. # Beer
    >>>>>>>.     # Stop
    >.           # Newline
    <<<<<<<<<<<.>>>>>>>.>>>>>.<<<<<<<<<<<<<<. # Take
    <<<.
    >>.>>>>>>>>.<<<<<<<. # One
    <<<.
    >>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<.>>>>>>>>>.<. # Down
    >>>. 
    <.<<.>>>>>>>>.  # And
    <<<<<.
    >>>>>>.<<<<<<<.<<<..    # Pass
    >>>>.
    >>>>>>>.<<<<<<<<<<<<<<<. # It
    >>>>>>>>.
    <.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<.>>>>>>>>. # Around
    <<<<. # Comma
    <.
    <<<<<<<<<<<<<<. # Count
    >.
    >.>.>>>..>>.<<<<.>>>>>>. # Bottles
    <<<<<<<<<.
    >>.>>.  # Of
    <<<<.
    >.>>..>>>>>. # Beer
    <<<<<<<<.
    >>.>>>>>>>>. # On
    >>>.
    <<<<<<<<.>.<<<. # The
    <<<.
    >>>>>>>>>>>.>.<<<<<.. # Wall
    >>>>>>>>.    # Stop
    >..   # Newline x2
    <<<<<<<<<<<<<<<<<<<     # Reset loop
]
# Last but 1 exception
>>. # Counter
>.
>.>.>>>..>>.<<<<.>>>>>>. # Bottles
<<<<<<<<<.
>>.>>.       # Of
<<<<.
>.>>..>>>>>. # Beer
<<<<<<<<.
>>.>>>>>>>>. # On
>>>.
<<<<<<<<.>.<<<. # The
<<<.
>>>>>>>>>>>.>.<<<<<.. # Wall
>>>>>>>.     # Comma
<.
<<<<<<<<<<<<<<.- # x with decrement
>.
>.>.>>>..>>.<<<<.>>>>>>. # Bottles
<<<<<<<<<.
>>.>>.       # Of
<<<<.
>.>>..>>>>>. # Beer
>>>>>>>.     # Stop
>.           # Newline
<<<<<<<<<<<.>>>>>>>.>>>>>.<<<<<<<<<<<<<<. # Take
<<<.
>>.>>>>>>>>.<<<<<<<. # One
<<<.
>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<.>>>>>>>>>.<. # Down
>>>. 
<.<<.>>>>>>>>.  # And
<<<<<.
>>>>>>.<<<<<<<.<<<..    # Pass
>>>>.
>>>>>>>.<<<<<<<<<<<<<<<. # It
>>>>>>>>.
<.<<<<.<<<<<<.>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<.>>>>>>>>. # Around
<<<<. # Comma
<.
<<<<<<<<<<<<<<. # Count
>.
>.>.>>>..>>.<<<<. # Bottle
<<<.
>>.>>.  # Of
<<<<.
>.>>..>>>>>. # Beer
<<<<<<<<.
>>.>>>>>>>>. # On
>>>.
<<<<<<<<.>.<<<. # The
<<<.
>>>>>>>>>>>.>.<<<<<.. # Wall
>>>>>>>>.    # Stop
>..   # Newline x2
# Last 1 exception
<<<<<<<<<<<<<<<<<. # Counter
>.
>.>.>>>..>>.<<<<. # Bottle
<<<.
>>.>>.       # Of
<<<<.
>.>>..>>>>>. # Beer
<<<<<<<<.
>>.>>>>>>>>. # On
>>>.
<<<<<<<<.>.<<<. # The
<<<.
>>>>>>>>>>>.>.<<<<<.. # Wall
>>>>>>>.     # Comma
<.
<<<<<<<<<<<<<<.++++++++ # x with reset to 99
>.
>.>.>>>..>>.<<<<. # Bottle
<<<.
>>.>>.       # Of
<<<<.
>.>>..>>>>>. # Beer
>>>>>>>.     # Stop
>.           # Newline
>----        # Change K to G
>>+++++++++  # Change P to Y
>++++        # Change I to M
<<<.<<<<<<<<<<<<<<<. # Go
<<.
>>>>>.<<<.           # To
<<.
>>>>>.>.<<<.         # The
<<<.
>>>>>>>>>.<<<<.<<<.>>>>>>.<<<<<. # Store
<<<.
>>>>>>>>>>>>.<<.>>>>>>>>.       # And
<<<<<.
<<<<<<<<<<<<.>>>>>>>>>>>>>>>>>>>>.<<. # Buy
<<<<<<.
<<<<.<<<<<<<.>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<<. # Some
>>>>>>>>>>.
>>>>>>>.<<<<<<<<<<<<<<<<<<.>>>>>>.<<<<<. # More
>>>>>>>>>>>.
<.
<<<<<<<<<<<<<<..  # 99
>.
>.>.>>>..>>.<<<<.>>>>>>. # Bottles
<<<<<<<<<.
>>.>>.  # Of
<<<<.
>.>>..>>>>>. # Beer
<<<<<<<<.
>>.>>>>>>>>. # On
>>>.
<<<<<<<<.>.<<<. # The
<<<.
>>>>>>>>>>>.>.<<<<<.. # Wall
>>>>>>>>.    # Stop
>.   # Newline x2

Output:

Try it yourself here!
OK, so it seems the URL is too long to include here, so you will need to copy/paste to try it yourself.

I tested it using this interpreter.

\$\endgroup\$
4
\$\begingroup\$

Julia, 227 215 213 bytes

w=" on the wall"
b=" bottles"
o=" of beer"
k=b*o
for n=99:-1:1
println("$n$k$w, $n$k.
$(n>1?"Take one down and pass it around":"Go to the store and buy some more"), $(n>1?"$(n-1)$(k=b*"\b"^(n<3)*o)":"99$b"o)$w.
")end

This uses string interpolation ("$variable") and ternaries to construct the output and print it to STDOUT.

Saved 14 bytes thanks to Glen O!

\$\endgroup\$
  • \$\begingroup\$ Rather than (n>1?" bottles":" bottle")" of beer", use " bottle""s"^(n>1)*" of beer" - note that the * is necessary after (n<1) because otherwise it tries to apply (n>1)" of beer" as the power. Also, is there any benefit to using while n>0 over for n=99:-1:1 (which allows the condition at the end to be simpler, and avoids the separate need for n=99)? \$\endgroup\$ – Glen O Nov 18 '15 at 18:07
  • \$\begingroup\$ Also use actual newlines in place of \n and switch the middle part to interpolation (rather than ",n>1?...",", use $(n>1?...")) to save a character, and move the , inside the conditional to before the next part, so it only needs to be written once. \$\endgroup\$ – Glen O Nov 18 '15 at 18:21
  • \$\begingroup\$ Actually, strike the suggestion of while over for - I just realised that you'd have to subtract one when doing the last number in each verse, so there's no net benefit. \$\endgroup\$ – Glen O Nov 18 '15 at 18:27
  • \$\begingroup\$ @GlenO Thanks as always for the great suggestions! \$\endgroup\$ – Alex A. Nov 18 '15 at 22:18
  • 1
    \$\begingroup\$ I was hoping to be able to just suggest a change - it's a bit silly that it doesn't permit that option if you've got enough rep to make an edit without the original answerer's acceptance. I do apologise if I did in any way step on toes for doing it. I just moved the evaluation of the "bottle<s> of beer" part to the end, so it only needs to be done once, and initialised it. I also used a backspace instead of a conditional "s" to save a bit. \$\endgroup\$ – Glen O Nov 19 '15 at 6:36
4
\$\begingroup\$

PHP, 251 bytes

This accounts for the plural/singular problem.

<?php for($i=99;$i>0;$i--){$b=" of beer";$s=" bottles$b";$r=" bottle$b";$w=" on the wall";$h=$i-1;echo$h>=1?"$i$s$w, $i$s.\nTake one down and pass it around, $h".($h<2?$r:$s)."$w.\n\n":"$i$r$w, $i$r. \nGo to the store and buy some more, 99$s$w.\n\n";}

Readable:

for ($i=99; $i > 0; $i--) {
  $b = " of beer";
  $s = " bottles$b";
  $r = " bottle$b";
  $w = " on the wall";
  $h = $i - 1;
  echo $h >= 1 ? "$i$s$w, $i$s.\nTake one down and pass it around, $h" . ($h<2 ? $r : $s) . "$w.\n\n" : "$i$r$w, $i$r. \nGo to the store and buy some more, 99$s$w. \n\n";
}
\$\endgroup\$
4
\$\begingroup\$

Beam, 1141 1109 bytes

I still have a lot of room to golf this further with all the empty spaces, but it is getting really hard to follow and breaks quite easily :) It's very similar to the one that I posted for this question, except it goes to the store before the beer reaches 1 and the cells used for the parameters have been shifted. I've also change the layout considerably. I'll try and do an explanation once I try out a couple more layouts.

P'P''''>`++++++)++'''P>`+++++++++++++)'''''''''''P+++++++++++++`P```>`++\ v@@++++++++++L(`<@+p'''''''''PL<
v``P''(++++++`<P'''''''''(++++++++`<L```P'+++++P'+++P'++++++P'++++P''''(/> p++@---@``p@'''''p+++@`> `)''' 'p-@''p\
>''p:'p@'p@'\>n'   >`>`)'''p@''''p@\>n'''p@''''p@-@````p@'''''p@`>`)'''''/v  `P+p``@p'''(`<@-p''''''''P'+up(`<`@@/
^/``@@p'@p''/ >'''\ /-p'@p'@p``@p``/`>-'P''''''''p+@>`)''p`n`L++++++++++@S 'p@````p@````p@'''''p@`p@````p@'''''p@```p++@---@``p@'''''p-@+@`p@+++@``p-@``p@'p-@'''p-@```p++@`p@'p@''''p+@++++@`````p@'''''p-@`p@--@``p-@``p@''''p--@p@+++@``p-@''''p-@>`)'''p@'p+:`p@'p@'''p@'p@@``p@`p-@'''p-@`>`)'''p@''''p@``p@``p@'p@'p-@@'''p--@`>`)'''p@''''p@-@````p@'''''p@`>`)'''''p++@---@``p@'''''p+++@`>`)''''p-@''p@@'''p+@H
^\p@`p-@```p`//'''/ \@@'''p--@`>`)'p/``````@pS@++++++++++L`<vP+p`P-p`P-p`@ p'''(`<@-p''''@--p``@-p`@+p'@p`@--p''''@-p'@p`````@p'''@+++p''@p```\
^             \'p-@/v               \ p-@''p-@`p-@``p@''''p@ -@``p-@``p@'p ++@'''p@'p+++@`p-@````p@'p-@'''p-@```p++@`p@''''p+@```p-@''''p-@@``/
^                   <                                       <             <

Try it in the stack snippet here

\$\endgroup\$
4
\$\begingroup\$

PHP, 250 246 244 233 228 bytes

I believe this is smallest so far. This is based on the 247 shot, with some modifications to further minimise.

Minimised

<?php $b=99;function x($n){return"$n bottle".($n-1?'s':'')." of beer";}$y=" on the wall";while($b){$c=x($b);echo"$c$y, $c.\n",--$b?"Take one down and pass it around":"Go to the store and buy some more",", ".x($b?:99)."$y.\n\n";}

Expanded

<?php

$b=99;
function x($n){return"$n bottle".($n-1?'s':'')." of beer";}
$y=" on the wall";
while(b){
    $c=x($b);
    echo"$c$y, $c.\n",--$b?"Take one down and pass it around":"Go to the store and buy some more",", ".x($b?:99)."$y.\n\n";
}
\$\endgroup\$
  • 1
    \$\begingroup\$ As you can run PHP from command line with php -r which is equivalent of perl -e and similar, is acceptable to omit the opening tag. See the related discussion in Running PHP with -r instead of code tags. \$\endgroup\$ – manatwork Nov 19 '15 at 18:27
  • \$\begingroup\$ Ah, thanks @manatwork, I guess I could then get mine down a bit more. \$\endgroup\$ – Phroggyy Nov 19 '15 at 18:29
  • \$\begingroup\$ while($b) works just as well. \$\endgroup\$ – frnhr Nov 21 '15 at 18:32
  • \$\begingroup\$ There is an extra newline at the end though. \$\endgroup\$ – frnhr Nov 21 '15 at 18:33
  • \$\begingroup\$ Thanks for the whole suggestion! The newline is required though, to have a line in between verses \$\endgroup\$ – Phroggyy Nov 21 '15 at 18:41

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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