| Bytes | Lang | Time | Link |
|---|---|---|---|
| 166 | Regenerate | 210626T213858Z | DLosc |
| nan | Java | 240314T211235Z | Rubinhoo |
| 243 | Tcl | 170212T152808Z | sergiol |
| 250 | AWK | 241118T165628Z | xrs |
| 481 | Python 3 Pydroid 3 app | 241018T224804Z | Junebug |
| 266 | Fortran GFortran cpp | 240618T173847Z | roblogic |
| 272 | ZX81 BASIC | 241018T222410Z | ayreguit |
| 213 | Raku | 151129T213421Z | Brad Gil |
| 289 | Oracle SQL | 210820T144854Z | Del |
| 241 | Bash | 240315T090253Z | Ivan |
| nan | For the fun from https//www.99bottlesofbeer.net/languageperl737.html | 241016T122152Z | Toto |
| 1122 | Template Qdeql | 241011T013153Z | Bbrk24 |
| 144 | Javascript ES6 | 240826T040342Z | Jake |
| 344 | Python 3 | 240823T105808Z | a random |
| 194 | Python 2 | 151119T003848Z | xnor |
| 259 | nroff | 221019T124355Z | 鳴神裁四点一号 |
| 148 | Uiua | 240317T123414Z | noodle p |
| 147 | Pip | 240325T020248Z | DLosc |
| 192 | Uiua | 240314T233757Z | Zylviij |
| 264 | YASEPL | 240226T200641Z | madeforl |
| 278 | TypeScript’s type system | 221226T134436Z | noodle p |
| 237 | Python 3.8 prerelease | 240217T193141Z | Alan Bag |
| 857 | Pyt | 230224T221551Z | Kip the |
| 236 | [Jq 1.5] | 171022T162634Z | jq170727 |
| 200 | Rattle | 210822T033744Z | d01 |
| 215 | Rust | 221204T002038Z | SuperPiz |
| 001 | Seriously | 220201T043526Z | DialFros |
| 167 | Bash | 190805T132121Z | primo |
| 206 | Excel | 210402T122226Z | Axuary |
| 116 | Japt | 210820T111438Z | Shaggy |
| 169 | Knight | 210523T034654Z | EasyasPi |
| 128 | Vyxal Hmj | 210607T195344Z | Aaroneou |
| 145 | Vyxal j | 210607T042248Z | wasif |
| 216 | Pinecone | 210422T163525Z | wasif |
| 279 | Duocentehexaquinquagesimal | 210415T024034Z | Makonede |
| 224 | M4 | 210402T084727Z | user1004 |
| nan | Pxem | 210331T113058Z | user1004 |
| 200 | APL Dyalog Unicode | 201213T131930Z | Kamila S |
| 198 | AWK | 201213T184352Z | cnamejj |
| 237 | Plain TeX | 200605T145259Z | Joe85AC |
| 205 | C# | 200602T125554Z | primo |
| 310 | Python | 200531T142004Z | SZT |
| 231 | Unix TMG | 200202T191155Z | Andriy M |
| 229 | C gcc | 200202T234351Z | S.S. Ann |
| 243 | C# Visual C# Interactive Compiler | 200102T124131Z | Jirka Pi |
| 222 | Keg | 190606T150441Z | user8505 |
| 246 | Wren | 191105T055607Z | user8505 |
| 877 | Whitespace | 191010T113058Z | Dorian |
| 2208 | Hexadecimal Stacking PseudoAssembly Language | 191015T151650Z | Dorian |
| 570 | Assembly MIPS | 190904T034729Z | Andrew B |
| 001 | Actually | 190902T170301Z | Sagittar |
| 237 | Javascript ES6 | 190324T021554Z | Lucas Be |
| 192 | ink | 190324T222259Z | Sara J |
| 295 | Java 295 Bytes | 151118T215724Z | Yassin H |
| 207 | Lua 5.1 | 170805T232826Z | tehtmi |
| 282 | C++ | 190321T210806Z | qookie |
| 275 | ES7 | 190321T192734Z | elipszil |
| 242 | Python 3 | 190228T032953Z | xcrafter |
| 221 | PowerShell | 181024T004210Z | Veskah |
| 207 | Powershell | 181024T141815Z | mazzy |
| 082 | Stax | 181024T000917Z | recursiv |
| 243 | Python 3 | 181023T230919Z | dana |
| 226 | Perl 6 | 181023T204005Z | moonhear |
| 334 | TSQL | 180511T184459Z | BradC |
| 206 | Gema | 180330T143616Z | manatwor |
| 1180 | 17 | 180204T150658Z | Hugh Wil |
| 743 | Brainfuck | 171016T201741Z | primo |
| 223 | Python | 171022T200819Z | EricSher |
| 290 | Funky | 171022T222530Z | ATaco |
| 312 | Prolog SWI | 171022T181711Z | Alexandr |
| 245 | Java 8 | 170817T174704Z | NotBaal |
| 172 | Python | 170810T000350Z | Oliver N |
| 204 | PowerShell | 170809T192047Z | jyao |
| 256 | Julia 0.6.0 | 170809T174255Z | Goysa |
| 272 | Ly | 170806T002119Z | LyricLy |
| 517 | TSQL | 151223T235432Z | Nelson |
| 235 | TLDCode | 170529T123150Z | Justinw |
| nan | Ohm | 170301T202614Z | Business |
| 260 | PHP | 160223T215148Z | ricdesi |
| 279 | Windows Batch | 170313T140708Z | loadingn |
| 389 | CGCC | 170301T221457Z | user6333 |
| 127 | Japt | 151206T035353Z | ETHprodu |
| 123 | SOGL 0.8.2 | 170212T102435Z | dzaima |
| 4028 | Brainfuck | 160829T122515Z | Hywel Re |
| 753 | C Preprocessor | 160901T041308Z | H Walter |
| 241 | F# | 160828T185323Z | asibahi |
| 360 | S.I.L.O.S | 160828T222426Z | betseg |
| 289 | C# | 151118T155153Z | Florian |
| 237 | dc | 160805T200444Z | brhfl |
| 225 | R | 160805T171946Z | user5957 |
| 223 | Haskell | 151118T173741Z | nimi |
| 233 | Maple | 160725T165136Z | DSkoog |
| 431 | Common Lisp Lispworks | 160711T045446Z | sadfaf |
| 227 | Ruby | 160710T063541Z | anna328p |
| 267 | C# | 160707T233812Z | aloisdg |
| 184 | MIT Scratch 2.0 | 160707T173707Z | anna328p |
| 234 | Python 3 | 160707T090306Z | Destruct |
| 159 | Retina | 160701T170923Z | Martin E |
| 845 | XSLT 1.0 no EXSLT | 160701T200557Z | psmay |
| 341 | /// | 160603T125105Z | Leaky Nu |
| 172 | PHP | 160523T065924Z | primo |
| 252 | Scratch | 160520T133753Z | weatherm |
| 210 | Python 3 | 160520T063136Z | Hunter V |
| 323 | TSQL | 160519T210913Z | Matthew |
| 226 | Grond | 160222T230844Z | Bald Ban |
| 221 | PHP | 160224T085705Z | FuzzyTre |
| 139 | Vim | 160222T181725Z | primo |
| 193 | Jolf | 160225T015409Z | Conor O& |
| 267 | R | 160224T083452Z | plannapu |
| 269 | R | 151203T191826Z | durum |
| 181 | PARI/GP | 151127T112350Z | primo |
| 335 | C++ | 151118T182010Z | Michelfr |
| 167 | 05AB1E | 160213T194924Z | Adnan |
| 213 | Groovy | 151121T184233Z | J Atkin |
| nan | SELECT. | 160213T084310Z | quintopi |
| 256 | C | 160213T175315Z | takra |
| 298 | JavaScript ES6 | 160101T144402Z | Benjamin |
| 176 | x86 MSDOS .COM file | 151223T053813Z | krubo |
| nan | Motorola MC14500B Machine Code | 151118T230128Z | Zach Gat |
| 313 | Microsoft Small Basic | 151229T121140Z | Marsan |
| 263 | Lua | 151223T152005Z | CHlM3RA |
| 515 | Loader | 151224T160620Z | SuperJed |
| 290 | Emacs Lisp | 151123T114532Z | Lord Yuu |
| 290 | Java | 151224T151550Z | Minimal |
| 359 | Ceylon 1.2 | 151122T231242Z | Paŭlo Eb |
| 255 | Milky Way 1.0.2 | 151202T213615Z | Zach Gat |
| 222 | Perl 5 | 151213T112421Z | Codefun6 |
| 229 | CJam | 151213T103811Z | username |
| 275 | Mouse2002 | 151210T002338Z | cat |
| 224 | Mathematica | 151118T162921Z | alephalp |
| 324 | Oracle SQL | 151119T155937Z | Michael |
| nan | 151118T204140Z | Adam Dal | |
| 186 | JavaScript ES6 | 151118T192452Z | Stefnotc |
| 143 | GolfScript | 151119T131241Z | primo |
| 196 | JavaScript ES6 | 151119T154532Z | xsot |
| 233 | JavaScript ES5 | 151119T030809Z | Oliver |
| 297 | C | 151118T164410Z | firefror |
| 000 | Vitsy | 151118T181423Z | Addison |
| 134 | CJam | 151122T162306Z | Dennis |
| 228 | PHP | 151119T180150Z | Phroggyy |
| 220 | CJam | 151121T233419Z | GamrCorp |
| 474 | Bubblegum | 151122T144331Z | Dennis |
| 305 | JavaScript ES6 | 151118T154207Z | Conor O& |
| nan | Scala | 151122T054629Z | Ruslan |
| 232 | Python3 | 151121T164535Z | frnhr |
| 169 | O 1.2 | 151121T181640Z | manatwor |
| 206 | golflua | 151121T172628Z | manatwor |
| 218 | Dart | 151121T165902Z | Nick |
| 1109 | Beam | 151120T014524Z | MickyT |
| 159 | Perl 5 | 151119T111652Z | LukStorm |
| 233 | R | 151120T173949Z | David |
| 256 | PHP | 151120T220755Z | MonkeyZe |
| 251 | PHP | 151119T125720Z | Sven |
| nan | BitShift | 151120T102916Z | Bassdrop |
| 214 | JavaScript ES6 | 151118T184737Z | ŽaMan |
| 274 | C# | 151120T010658Z | Igby Lar |
| 196 | C | 151119T020740Z | xsot |
| 376 | Windows Batch | 151118T191420Z | Adnan |
| 235 | Bash | 151119T132849Z | Markus D |
| 287 | Go | 151119T151142Z | Kristoff |
| 297 | R | 151119T113405Z | Tensibai |
| 248 | PHP | 151119T115145Z | Martin O |
| 267 | PHP | 151119T124735Z | Doug McL |
| 243 | Perl 5 | 151118T212914Z | LukStorm |
| 230 | C | 151118T194456Z | Arnaud |
| 213 | Julia | 151118T175415Z | Alex A. |
| 265 | DStack | 151119T043719Z | DarkPhan |
| 239 | Swift 2.0 | 151119T030339Z | esthepik |
| 249 | C | 151119T015318Z | Ray |
| 240 | C | 151118T222016Z | Runium |
| 001 | Seriously | 151118T163321Z | lirtosia |
| 244 | Mouse | 151118T224122Z | Alex A. |
| 932 | Labyrinth | 151118T213533Z | Martin E |
| 281 | Groovy | 151118T215245Z | a spaghe |
| 289 | C++ | 151118T203820Z | ssell |
| 145 | Pyth | 151118T184943Z | PurkkaKo |
| 204 | Python 2 | 151118T185938Z | Sp3000 |
| 667 | Templates Considered Harmful | 151118T184932Z | feersum |
| 254 | Python | 151118T155543Z | xenia |
| 254 | Matlab | 151118T173034Z | flawr |
| 269 | PHP | 151118T160655Z | undefine |
Regenerate, 170 166 bytes
((99( bottle)s( of beer))( on the wall)), $2.
(Take one down and pass it around, (((${$9-1}|98)$3s{1-1/$9}$4)$5).
$7, $8.
){98}Go to the store and buy some more, $1.
This is basically just a bunch of capturing groups and backreferences repeated 98 times, with two interesting parts:
- Group 9, which holds the number at each iteration, is
(${$9-1}|98). The first time through, since group 9 hasn't been matched yet, the$9backreference fails and we use the other option,98. Afterwards,$9contains the previous number, so we use that value minus 1:${$9-1}. - In order not to pluralize
bottlewhen the number hits 1, we uses{1-1/$9}. Since/is integer division,1/$9will be 0 if group 9 is greater than 1 and 1 if group 9 equals 1. Then{1-1/$9}repeats thes1 time if the number is over 1 and 0 times if the number equals 1.
Java, 274 bytes. Java 21+: 245 bytes. Java 24: 234 bytes
Java v24+:
void main(){String a=" bottle",b=" of beer",s=a+'s'+b,x=s,c=" on the wall",n=".\n";for(int i=99;i>0;)println(i+x+c+", "+i+x+n+(--i>0?"Take one down and pass it around, "+i:"Go to the store and buy some more, 99")+(x=i==1?a+b:s)+c+n);}
Ungolfed:
void main(){
String a=" bottle",b=" of beer",s=a+'s'+b,x=s,c=" on the wall",n=".\n";
for(int i=99;i>0;)
println(
i+x+c+", "+i+x+n
+(--i>0?"Take one down and pass it around, "+i:"Go to the store and buy some more, 99")
+(x=i==1?a+b:s)+c+n
);
}
Built on the previous record, shortened by 6 14 16 19 25 27 38 characters.
Curious to see how much lower we can still go.
Edit3: Added Java 24 version (just released) which auto-imports and thus lets us remove "System.out." from the program. Run the source directly with "java --source 24 --enable-preview B.java".
Removed the previous versions to limit the length of this entry. For Java 21-23, replace "println" with "System.out.println". In addition, for Java <21, use this header: "interface B{static void main(String[]p){", and match the parentheses.
Edit2: Added Java 21-23 version which allows further reductions through the implicit class & instance main method features. Run the source directly with "java --source 21 --enable-preview B.java". (Match the version number to your Java.) "--enable-preview" won't be needed once the feature graduates from preview.
Edit1: Previous version with length of 268 chars matched the output in the highest-voted java entry at the time (~290 chars), but it didn't fully match the punctuation in the challenge text. I updated it to match the challenge which required +6 bytes. Credit to @DLosc and @moderators .
Tcl, 243 bytes
proc B {} {set x " bottle[expr $::i>1?{s}:{}] of beer"}
set i 99
time {puts "$i[B][set w " on the wall"], $i[B].
Take one down and pass it around, [incr i -1][B]$w."} 98
puts "1[B]$w, 1[B].
Go to the store and buy some more, [incr i 98][B]$w."
proc B i {set x " bottle[expr $i>1?{s}:{}] of beer"}
set w " on the wall"
set i 99
while \$i>1 {puts "$i[B $i]$w, $i[B $i].\nTake one down and pass it around, [incr i -1][B $i]$w."}
puts "1[B $i]$w, 1[B $i].\nGo to the store and buy some more, 99[B 9]$w."
AWK, 250 bytes
func b(x){return x" bottle"(1~x?"":"s")" of beer"}func p(y,z){print y w", "y"."t z w".\n"}END{w=" on the wall";t="\nTake one down and pass it around, "
for(i=99;i>1;)p(b(i),b(--i));print b(i)w", "b(i)".\nGo to the store and buy some more, "b(99)w"."}
func b(x){return x" bottle"(1~x?"":"s")" of beer"}
func p(y,z){print y w", "y"."t z w".\n"}
END{
w=" on the wall";
t="\nTake one down and pass it around, "
for(i=99;i>1;)p(b(i),b(--i));
print b(i)w", "b(i)".\nGo to the store and buy some more, "b(99)w"."}
Python 3 (Pydroid 3 app), 481 bytes
for i in range(99,0,-1):
if i == 1:
print(f"{i} bottle of beer on the wall, {i} bottle of beer")
print("Go to the store, Buy some more, 99 bottles of beer on the wall")
elif i == 2:
print(f"{i} bottles of beer on the wall, {i} bottles of beer")
print("Take one down, pass it around, 1 bottle of beer on the wall")
else:
print(f"{i} bottles of beer on the wall, {i} bottles of beer")
print(f"Take one down, pass it around, {i-1} bottles of beer on the wall")
print()
Fortran (GFortran) -cpp, 409.. 266 bytes
#define w' on the wall'
#define p i,' bottle',char(n),' of beer'
#define q print"(*(g0))"
n=115;do5 i=99,1,-1;if(i<2)n=0
if(i<99)q,'Take one down, pass it around, ',p,w,'.',new_line(w)
5 q,p,w,', ',p,'.'
n=115;i=99;q,'Go to the store and buy some more, ',p,w,'.';end
-cppallows me to#definemacros- macro
puses ASCII conversion, so acharactervariable's'isn't needed - macro
qformats integers nicely, so a conversion ofito string isn't needed - loop
do5(ungolfeddo 5) loops around to label5two lines below
ZX81 BASIC, 272 bytes
10 FOR N=CODE "#63" TO SGN PI STEP COS PI
20 PRINT AT NOT PI, NOT PI;N;" BOTTLE";"S" AND N<>SGN PI;" OF BEER ON THE WALL, ";N;" BOTTLE";"S" AND N<>SGN PI;" OF BEER. ","TAKE ONE DOWN AND PASS IT AROUND, " AND N<>SGN PI;"GO TO THE STORE AND BUY SOME MORE, " AND N=SGN PI;(N-SGN PI AND N<>SGN PI)+(CODE "#63" AND N=SGN PI);" BOTTLE";"S" AND N<>VAL "2";" OF BEER ON THE WALL. "
30 NEXT N
Best I can do is all caps with 32 columns. Copy/paste to try it here.
Raku, 213 bytes
my$b=' bottle';my$e=' of beer';my$o=" on the wall";for 99…1 {my$c=$_~$b~'s'x?($_-1)~$e;say "Take one down and pass it around, $c$o.\n"if $++;say "$c$o, $c."};say "Go to the store and buy some more, 99{$b}s$e$o."
my$b=' bottle';
my$e=' of beer';
my$o=" on the wall";
for 99…1 {
my$c=$_~$b~'s'x?($_-1)~$e;
say "Take one down and pass it around, $c$o.\n"if $++;
say "$c$o, $c."
};
say "Go to the store and buy some more, 99{$b}s$e$o."
Oracle SQL, 254 247 285 289 Bytes
Golfed:
SELECT REGEXP_REPLACE(n||b||w||', '||n||b||'.'||CHR(10)||DECODE(n,1,'Go to the store and buy some more,99',t||(n-1))||b||w||'.','(^1 | 1 )bottles','1 bottle')FROM(SELECT 100-LEVEL n,' bottles of beer'b,' on the wall'w,'Take one down and pass it around, 't FROM DUAL CONNECT BY LEVEL<=99);
Ungolfed:
SELECT
REGEXP_REPLACE(
n||b||w||', '||n||b||'.'||CHR(10)||
DECODE(n, 1, 'Go to the store and buy some more, 99',t||(n-1))||b||w||'.'
, '(^1 | 1 )bottles','1 bottle'
)
FROM(
SELECT
100-LEVEL n
,' bottles of beer'b
,' on the wall'w
,'Take one down and pass it around, 't
FROM DUAL
CONNECT BY LEVEL<=99
);
Basically, I get the row number via the hierarchical query and build a small library in the inner query. Then I put it all together in the outer query.
Edit 1:
-7 Bytes: Used the "distributive" property on common string within the DECODE function.
Edit 2: +38 bytes: Oops, missed the s on 1 bottle. Fixed with regular expression string replacement.
Try it out at DBFiddle: Golfed -- Readable
285b-bugged
Bash, 268, 261, 247, 244, 241 bytes
f(){
(($1>1))&&s=s
[ $2 ]||a=" on the wall"
echo "$1 bottle$s of beer$a"
}
for((n=$1;n;n--));{
b="Take one down and pass it around,"
j=$[n-1]
((j<1))&&b="Go to the store and buy some more," j=$1
echo -e "$(f $n), $(f $n 1).\n$b $(f $j).\n"
}
For the fun from (https://www.99-bottles-of-beer.net/language-perl-737.html), just run it, it works !
Perl, 1694 bytes
''=~( '(?{' .('`' |'%') .('[' ^'-')
.('`' |'!') .('`' |',') .'"'. '\\$'
.'==' .('[' ^'+') .('`' |'/') .('['
^'+') .'||' .(';' &'=') .(';' &'=')
.';-' .'-'. '\\$' .'=;' .('[' ^'(')
.('[' ^'.') .('`' |'"') .('!' ^'+')
.'_\\{' .'(\\$' .';=('. '\\$=|' ."\|".( '`'^'.'
).(('`')| '/').').' .'\\"'.+( '{'^'['). ('`'|'"') .('`'|'/'
).('['^'/') .('['^'/'). ('`'|',').( '`'|('%')). '\\".\\"'.( '['^('(')).
'\\"'.('['^ '#').'!!--' .'\\$=.\\"' .('{'^'['). ('`'|'/').( '`'|"\&").(
'{'^"\[").( '`'|"\"").( '`'|"\%").( '`'|"\%").( '['^(')')). '\\").\\"'.
('{'^'[').( '`'|"\/").( '`'|"\.").( '{'^"\[").( '['^"\/").( '`'|"\(").(
'`'|"\%").( '{'^"\[").( '['^"\,").( '`'|"\!").( '`'|"\,").( '`'|(',')).
'\\"\\}'.+( '['^"\+").( '['^"\)").( '`'|"\)").( '`'|"\.").( '['^('/')).
'+_,\\",'.( '{'^('[')). ('\\$;!').( '!'^"\+").( '{'^"\/").( '`'|"\!").(
'`'|"\+").( '`'|"\%").( '{'^"\[").( '`'|"\/").( '`'|"\.").( '`'|"\%").(
'{'^"\[").( '`'|"\$").( '`'|"\/").( '['^"\,").( '`'|('.')). ','.(('{')^
'[').("\["^ '+').("\`"| '!').("\["^ '(').("\["^ '(').("\{"^ '[').("\`"|
')').("\["^ '/').("\{"^ '[').("\`"| '!').("\["^ ')').("\`"| '/').("\["^
'.').("\`"| '.').("\`"| '$')."\,".( '!'^('+')). '\\",_,\\"' .'!'.("\!"^
'+').("\!"^ '+').'\\"'. ('['^',').( '`'|"\(").( '`'|"\)").( '`'|"\,").(
'`'|('%')). '++\\$="})' );$:=('.')^ '~';$~='@'| '(';$^=')'^ '[';$/='`';
Template Qdeql, 1132 1124 1122 bytes
o:2-O:9\D{o::= -=}I:119=t{a:256_e\a::D o::=a:o_1*/a::=}x:98-s{e:10
t }O::==-n{e:111 t }/i{e:32 t }c{e:116 t }q{a:e+1 a::=z:o_e_2\z::=
\e::=a:o+1\--a::=a:o+3-\/\/a::=a:o_e+1/a::= //o::=o:o+1}e:0 q
N:108=E{a:e+1 a::=a:o_1\a::= \-o::=a:o+1-\/\/a::=z:o_e_2/=/z::=}h{e:101
t }-L{a:o_1 a::= -}S:104=H{f:e+1 f::= -f:207 f::L f:o_e_2 f::=}y{E
q H a:e+1 a::=o:o_1*a:o_a a::=}g{e:0 y e:1 E q H a:o_1==-a::=a:o_3*o:o_1
a::=}g p:114 b{i e:x t n c t e:N t h }v:115 k{i n e:102 t i e:x
t h t e:p t }u{e:97 t }r{b e:v t k }r d{e:46 t }m{e:110 t }l{i
n m i c e:S t h i e:I t u e:N t t }l w{e:44 t }w i g r d s j:100
R:117 T{e:84 t u e:107 t h i n m h i e:j t n e:I t m i u m e:j
t i e:112 t u e:v t t i e:105 t c i u e:p t n e:R t m e:j t w
i }T A:49==-=\===\/\/\===\/\/g r l d s s g r l w i g r d s T
==-==/a:O+1=o:4\a::==-=e:1 E ===/=-==/-o:2=-=\==\/\/a:3\a::=
-a::= \-o::= -\/\/a::= /o::=a:1/a::=e:0 y r l d s s e:0 y r l
w i e:0 y r d s T =-o:1=-e:A=/t b k l d s s e:A t b k l w i e:A
t b k d s e:71 t n i c n i c e:S t h i e:v t c n e:p t h i u
m e:j t i e:x t e:R t e:121 t i e:v t n e:109 t h i e:109 t n
e:p t h w i e:57 t t r l d
Template Qdeql is a programming language that compiles to Qdeql. All function calls are resolved at compile time. Thus, while the source code is quite short, the compiled output isn't -- the resulting Qdeql is nearly half a megabyte!
This is particularly special to me because, to my knowledge, nobody has written a Qdeql program for 99 Bottles of Beer before today!
This is the same general approach as this example, with a few changes:
- Punctuation changes, such as comma placement, to match the spec for this challenge
- Declarations were reordered to minimize the amount of whitespace required
- I entirely removed some functions like
assertNEquals, and inlined functions that were only called once - The end was rewritten to have the "Go to the store and buy some more" line
- A lot more specialized putchar functions than just
newline
Identifiers were abbreviated automatically using this script, but whitespace was manually contracted.
Edits:
- -8 for replacing some computations with direct assignment when the result is a known one-digit number
- -2 in whitespace reduction by moving a couple variable assignments
Javascript (ES6), 144 Bytes
for(i=99;i;)alert(`${i} bottles of beer on the wall, ${i--} bottles of beer.
Take one down, pass it around, ${i} bottles of beer on the wall.`);
Sadly, tio.run doesn't support alert, so here's a console.log version (155 bytes):
Link
Explanation:
for(
i=99; // This is the increment
i; // This becomes false when i==0
// There is no increment; The increment is in the string.
) // No need for brackets, since this is a single command
alert(`${i} bottles of beer on the wall, ${i--} bottles of beer. // I use ${i--} to still keep the i variable while decreasing it to replace the for increment.
Take one down, pass it around, ${i} bottles of beer on the wall.`);
Python 3, 350 344 bytes
first golf Saved 6 bytes thanks to @emanresuA (i just learnt how to use f-strings)
print("\n".join([f"""{i if i!=0 else"No more"} bottle{(i!=1)*"s"} of beer on the wall, {i if i!=0 else"no more"} bottle{(i!=1)*"s"} of beer.
{"Take one down and pass it around"if i!=0else"Go to the store and buy some more"}, {"no more" if i-1==0else"99"if i==0else i-1} bottle{((i-1)!=1)*"s"} of beer on the wall.
"""for i in range(99,-1,-1)]))
Explanation
It creates a list, [f"""{i if i!=0 else"No more"} bottle{(i!=1)*"s"} of beer on the wall, {i if i!=0 else"no more"} bottle{(i!=1)*"s"} of beer. {"Take one down and pass it around"if i!=0else"Go to the store and buy some more"}, {"no more" if i-1==0else"99"if i==0else i-1} bottle{((i-1)!=1)*"s"} of beer on the wall. """for i in range(99,-1,-1)], which works because it loops from 99 down to 0, and then it puts the index in it, unless it's 0, in which case it replaces it with "no more" and "go to the store and buy some more", and unless it's 1, in which case it just adds or deletes an "s" at the end. Then it just converts that into a string (seperated with \n)
Python 2, 194 bytes
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.
nroff, 259 bytes
.de B
\\$1
bottle
.if \\$1>1 \h'-1's
of beer
..
.de F
.B \\nX
on the wall,
.B \\nX
\h'-1'.
.sp 0
.nr X \\nX-1
.ie \\nX \\{Take one down and pass it around,
.B \\nX
\\}
.el \\{Go to the store and buy some more,
.B 99
\\}
on the wall.
..
.nr X 99
.while \nX .F
How it works
.de B \" macro to output N bottle(s) of beer
\\$1 \" argument
bottle \" This string is rendered as is, with automatically a space
.if \\$1>1 \h'-1's \" Output s without leading space if argument is >1
of beer \" This string is renderd as is, with automatically a space
.. \" end of macro
.de F \" main macro to print two lines and a blank line
.B \\nX \" Call macro B with value of numeric register X
on the wall, \" rendered as is with automatically a space
.B \\nX
\h'-1'. \" Append a full stop without leading space.
.sp 0 \" Next line.
.nr X \\nX-1. \" Decrement register X
.ie \\nX \\{Take one down and pass it around,
.B \\nX
\\} \" Show this if X is not zero
.el \\{Go to the store and buy some more,
.B 99
\\} \" Show this otherwise
on the wall. \" This string is rendered with leading space
\" Explicitly append a blank line
.. \" End of macro definition
.nr X 99 \" Initialize a numeric register X
.while \nX .F. \" Macro F is done repeatedly until X is zero
Uiua, 157 156 148 bytes
&p↘2↻33↘32∧($"Take one down and pass it around, _.\n\n_, _.\n_".⊂," on the wall"$"_ bottle_ of beer":↯≠1,@s)+1⇡99"Go to the store and buy some more"
Explanation:
∧( ... )+1⇡99"Go to the store and buy some more, "
Fold the inclusive range 1 to 99, with an initial value of the end of the text, by the following function:
-
$"_ bottle_ of beer":↯≠1,@sRepeat
sby whether the number is 1 or not, then put that in a format string with the number to get the "[N] bottle[s] of beer" part. -
.⊂," on the wall"Append " on the wall" to a copy, and copy the new string as well.
-
$"Take one down and pass it around, _.\n\n_, _.\n_"Fill these into the format string. Every
_is where a stack item goes, starting from the left. Note that this starts with the "Take one down and pass it around" bit, so we'll have to remove that from the first line later. The final_at the end of the string becomes the fold value.
↘32
Drop 32 characters from the start of the string, removing the starting "Take one down and pass it around".
↻33
Rotate the string 33 characters to the left. This moves ", 99 bottles of beer on the wall." to the end, leaving two leading newlines.
&p↘2
Remove the aforementioned trailing newlines and print to STDOUT.
Pip, 147 bytes
L DhP[V Y{[h|99" bottle"h=1?x's" of beer"]}w:" on the wall"k;Vy'.nDh?"Take one down and pass it around""Go to the store and buy some more"k;Vyw'.n]
Explanation
We use h as the loop counter. It is a variable predefined to 100, so the first thing we do is Decrement it to 99 and then Loop that many times.
Each time through the loop, we Print the contents of a big list (automatically concatenated together, with a trailing newline):
V Y{[h|99" bottle"h=1?x's" of beer"]}: the appropriate variation on "N bottle(s) of beer" based on the current value ofh(see below)w: " on the wall"k: ", " (a predefined variable)Vy: evaluate the "N bottle(s) of beer" code again'.: "."n: newline (a predefined variable)Dh?"Take one down and pass it around""Go to the store and buy some more": decrementh; "Take one down and pass it around" if it's still truthy (nonzero), otherwise "Go to the store and buy some more"k,Vy,w,'.,n: as above
{[h|99" bottle"h=1?x's" of beer"]}
[ ] ; Return this list (which gets concatenated when output):
h|99 ; h, or else 99 if h is 0
" bottle" ; That string
h=1?x's ; If h is 1, empty string; otherwise, "s"
" of beer" ; That string
Uiua, 192 bytes
o←:" of beer on the wall"
a←⊂:⊂" bottle"⟨""|@s⟩⊃(>1|°⋕)
b←⊂⟨"Take one down and pass it around, "a-1|"Go to the store and buy some more, "a99⟩=1.
l←&p$"__, _ of beer.\n__.\n"o⊃(.a|b)o
⍚l⇌+1⇡99
YASEPL, 264 bytes
=n$100=p)"s"=q)p=w=o)" bottle"=d)comma`1!-[4!p)""`4!w$n-[5!q)""`5#n#o#p#" of beer on the wall"#d#space#n#o#p>" of beer."!@2#"Take one down and pass it around"#d|3`2#"Go to the store and buy some more"#d!q)"s"!w$99`3#space#w#" bottle"#q>" of beer on the wall.">""![
TypeScript’s type system, 278 bytes
This was the first golf I ever submitted using TS types! It's been over a year since I made my original 591 byte solution, and I'm glad to say I have gotten way better at TS types golf. Revisiting the 99 bottles of beer problem, I came up with the following solution, which is 60 bytes shorter than the solution ASCII-only wrote based on mine, and over half the size of the original solution I had when I first approached the problem.
//@ts-nocheck
type F<N=[1],S="Go to the store and buy some more, 99 bottles of beer on the wall.",L=N["length"],X=`${L} bottle${L extends 1?"":"s"} of beer`,Z=" on the wall",V=`${X}${Z}, ${X}.
${S}`>=L extends 99?V:F<[...N,1],`Take one down and pass it around, ${X}${Z}.
${V}`>
Try it at the TypeScript playground!
This is a type F which is generic, but all the generic type parameters have defaults so no input types are needed.
Explanation: Start with the last line of the text, and N = 1:
Go to the store and buy some more, 99 bottles of beer on the wall.
Until N = 99, increment N and prepend:
Take one down and pass it around, {N} bottles of beer on the wall.
{N} bottles of beer on the wall, {N} bottles of beer.
When N = 99, prepend:
99 bottles of beer on the wall, 99 bottles of beer.
and return the final string.
In the actual program, repeated parts of the text are extracted into types that are then embedded into the string type.
For posterity's sake, here's my old solution, although I'm a bit embarassed about how bad I used to be :)
TypeScript Type System, 591 344 bytes
344 bytes thanks to @ASCII-only
type m<P=-1,A=[]>=A['length']extends 100?A:m<A['length'],[...A,P]>
type n=m
type d<N>=n[N]
type a<N>=`${N} bottle${N extends 1?"":"s"} of beer`
type _<N extends 0=99>=`${a<N>} on the wall, ${a<N>}.
${N extends 1?`Go to the store and buy some more, ${a<99>} on the wall.`:`Take one down and pass it around, ${a<d<N>>} on the wall.
${_<d<N>>}`}`
Also I'm not sure this is valid, since it doesn't output the type to STDOUT, since that's not a thing with TS types.
Python 3.8 (pre-release), 237 bytes
for i in range(99,0,-1):print(f"{i}"+(x:=f" bottle{'s'*(i>1)} of beer on the wall")+", "+f"{i}"+x[:16-(i<2)]+".\n",f"Take one down and pass it around, {i-1-(i<3)}{x}.\n"if i>1else f"Go to the store and buy some more, 99 bottles{x[7:]}.")
Pyt, 855 857 bytes
2ᴇ⁻⁻`⁺ĐĐ₀7²⁻+⇹1ᴇ%7²⁻+5²Đ2⁵2ᴇ⁻⁻3⑴ǰƖ5!4-ĐĐ8-2ᴇ⁺Đ77++2⁵3⑴ǰƖ2ᴇ⁺⁺2⁵7²2*2ᴇ⁺ĐĐ67++2⁵3⑴ǰƖĐ⁻2⁵5!4-2ᴇ4+Đ3-2⁵5!⁻2ᴇ3-5!4!₂-Đ9△⁻2⁵áĐ0⦋áƑÁĐ₀7²⁻+⇹1ᴇ%7²⁻+2⁵2ᴇ⁻⁻3⑴ǰƖ5!4-ĐĐ8-2ᴇ⁺Đ77++2⁵3⑴ǰƖ2ᴇ⁺⁺2⁵7²2*2ᴇ⁺ĐĐ67++9△⁺1ᴇ9²3+2ᴇ3-2ᴇ7+2ᴇ⁺2⁵3⑴ǰƖĐ⁻2ᴇ⁺2⁵2ᴇ3⑴ǰƖ5!⁻Đ9-9△⁻2⁵3⑴ǰƖ⁺2ᴇ3-5!5-Đ2⁵2ᴇ5+5!4-2⁵2ᴇ3-5!6-Đ3-Đ6+Đ7-2ᴇ9△⁻2⁵áĐ0⦋⁻áƑÁĐ₀7²⁻+⇹1ᴇ%7²⁻+2⁵2ᴇ⁻⁻3⑴ǰƖ5!4-ĐĐ8-2ᴇ⁺Đ77++2⁵3⑴ǰƖ2ᴇ⁺⁺2⁵7²2*2ᴇ⁺ĐĐ67++2⁵3⑴ǰƖĐ⁻2⁵5!4-2ᴇ4+Đ3-2⁵5!⁻2ᴇ3-5!4!₂-Đ9△⁺1ᴇáĐĐŁř2≥*Đ1⦋68*≠?ŕ:ŕĐŁř2≠*Đ6²⁻⦋68*≠?ŕ:ŕĐŁř6²≠*Đ9²5+⦋68*≠?ŕ:ŕĐŁř9²6+≠*;Đ9²5+⦋68*=?ŕĐŁř9²6+≠*:ŕ;žƇǰƥ0⦋⁻⁻łŕ7²2⁵2ᴇ⁻⁻3⑴ǰƖ5!4-ĐĐ8-2ᴇ⁺2⁵3⑴ǰƖ2ᴇ⁺⁺2⁵7²2*2ᴇ⁺ĐĐ67++2⁵3⑴ǰƖĐ⁻2⁵5!4-2ᴇ4+Đ3-2⁵5!⁻2ᴇ3-5!4!₂-Đ9△⁻2⁵7²2⁵2ᴇ⁻⁻3⑴ǰƖ5!4-ĐĐ8-2ᴇ⁺2⁵3⑴ǰƖ2ᴇ⁺⁺2⁵7²2*2ᴇ⁺ĐĐ67++9△⁺1ᴇ7⬠⁺3⑴ǰƖ2⁵5!4-Đ5-2⁵5!4-2ᴇ4+Đ3-2⁵5!5-Đ⁺Đ5-Đ3+2ᴇ⁺2⁵2ᴇ3-2ᴇ1ᴇ+2ᴇ2⁵7²2*5!3-Đ4+2⁵5!5-Đ4-Đ2-Đ8-2⁵2ᴇ9+3⑴ǰƖĐ3+2ᴇ⁺9△⁻2⁵6⬠6+Đ2⁵2ᴇ⁻⁻3⑴ǰƖ5!4-ĐĐ8-2ᴇ⁺5!5-2⁵3⑴ǰƖ2ᴇ⁺⁺2⁵7²2*2ᴇ⁺ĐĐ67++2⁵3⑴ǰƖĐ⁻2⁵5!4-2ᴇ4+Đ3-2⁵5!⁻2ᴇ3-5!4!₂-Đ9△⁺áƇǰ;
As Pyt code does not include strings, the entire song has to be built letter by letter. The first half or so of the code (from the beginning until the ł) prints all but the last verse. The rest of the code prints the last verse.
I'm sure this can be golfed; I'm really just too lazy (plus I've already spent like 3 hours on it and I need a break).
[Jq 1.5], 236 232 bytes
def B:" bottle\(if.>1 then"s"else""end) of beer";def W:" on the wall";def T:"Take one down and pass it around";99-range(99)|"\(.)\(B+W), \(.)\(B).
\(T), \(.-1)\(.-1|B+W).
"|gsub(0|T+", 0"+B+W;"Go to the store and buy some more, 99"+B+W)
Expanded
def B:" bottle\(if.>1 then"s"else""end) of beer";
def W:" on the wall";
def T:"Take one down and pass it around";
99-range(99)
| "\(.)\(B+W), \(.)\(B).
\(T), \(.-1)\(.-1|B+W).
"
|gsub(0|T+", 0"+B+W;"Go to the store and buy some more, 99"+B+W)
Ty GammaFunction for catching a mistake.
Rattle, 201 200 bytes
99& bottles of beer& on the wall&Take one down and pass it around, &, &.&1 bottle of beer&Go to the store and buy some more, 99|IPg[bb1b2b4bb1b5B-sb3[1f0]bb1b2b5Bbb^B]0;b6b2b5Bbb^Bb6b2b4b6b5Bb7b1b2b5q
This basically takes the lyrics chopped up then pieces them together. It's likely that this can be shortened a bit
Rust, 215 bytes
fn main(){for a in!297..{print!("{} bottle{}{}",99-a%!1%2383/3,&"s of beer on the wall"[a%!1/!4..87>>a%3&29],[", ",".
Take one down and pass it around, ",".
",".
Go to the store and buy some more, "][a%(6-3%!a)])}}
This is the smallest I could get with Rust... As for the standard version, it's 259 bytes (No solution, just proof). Both versions error with addition overflow... There's quite a bit of messy logic to filter the integer mess, still being smaller than a 0-300 loop.
It seems pretty competitive, even beating a Javascript answer?
Bash, 167 bytes
Saved 2 bytes due to Sisyphus.
eval a={1..99}'" bottle$s of beer"
b="$a on the wall";f=$b,\ $a.$o;o="
Take one down and pass it around, $b.
$f";s=s';echo "$f
Go to the store and buy some more, $b."
Excel, 198 209 206 bytes
+9 bytes for correcting 1 bottle error
-3 bytes for tweaks
=LET(q,99-ROW(1:99),b,q+1&" bottle"&REPT("s",q>0)&" of beer",w,b&" on the wall",w&", "&b&".
"&IF(q,"Take one down and pass it around, "&INDEX(w,100-q),"Go to the store and buy some more. "&INDEX(w,1))&".
")
This version shows 3 lines per cell. Would be slightly longer to put it all in one cell and wouldn't be completely readable on screen.
Original
=LET(q,100-ROW(1:98),b," bottles of beer",w,b&" on the wall",CONCAT(q&w&", "&q&b&".
Take one down and pass it around, "&(q-1)&w&".
")&"1"&b&", 1"&b&".
Go to the store and buy some more, 99"&w &".")
Japt, 116 bytes
Needs more golfing or, perhaps, a completely different approach. Borrows a couple of tricks from ETH' original version.
Includes 2 trailing newlines.
´Lõ Ô˱` Þ¤{´LÎçs} Þ8`".
{=D+` e Ø!`}, {D}.
{LÎg`Go ‘ e ÐJe „d ¿y Ñ Ú
Take e ܵ „d p†s Š ÂИ`·}, "iUìé~H
´Lõ Ô˱`...{´LÎçs}...`"...{=D+`...`}...{D}...{LÎg`...`·}..."iUìé~H
´L :Prefix decrement L (initially 100)
õ :Range [1,L]
Ô :Reverse
Ë :Map each D
± : Append
` : Compressed string
... : " bottle"
{ : Interpolate
´LÎ : Prefix decrement L and get its sign
çs : Repeat "s" that many times
} : End interpolate
... : " of beer"
` : End compressed string
"... : Literal string (the return value)
{ : Interpolate
= : Assign to variable U
D+`...` : D & the compressed string " on the wall"
} : End interpolate
... : Literals
{D} : Interpolate D
... : Literals
{ : Interpolate
LÎg : Get the sign of L and index (0-based) into
`...` : Compressed string "Go to the store and buy some more\nTake one down and pass it around"
· : Split on newlines
} : End interpolate
..." : End of string
iU : Prepend U
à :End map
¬ :Join
é :Rotate right by
~H : The bitwise NOT of 32 (i.e., -33)
Knight, 170 169 bytes
;=r 99WrO++++++""r+C=sB=bS" bottles of beer"7?1r""=e" on the wall"+", "r+bI=r-rT+".
Take one down and pass it around, "r".
Go to the store and buy some more, 99"Cs+e".
"
- 1 byte: inline
CALL
Ungolfed but still barely understandable
# set our counter to 99 (r)
; = counter 99
# We call this inline in the golfed code
# getbottle(s):
# returns pluralized " bottle(s) of beer" depending
# on counter's value, also storing it in beer
; = getbottles BLOCK {
: = beer
: SUBSTITUTE (
: " bottles of beer"
: 7
# when counter == 1, remove the s
: ? 1 counter
# replace with empty string
: ""
: )
: }
# Loop while counter != 0
: WHILE counter {
# basically concatenate everything
# still better than StringBuilder
: OUTPUT
: ++++++
: ""
: counter
: + (CALL getbottles)
: (= wall " on the wall")
: + ", "
: counter
: + beer
: IF (= counter - counter 1) {
: # note: \n doesn't actually work, it is just for clarity
: + ".\nTake one down and pass it around, " counter
: } {
: ".\nGo to the store and buy some more, 99"
: }
: + (CALL getbottles)
: wall
: ".\n"
: }
Vyxal Hmj, 128 bytes
ƛ‛ḋ¶øP«lT…|«"Ṅ£¥:«∧*JEp
'«\,+"Ṅ$"Ṅ‛.
+n‹[`¬Ȧ λḭ ∧ċ λ¬ ∆¶ it ⟑Ṡ`|«¢ṁĖ↲Ǐ¶QṪD£y∩i› kḭS√⁰«¡]‛, ++n‹[n‹|99]‛ḋ¶øP«∪ṠEȧ₆›λ*ĖC9«"Ṅ\.++;Ṙ
I was going to put this in a comment on @Wasif's answer, but the link was too long, so here's my Vyxal answer, with a -17 byte golf.
Vyxal j, 145 bytes
2₁rƛ«ƛ
÷v≬ẏẆ:βĠPd⁰1Ȧ∩_«£¥:½h\r+WḢnð+vJ‛, j\.¶`¬Ȧ λḭ ∧ċ λ¬ ∆¶ it ⟑Ṡ, `n1-ð¥\.Wṅ;Ṙ`1 ḋ¶ `¥⌈ḢṄ+:½h`er. `+"‛, j`Go to λλ ¬↓ λ¬ by λ⋎ λƈ, 99 `¥+\.+"⁋J
Pinecone, 216 bytes
l:" on the wall";k:" bottles of beer";i:99|i>0|i:i-1@(j:(i.String);print:j+k+l+", "+j+k+".";i=1?print:"Go to the store and buy some more, 99"+k+l+"."|print:"Take one down and pass it around, "+((i-1).String)+k+l+".")
Duocentehexaquinquagesimal, 279 bytes
`Y7íY-þÌÅȵ3₃1œ₆"Σè‹×ê8ëbc¾½}tiQιδcâāιΖ´K2X©∍U7ΘËð»¦Õe˜ãΓh=_²₆G܃‚ÄÏ4ÒþO@æc†5ˆ‹₄ý¡)Esƶ’ĆË₁^rgÝyúÃćÆa^}λв?‰ZJ~‡çN©ƶƶнîõgoΈy«N§Lÿ£&Ćƶ¯…sHkHÆ#нåY~gûîf6!0§`zнÕlʒ3ǝú×…ù[9»¦\ÌååÌ}ι|~qsŒnNdΔd’â*›nQáîÃî~j™∍ît‹ó0uº5-˜ÐØîĆe&U!z©ÅñÒ(„†{k4Zéм›}%1₅cʒ€bιG6c‚¤[øÚYR:ñŒäηíMÝVηí\δÇñ5æƶÖ|›5Wì̦z
M4, 224 bytes
define(b,`$1 bottle`'ifelse($1,1,,s) of beer')define(w,`b($1) on the wall')define(f,`w($1), b($1).
ifelse($1,1,`Go to the store and buy some more, w(99).',`Take one down and pass it around, w(decr($1)).
f(decr($1))')')f(99)
If I learn GNU extensions, perhaps I would shorten this code.
Pxem, Filename: 131 bytes + Content: 61 bytes = 192 bytes.
I escaped spaces too (\040).
- Filename (escaped):
c.z.e,.o\040.oq.e.s..o\n.o\001.-.c\001.y.sGo\040to\040the\040store\040and\040buy\040some\040more,\040.pc.\n.e.d.a.tTake\040one\040down\040and\040pass\040it\040around,\040.p.m.e..o\n.o\n.o.a - Content (escaped):
.cd.y.t\040on\040the\040wall.mXXq.a.s.c.n.t\040of\040beer.m\001.zXXs.a\040bottle.p
Actual source
Filename
c.z.e,.o .oq.e.s..o
.o.-.c.y.sGo to the store and buy some more, .pc.
.e.d.a.tTake one down and pass it around, .p.m.e..o
.o
.o.a
Content
.cd.y.t on the wall.mXXq.a.s.c.n.t of beer.m.zXXs.a bottle.p
With comments
Inspired by Dorian's answer in Whitespace at first, then golfed well. Though both Whitespace and Pxem are stack-oriented programming language, their features are different, as in these:
- Whitespace has label and (conditional) go-to commands; Pxem has while-done loop.
- Both of them have subroutine, but Pxem can have only one subroutine. Also that of Pxem works as a function rather than a subroutine.
- Whitespace has commands that accesses to non-top items of its stack; Pxem can reverse items on stack.
- And more, I think.
Overall of the program
- Iteration from 99 to 1 on filename.
- Content stands for a subroutine to output strings that are frequently recycled. - It depends on top of stack. If the item is more than 99, it outputs " on the wall" in addition to "[0-9]+ bottles? of beer".
Filename
XX.z
# push 99;
# while size<2||[ $(pop) -ne $(pop) ]; do
.ac.zXX.z
# for i in $(reverse $(call $stack)); do
# push $i; done
## NOTE let it be "call" next time
.a.eXX.z
# push 44; putc $(pop); push 32; putc $(pop)
## NOTE DOTo is actually:
## if !empty; then : do above; fi
.a,.o .oXX.z
# push 113; call; pop
## NOTE 113>=100
.aq.e.sXX
# push 46; putchar $(pop);
# push 10; putchar $(pop)
.a..o\n.oXX.z
# push 1;
# push $(( (x=$(pop)-$(pop))<0?-x:x ))
## NOTE arithmetic operators actually:
## check if size>=2 before;
## NOP if size<2
.a\001.-XX.z
# dup; push 1;
# while size<2||[ $(pop) -gt $(pop) ]; do
.a.c\001.yXX.z
# pop;
## NOTE literal is pushed from backwards
# for i in 32 44 --- 71; do push $i; done
.a.sGo to the store and buy some more, XX.z
# while !empty; do putchar $(pop); done
.a.pXX.z
# push 10; push 46; push 99;
# call
.ac.\n.eXX.z
# exit
.a.dXX.z
# done
.a.aXX.z
# if !empty; do heap=$(pop); fi
# for i in 32 44 --- 84; do push $i; done
.a.tTake one down and pass it around, XX.z
# while !empty; do putc $(pop); done
.a.pXX.z
# case ${heap:+y} in (y)
# push $heap;; esac;
# call; push 46; putc $(pop);
# push 10; putc $(pop)
# push 10; putc $(pop)
.a.m.e..o\n.o\n.oXX.z
# done
.a.a
Content
XX.z
## NOTE subroutine stack is initialized
## to be same as that of its caller
## but its heap is initialized to be empty,
## which is not shared to its caller
## So, implicitly: stack="$*"
## NOTE when returning to subroutine,
## heap is discarded but items on its
## stack is pushed to its caller, from
## bottom to top
# dup; push 100;
# while size<2||[ $(pop) -gt $(pop) ]; do
.a.cd.yXX.z
# heap=$(pop)
.a.tXX.z
# for i in 108 108 --- 32; do push $i; done;
# push $heap;
# push 113; push 88; push 88
.a on the wall.mXXqXX.z
# done
.a.aXX.z
# pop; dup; printf %d $(pop)
.a.s.c.nXX.z
# heap=$(pop)
.a.tXX.z
# for i in 114 101 --- 32; do push $i; done;
# push $heap; push 1;
# while size<2||[ $(pop) -ne $(pop) ]; do
.a of beer.m\001.zXX.z
# push 115; push 88; push 88
.aXXXXs.z
# done
.a.aXX.z
# for i in 101 --- 32; do push $i; done;
# while !empty; do putc $(pop); done
.a bottle.pXX.z
# (* implicitly *) return $stack (* to its caller *)
.a
APL (Dyalog Unicode), 200 bytes
-18 thanks to Razetime
d←'.'
q←'s',⍨w←'bottle'
x←∊a z←' of beer' ' on the wall'
{⎕←∊⍵q x','⍵q a d⋄⎕←∊'Take one down and pass it around,'(⍵-1)w('s'/⍨⍵≠2)x d}¨⌽1↓⍳99
∊1w x','1w a d
∊'Go to the store and buy some more,'99q x d
AWK, 198 bytes
a=100{d=" on the wall";e=" of beer";for(f=" bottle";a--;$0=g)g=g (a?(c=a f (a-1?"s":b)e)d", "c".\nTake one down and pass it around, "c d".\n\n":"Go to the store and buy some more, 99"f"s"e d".\n")}1
I didn't see AWK on the last yet, so here's one example.
This code will print the whole "99 bottles..." dialogue for every line of input fed into the code. I'm not sure how best to break this apart, but maybe this helps?
a=100{ ... }
Something truthy to trigger the code block, also sets the loop variable a to 100.
d=" on the wall";e=" of beer";
Store some re-used strings in variables.
for(f=" bottle";a--;$0=g)
The loop control, first set f in the loop init to save a ;. Then stop/go based on a after decrementing. At the end of the each iteration, set $0 to the accumulated output in g.
g=g ( ... )
Append the text for the next number of bottes to the accumulating output. Sadly the space is needed to avoid AWK parsing g( as a function call.
a?
Ternary for "is there more bottles?"
(c=a f (a-1?"s":b)e)
When there is more than one bottle... Generate "NN bottle of beer" or "NN bottles of beer" to be appended to g and also store that string in c. Using b in the ternary instead of "" saves a character and works since using an uninitialized variables as a string in AWK are treated like empty strings.
d", "c".\nTake one down and pass it around, "c d".\n\n"
Also append the rest of the text we need, making use of c set previously
:"Go to the store and buy some more, 99"f e d".\n"
When at zero bottles, append the last bit of text.
1
A truthy value with no code block causes the default action, which is to print the value of $0
<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>
Plain TeX (237 characters)
\input tikz\let~\def~\1#1{ bottle#1 of beer}~\7{~ on the wall}~\9#1#2{\def~{ #1\1#2}Take one down and pass it around,\7.\bigskip\par\7,~.\par}~~{ 99\1s}\7,~.\par\foreach\2in{98,...,2}{\9\2s}{\91 }Go to the store and buy some more,\7.\bye
Any Comments Appreciated
Please help me golf this code to an unhealthy extent.
C#, 205 bytes
()=>{for(int i=299;i-->2;)System.Console.Write(@$"{i/3:0;;99} bottl{i/3^1:es;;e} of beer{i%3-3/i: on the wall;\.
Go to the store and buy some more;\.
Take one down and pass it around}{~i%3:;\, ;\.
;}");};
As an anonymous lambda. A full program scores 227.
Putting custom numeric formats to good use. I'm particularly satisfied with i%3-3/i to select between Take one down, Go to the store, and on the wall.
Python, 357 339 310 bytes
After shaving off the fat to meet the expected output it didn't save as many bytes as I had expected:
def B(n):A='bottle';return A if n==1 else A+'s'
A=99
while A>=1:F='of';D=F+' beer';E='more';C=D+' on the wall';G='no '+E;H=f"Take one down and pass it around, {A-1 if A>1 else G} {B(A-1)} {C}\n"if A!=1 else f"Go to the store and buy some {E}, 99 {B(2)} {C}.";print(f"{A} {B(A)} {C}, {A} {B(A)} {D}.\n"+H);A=A-1
The following code is for code-golf output:
This is the lowest I can hit so far
def B(n):A='bottle';return A if n==1 else A+'s'
A=99
while A>=0:G='of';D=G+' beer';E='more';C=D+' on the wall';F='no '+E;print(f"{A} {B(A)} {C}, {A} {B(A)} {D}.\nTake one down and pass it around, {A-1 if A>1 else F} {B(A-1)} {C}.\n"if A!=0 else f"No {E} {B(2)} {C}, {F} {B(2)} {D}.\nGo to the store and buy some {E}, 99 {B(2)} {C}.");A=A-1
Here's the sort of bigger version:
def get_bottles(num_bottle):
p = "bottle"
return p if num_bottle == 1 else p + "s"
bottleNo = 99
while bottleNo >= 0:
of = "of"
beer = of + " beer"
more = "more"
botw = beer + " on the wall"
noMore = "no " + more
print(f"{bottleNo} {get_bottles(bottleNo)} {botw}, {bottleNo} {get_bottles(bottleNo)} {beer}.\nTake one down and "
f"pass it around, {bottleNo - 1 if bottleNo > 1 else noMore} {get_bottles(bottleNo - 1)} {botw}.\n" if
bottleNo != 0
else f"No {more} {get_bottles(2)} {botw}, {noMore} {get_bottles(2)} {beer}.\nGo to the store "
f"and buy some {more}, 99 {get_bottles(2)} {botw}.")
bottleNo = bottleNo - 1
Unix TMG, 231 byte
o:parse(v)[n<143?]\o;v:b l b={3< on the wall, >3<.>*2 1< on the wall.>**};b:decimal(n)([n>1?]={<s>}|={})={2< bottle>1< of beer>};l:[--n?]={<Take one down and pass it around, >}|[n=143]={<Go to the store and buy some more, >};n:143;
Expanded:
o: parse(v) [n<143?]\o;
v: b l b = {3 < on the wall, > 3 <.> * 2 1 < on the wall.> * * };
b: decimal(n) ([n>1?]={<s>}|={}) = {2 < bottle> 1 < of beer>};
l: [--n?] = {<Take one down and pass it around, >}
| [n=143] = {<Go to the store and buy some more, >};
n: 143;
The fact that this 1972 language uses octal instead of decimal doesn't help in this challenge 😂
C (gcc), 229 bytes
#define B" bottle%c of beer"
#define W" on the wall"
f(x){for(x=99;x;)printf("%d"B W", %1$d"B".\n%s, %d"B W".\n\n",x+1,'s'*!!x,'s'*!!x,x?"Take one down and pass it around":"Go to the store and buy some more",x?x:99,--x-1?'s':0);}
Needs more golf...
C# (Visual C# Interactive Compiler), 243 bytes
for(int i=99;i>0;){string s="s",a=" bottle",b=" of beer",w=" on the wall",c=$"{i+a+(i>1?s:"")+b}";Write(@$"{c+w}, {c}.
{(--i>0?$"Take one down and pass it around, {i+a+(i>1?s:"")+b+w}":$"Go to the store and buy some more, 99{a+s+b+w}")}.
");}
Keg, 222 bytes
c&(c|&:.& bottle&:&1>[s] of beer on the wall\, ^(,)&:.& bottle&:&1>[s] of beer\.
^(,)&:&1=[Go to the store and buy some more|Take one down\, pass it around]\, ^(,)&:&1=[\9\9|&;:.&] bottle&:&1>[s] of beer on the wall\.
^(,
Explanation
- First it stores the current counter into the accumulator
- Then it prints all verses accordingly until the last verse
- Finally this hard-codes the final verse
Let's see if I can get this any shorter.
Wren, 246 bytes
System.print((99..1).map{|i|"~ on the wall, ~.\n%(i>1?"Take one down and pass it around":"Go to the store and buy some more"), %(i>1?i-1:99) bottle%(i!=2?"s":"") of beer on the wall.".replace("~","%(i) bottle%(i>1?"s":"") of beer")}.join("\n\n"))
Whitespace, 1977 1342 1013 877 bytes
(very much whitespace)
Finally, under 1000 bytes.
-635 bytes by manually correcting the automatic whitelips labels
-329 bytes by offsetting the letters and using 0 for spaces
-136 bytes by pushing whole sentences in one big integer and using divmod to calculate the letters.
visible code:
sssttsssttl push 99
lssssl label main:
lsttl call wall
lststl call comma_space
lsttsl call beer
lstsl call stop_nl
ssstl push 1
tsst sub
lstttl call take
lststl call comma_space
lsttl call wall
lstsl call stop_nl
ssststsl push newline (10)
tlss printc
lslssl jump main
lssttl label take:
sls dup
ltssssl jz store
ssstststssl "T"
tlss printc
ssstsstsstttssttsssttsststtstststststssststssttsttttttstsssstttstsssttstttssstssssttsssssssssttsstttststttsssttsssttststtstsssttttstssssttsstssssttl
"ake one down and pass it around"
lsll jmp print
lsssssl label store:
sll drop
sssttsssttl push 99
ssstssstttl "G"
tlss printc
ssstsstststttttsttssssststtstttttssttsstsststttssssttsssttsssssttstssttstststtsttsttstssssstsssttstsstttttttssssttsttsttstststsststtssttsstssttttsttstttl
"o to the store and buy some more"
lstl call print
lststl call comma_space
lsttl call wall
lstsl call stop_nl
lll end
lsssl label stop_nl:
ssststttsl "."
tlss printc
ssststsl <lf>
tlss printc
ltl return
lssstl label comma_space:
ssststtssl ","
tlss printc
sssl 0
lsll jmp print
lsstl label wall:
lsttsl call beer
ssststssststssssttttttsstttsstststttstssttsstsssssstttttttsl
" on the wall"
lsll jmp print
lsstsl label beer:
lststtl call bottles
ssstssstssssstsssttsttsttstttssstttsttttsl
" of beer"
lsll jmp print
lsssttl label bottles:
sls dup bottlecount
tlst printi
sssttsststsstssssstttsttssttttssssl
" bottle"
lstl call print
sls dup bottlecount
ssstl push 1
tsst sub
ltststl jz return
ssstssttl 's'
lssl label print:
sssttstsl 26
stsstl copy 1
stsstl copy 1
tstt mod
sls dup
ltstssl jz space
ssstssssssl push 64
tsss add
lsstssl label space:
ssstsssssl push 32
tsss add
tlss printc
tsts div
sls dup
ltsstsl jz end_print
lsll jump print
lssstsl label end_print:
sll drop
lsststl label return:
ltl return
Hexadecimal Stacking Pseudo-Assembly Language, 2208 bytes
20000140030000000620100040000000001642030040040041000040010020000140000041010040000022000042000040000040000030000003000001001620006340000003040001000000000120001140010003040001000200001120006C40020020006C40020020006140020020007740020020002040020020006540020020006840020020007440020020002040020020006E40020020006F40020020002040020003040014020003040002010000000220001240010003040001000300001220007240020020006540020020006540020020006240020020002040020020006640020020006F40020020002040020003040014020003040002010000000342000040000003040012000020006540020020006C40020020007440020020007440020020006F40020020006240020020002040020003040014020042000040000042000040000020000140000030000020000040000030000003000002010020007340020003040014020003040002010000000442000040000020000040000030000020000040000030000003000001000520006440020020006E40020020007540020020006F40020020007240020020006140020020002040020020007440020020006940020020002040020020007340020020007340020020006140020020007040020020002040020020006440020020006E40020020006140020020002040020020006E40020020007740020020006F40020020006440020020002040020020006540020020006E40020020006F40020020002040020020006540020020006B40020020006140020020005440020003040014020003040002010000000520002040020020002C40020020006540020020007240020020006F40020020006D40020020002040020020006540020020006D40020020006F40020020007340020020002040020020007940020020007540020020006240020020002040020020006440020020006E40020020006140020020002040020020006540020020007240020020006F40020020007440020020007340020020002040020020006540020020006840020020007440020020002040020020006F40020020007440020020002040020020006F40020020004740020003040014020020006340000020001540010003040001000100001520002E40020003040014020003040001002700000020001040010003040001000100001020002040020020002C40020003040014020020002040010003040001000200002020000A40020020002E40020003040014020041000040010020000140000041010040000022000020003040010003040001000400003020002040020020002C40020003040014020020004040010003040001000100004020000A40020020000A40020020002E400200030400140200030400010000000007410200430200400000400000300000030000010007000017410400430400400000400000300000030000010017000027400300300303420300400300030300010006
That was quite some work, because the language has a few difficulties (or maybe just interpreter bugs)
You can only jump to labels you have been before, so basically you have to run through the code, skipping every jump and print command, and then you can run it
Subtracting is "backwards". For example, 100-1 is
push 1,push 100,sub, what makes loops a bit difficult.It can't handle negative values, so using -1 + 100 instead, isn't possible. If you try to calculate 0-1, you will get 0 as the result.
The functions
NOTandXORaren't working (I didn't try ifANDandORare working)The only conditional is "skip next command, if popped value is not zero", which is exactly opposite to all other esoteric languages I know so far.
You have to push return-labels by yourself (and you can't return to a label where you haven't been before)
So what the code does is, it sets up a list of 1's on the initializing-stack and uses them to skip every jump and print command, then it deletes the list, fills it with 0's and runs the main loop.
Stack 0: bottle count, Stack 1: return labels, Stack 2: Strings, Stack 3: Initialize flag, Stack 4: Initialize Queue
200001 1
400300 push initialize = 1
000006 initializer:
201000 0x1000 (init_counter)
400000 push
000016 initialize_loop:
420300 peek initialize
400400 push init_queue
410000 pop init_counter
400100 push on other stack
200001 1
400000 push
410100 pop init_counter
400000 push to counter_stack
220000 sub
420000 peek init_counter
400000 push
400000 push 0
300000 equals
030000 if init_counter > 0
010016 go to initialize loop
200063 99
400000 push
030400 if not initializing
010000 go to main
000001 Label wall:
200011 0x11 (return address)
400100 push retstack
030400 if not initializing
010002 jmp beer
000011 Label Return_beer_wall
20006C 'l'
400200 push
20006C 'l'
400200 push
200061 'a'
400200 push
200077 'w'
400200 push
200020 ' '
400200 push
200065 'e'
400200 push
200068 'h'
400200 push
200074 't'
400200 push
200020 ' '
400200 push
20006E 'n'
400200 push
20006F 'o'
400200 push
200020 ' '
400200 push
030400 if not initializing
140200 print string
030400 if not initializing
020100 return
000002 Label beer:
200012 0x12 (return address)
400100 push retstack
030400 if not initializing
010003 jmp bottles
000012 Label Return_bottles_beer
200072 'r'
400200 push
200065 'e'
400200 push
200065 'e'
400200 push
200062 'b'
400200 push
200020 ' '
400200 push
200066 'f'
400200 push
20006F 'o'
400200 push
200020 ' '
400200 push
030400 if not initializing
140200 print string
030400 if not initializing
020100 return
000003 Label bottles:
420000 peek bottle count
400000 push
030400 if not initializing
120000 print number
200065 'e'
400200 push
20006C 'l'
400200 push
200074 't'
400200 push
200074 't'
400200 push
20006F 'o'
400200 push
200062 'b'
400200 push
200020 ' '
400200 push
030400 if not initializing
140200 print string
420000 get bottle count
400000 push
420000 get bottle count
400000 push
200001 1
400000 push
300000 equals
200000 0
400000 push
300000 equals
030000 skip if true
020100 return
200073 's'
400200 push
030400 if not initializing
140200 print string
030400 if not initializing
020100 return
000004 Label Take:
420000 get bottle count
400000 push
200000 0
400000 push
300000 equals (bottle count = 0)
200000 0
400000 push
300000 equals (bottle count != 0)
030000 if bottle count = 0
010005 jmp Store
200064 d
400200 push
20006E n
400200 push
200075 u
400200 push
20006F o
400200 push
200072 r
400200 push
200061 a
400200 push
200020
400200 push
200074 t
400200 push
200069 i
400200 push
200020
400200 push
200073 s
400200 push
200073 s
400200 push
200061 a
400200 push
200070 p
400200 push
200020
400200 push
200064 d
400200 push
20006E n
400200 push
200061 a
400200 push
200020
400200 push
20006E n
400200 push
200077 w
400200 push
20006F o
400200 push
200064 d
400200 push
200020
400200 push
200065 e
400200 push
20006E n
400200 push
20006F o
400200 push
200020
400200 push
200065 e
400200 push
20006B k
400200 push
200061 a
400200 push
200054 T
400200 push
030400 if not initializing
140200 print string
030400 if not initializing
020100 return
000005 Label Store:
200020 ' '
400200 push
20002C ','
400200 push
200065 e
400200 push
200072 r
400200 push
20006F o
400200 push
20006D m
400200 push
200020
400200 push
200065 e
400200 push
20006D m
400200 push
20006F o
400200 push
200073 s
400200 push
200020
400200 push
200079 y
400200 push
200075 u
400200 push
200062 b
400200 push
200020
400200 push
200064 d
400200 push
20006E n
400200 push
200061 a
400200 push
200020
400200 push
200065 e
400200 push
200072 r
400200 push
20006F o
400200 push
200074 t
400200 push
200073 s
400200 push
200020
400200 push
200065 e
400200 push
200068 h
400200 push
200074 t
400200 push
200020
400200 push
20006F o
400200 push
200074 t
400200 push
200020
400200 push
20006F o
400200 push
200047 G
400200 push
030400 if not initializing
140200 print string
200063 99
400000 push bottle counter
200015 0x15 (return address)
400100 push retstack
030400 if not initializing
010001 jmp wall
000015 Label Return_wall_Store
20002E '.'
400200 push
030400 if not initializing
140200 print string
030400 if not initializing
010027 go to end_program
000000 Label Main:
200010 0x10 (return address)
400100 push retstack
030400 if not initializing
010001 jmp wall
000010 Label Return_wall_main
200020 ' '
400200 push
20002C ','
400200 push
030400 if not initializing
140200 print string
200020 0x20 (return address)
400100 push retstack
030400 if not initializing
010002 jmp beer
000020 Label Return_beer_main
20000A <nl>
400200 push
20002E '.'
400200 push
030400 if not initializing
140200 print string
410000 pop bottle count
400100 push on other stack
200001 1
400000 push
410100 pop bottle count
400000 push to original stack
220000 sub
200030 0x30 (return address)
400100 push retstack
030400 if not initializing
010004 jmp Take
000030 Label Return_Take_main
200020 ' '
400200 push
20002C ','
400200 push
030400 if not initializing
140200 print string
200040 0x40 (return address)
400100 push retstack
030400 if not initializing
010001 jmp wall
000040 Label Return_wall_main_2
20000A <nl>
400200 push
20000A <nl>
400200 push
20002E '.'
400200 push
030400 if not initializing
140200 print string
030400 if not initializing
010000 jmp main
000007 flush_strings:
410200 pop character
430200 get strings-stack size
400000 push
400000 push 0
300000 equals
030000 if characters left
010007 go to flush_strings
000017 flush_init_queue:
410400 pop entry
430400 get init_queue_stack size
400000 push
400000 push 0
300000 equals
030000 if entries left
010017 go to flush_init_queue
000027 end_program:
400300 push 0
300303 equals
420300 peek initialize
400300 push initialize
030300 if not initialize
010006 go to initializer
Assembly (MIPS, SPIM), 676 623 575 570 bytes
.data
a: .asciiz " bottle"
c: .asciiz " bottles"
e: .asciiz " of beer.\n"
f: .asciiz " of beer on the wall, "
g: .asciiz " of beer on the wall.\n"
h: .asciiz "Take one down and pass it around, "
i: .asciiz "Go to the store and buy some more, "
.text
.globl main
main:
li $8 99
li $11 1
y:
la $9 f
jal t
la $9 e
jal t
addi $8 -1
beq $8 $0 v
la $4 h
syscall
la $9 g
jal t
li $2 11
li $4 10
syscall
j y
t:
move $4 $8
li $2 1
syscall
li $2 4
beq $8 $11 q
la $4 c
j r
q:
la $4 a
r:
syscall
move $4 $9
syscall
jr $ra
v:
la $4 i
syscall
li $8 99
la $9 g
jal t
li $2 10
syscall
Turns out it's actually cheaper to declare "bottle" and "bottles", as well as strings with newlines and commas directly in place, and just select between them. Also, using all the syscalls is actually cheaper than the alternative, though only because the the call pointer register is hidden. MIPS' need for newlines actually makes this surprisingly readable, if you know the opcodes. For those of you trying to decipher it, t is a function to print the variations of " bottle[s] of beer...," and $9 stores the address of the string to finish that phrase. One annoying caveat was the fact that all the verses require a newline between them, but the end cannot have two newlines (afaik). So theres a section at the end of the loop that prints a single character, which happens to be newline (decimal 10).
Edit: saved 5 bytes by using $9 instead of $10. I had originally used $9, but optimized it out, and forgot to shift the registers optimally. Also, this submission took forever because I was editing it in place.
Javascript ES6, 247 237 bytes
m=" bottles of beer",j=m.replace("s",""),k=" on the wall",a="";for(i=99;i>1;)a+=i+m+k+`, ${i+m}.
Take one down and pass it around, ${(--i)+(i-1?m:j)+k}.
`;a+=`1${j+k}, 1${j}. Go to the store and buy some more, 99${m+k}.`;console.log(a);
-10 bytes thanks to Jo King.
ink, 192 bytes
-(t)->c->v->
, ->c->
-(k){k<99:
Take one down and pass it around, ->c->v->
.
\
->t
}Go to the store and buy some more, ->c->v->
.
=c
{99-k%99} bottle{k-98:s} of beer->->
=v
on the wall<>->->
Not too bad for a non-esoteric language.
Explained
-(t) // A gather point, with the label t. We can divert here, and t can be read as a view counter.
->c->v-> // Go to c, then v, then return here
, ->c-> // Print a comma and a space, then go to c and return here
-(k) // Another labelled gather. Having the read counter be here is useful, because it means we handle the increment in the right spot.
{k<99: // The first 98 times:
Take one down and pass it around, ->c->v-> // Take one down and pass it around. Also, go to c and v.
. // Print a period
\ // Ink is a bit weird with whitespace, but this lets us force a newline. Note that there is one space after the backslash in the original.
->t // Back to the top
}Go to the store and buy some more, ->c->v-> // We only get here when k>=99
. // Print a period, then halt because we're out of content.
=c // In this stitch, we print how many bottles of beer we have. We use the k counter to keep track.
{99-k%99} bottle{k-98:s} of beer->-> // The modulo is to reset to 99 when we get back from the store. We also almost always print the s after bottle - but not when k is 98.
=v // "on the wall"
on the wall<>->-> // <> means don't print a newline after this string. You need to specify that sometimes.
Java 304 301 300 295 Bytes
First time posting an answer. I heard we could use enum but could not find how.
interface A{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
interface A {
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, J Atkin and Benjamin Urquhart
Lua 5.1, 211 207 bytes
(Also works in Lua 5.2 and Lua 5.3.)
4 bytes saved thanks to primo.
B=" on the wall"P=""S="Go to the store and buy some more"for i=1,99 do
A=i.." bottle"..P.." of beer"S=([[Take one down and pass it around, AB.
AB, A.
S]]):gsub(".",_G)P="s"end
print(S:sub(68)..S:sub(33,65))
I chop up the song into chunks that have the same number of bottles of beer which simplifies the interpolation at the cost of some slicing at the end. This also allows constructing the verses backwards which simplifies the logic for pluralizing "bottle".
:gsub(".",_G) is a fun little call that replaces each character in a string with its value as a global variable (with no replacement if the global variable is not defined).
I played around with some of the tricks seen in the Python answers, but I wasn't able to beat this yet. It may still be possible to do a better in-order solution though.
C++, 288 289 282 bytes
#import<iostream>
int i,v;main(){for(i=99;i>0;i--)printf("%1$d%6$s%2$s%7$s%8$s, %1$d%6$s%2$s%7$s.\n%3$s, %4$d%6$s%5$s%7$s%8$s.\n\n",i,i-1?"s":"",i-1?"Take one down and pass it around":"Go to the store and buy some more",v=i-1?:99,v-1==1?"":"s"," bottle"," of beer"," on the wall");}
Requires no additional compile flags.
Ideone: https://ideone.com/fhL9Lv
ES7, 275 bytes
for(x=99,a=``;x;)a+=x+` bottles of beer on the wall, ${x} bottles of beer,
Take one down and pass it around, ${x--} bottle${x-1?"s":""} of beer on the wall.
`;a+=`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.`
Feel free to find bugs and to give ideas on how to optimize the code.
Python 3, 288 266 253 (credit: Jo King) 251 242 bytes
b=lambda x:"%s bottle%s of beer"%(x,"s"*(x>1));o="on the wall"
for i in range(99,0,-1):print("\n%s %s, %s.\n%s"%(b(i),o,b(i),["Take one down and pass it around, %s %s."%(b(i-1),o),"Go to the store and buy some more, %s %s."%(b(99),o)][i==1]))
PowerShell, 228 227 220 221 bytes
$a,$l,$e,$s=" bottles of beer"," bottle of beer"," on the wall","Take one down and pass it around, "
99..3|%{"$_$a$e, $_$a.
$s$($_-1)$a$e.
"}
"2$a$e, 2$a.
$s`1$l$e.
1$l$e, 1$l.
Go to the store and buy some more, 99$a$e."
Psssh, who needs fancy-pants logic. (Spoilers: Better answers do) This just manually builds the last two lines instead of doing clever stuff. Also, saved 7 bytes by replacing `n with an actual line break. Lost a byte because I forgot to punctuate.
Powershell, 208 207 bytes
-1 byte, thanks @Veskah
inspired by Veskah's answer.
$l,$e,$o=" bottles of beer"," bottle of beer"," on the wall"
99..1|%{"$_$l$o, $_$l."
if($_---le2){$l,$e=$e,$l}"$(("Take one down and pass it around, $_","Go to the store and buy some more, 99")[!$_])$l$o.
"}
Psssh, is a swap a clever stuff? :)
Python 3, 243 bytes
b=lambda x,y: f'{x} bottle{("","s")[x>1]} of beer{(""," on the wall")[y]}'
p=print
for i in range(99,0,-1):
p(f'{b(i,1)}, {b(i,0)}.')
p((f'Go to the store and buy some more, {b(99,1)}.',f'Take one down and pass it around, {b(i-1,1)}.')[i>1])
Perl 6, 226 bytes
sub b(\a,$b?){a~' bottle'~('s'if a-1)~' of beer'~(' on the wall'if $b)}
for 99…1 ->\a{say b(a,1)~", "~b(a)~'.
'~(if a-1 {'Take one down and pass it around, '~b a,1;}else{'Go to the store and buy some more, '~b 99,1;})~'.
';}
T-SQL, 334 bytes
WITH n AS(SELECT 99c UNION ALL SELECT c-1FROM n WHERE c>2),s
AS(SELECT' bottles of beer'b,' on the wall'w,'.
Take one down and pass it around, 't)SELECT
CONCAT(c,b,w,', ',c,b,t,c-1,IIF(c=2,STUFF(b,8,1,''),b),w,'.')FROM n,s
UNION ALL SELECT REPLACE(CONCAT(1,b,w,', ',1,b),'s','')+'.
Go to the store and buy some more, 99'+b+w+'.'FROM s
Inspired by but different than both other T-SQL answers. Note that both these answers have a bug on the 2nd to last verse, they output 1 bottles instead of 1 bottle. If I allow that bug in my code, too, I can get down to 309 bytes by removing IIF(c=2,STUFF(b,8,1,''),b).
In my case I'm joining together a table of numbers and a table of strings, and using the CONCAT() function to assemble each verse.
I then construct the very last verse separately using UNION ALL. REPLACE() is used to make both of the bottle singular.
Gema, 210 206 characters
\A=@set{b;99}@repeat{99;@w{}, @b{}.\n@cmpn{$b;1;;Go to the store and buy some more@set{b;99};Take one down and pass it around@decr{b}}, @w{}.\n\n}@end
b:=$b bottle@cmpn{$b;1;;;s} of beer
w:=@b{} on the wall
Sample run:
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.
17, 1180 bytes
0 {
2 #
1 -
:
2 @
3 <
0 @
1f : : : : : : : : : : : : : : : : : : : : : :
2 # $$
$ 5d $ 69 $ 6e $ 6e $ 66 $ 5g $ 6d $ $ 69 $ 60 $ $ 5d $ 5g $ 5g $ 6c $ $ 69 $ 68 $ $ 6e $ 62 $ 5g $ $ 70 $ 5c $ 66 $ 66 $ 2a $ $
2 # $$
$ 5d $ 69 $ 6e $ 6e $ 66 $ 5g $ 6d $ $ 69 $ 60 $ $ 5d $ 5g $ 5g $ 6c $ 2c $ a $
4g $ 5c $ 65 $ 5g $ $ 69 $ 68 $ 5g $ $ 5f $ 69 $ 70 $ 68 $ $ 5c $ 68 $ 5f $ $ 6a $ 5c $ 6d $ 6d $ $ 63 $ 6e $ $ 5c $ 6c $ 69 $ 6f $ 68 $ 5f $ 2a $ $
2 # 1 - $$
$ 5d $ 69 $ 6e $ 6e $ 66 $ 5g $ 6d $ $ 69 $ 60 $ $ 5d $ 5g $ 5g $ 6c $ $ 69 $ 68 $ $ 6e $ 62 $ 5g $ $ 70 $ 5c $ 66 $ 66 $ 2c $ a $ a $
}
1 {
1f : : : : : : : : : : : : : : : : : : : : : : :
2f $ $ 5d $ 69 $ 6e $ 6e $ 66 $ 5g $ $ 69 $ 60 $ $ 5d $ 5g $ 5g $ 6c $ $ 69 $ 68 $ $ 6e $ 62 $ 5g $ $ 70 $ 5c $ 66 $ 66 $ 2a $ $ 2f $ $ 5d $ 69 $ 6e $ 6e $ 66 $ 5g $ $ 69 $ 60 $ $ 5d $ 5g $ 5g $ 6c $ 2c $ a $
43 $ 69 $ $ 6e $ 69 $ $ 6e $ 62 $ 5g $ $ 6d $ 6e $ 69 $ 6c $ 5g $ $ 5c $ 68 $ 5f $ $ 5d $ 6f $ 72 $ $ 6d $ 69 $ 67 $ 5g $ $ 67 $ 69 $ 6c $ 5g $ 2a $ $ 36 $ 36 $ $ 5d $ 69 $ 6e $ 6e $ 66 $ 5g $ 6d $ $ 69 $ 60 $ $ 5d $ 5g $ 5g $ 6c $ $ 69 $ 68 $ $ 6e $ 62 $ 5g $ $ 70 $ 5c $ 66 $ 66 $ 2c $ a $
0 @
}
777 {
5f 2 @
0 1 @
0 0 @
}
Brainfuck, 743 bytes
++++++++++>>--->++++>------>-->>++>+>>+>->++[[>+++++++[>++>+>+<<<-]<-]+<+++]>>>>>--
>>-->>++>->+++[<]>[-<<+[<->-----]<---[<[<]>[->]<]+<[>-]>[-<++++++++++<->>>]-[<->---
--]<+++[<[<]>[+>]<]<->>>[>[[>]<<<<.<<<<---.>>>-.<<<++++.<.>>>.-.<<.<.>-.>>+.<+++.>-
.<<<.>---.>>.<<+++.<.>>>++.<<---.>----..<<.>>>>--.+++<<+.<<.>.>--.>-.<+++.->-.+<<++
+.<<.>.<<<<-<]>[[>]<<<-.<<<.<<<.>>.>.<<< . > > .<++++.---.<.>>-.+.>.<--.<.<.>----.>
>-.<<+++.<.>--.>+++.++++.<<.>>------.>+.--.<<+++.<.>>>.++.<-.++<.-<<.>.<<<<-<<<++++
+++++.>>>]<+>]<++[<<[<]>[.>]>>>>>>.>--.>>.<..->>.<<<+++.<<<<-[>>>>>.[<]]<[>]>+>>>.>
>>.<<+.<.>----.+++..->-.++[<<]<-[>>>>>.>>>.-.+<<<.>>.<++++.---.<.>>+++.---<----.+++
>>>..[<<]]<<[>]>-[>>>>++.--<.<<<+[>>>.<<<<]>[>]<-<]>>[>>.>.<<<<]>[<<++>]<[>]<-]>+>]
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
>+>
]
Python, 245 223 bytes
w="bottles of beer on the wall"
[print(i,w+',',w[:15]+'.\nTake one down and pass it around,',str(i-1),w+'.\n')for i in range(99,1,-1)]
print('1 bottle',w[8:],',1 bottle',w[8:15]+'.\nGo to the store and buy some more,',99,w)
edit: thank you GamrCorps for the suggestion to cut down over 20 bytes!
Funky, 290 bytes
for(i=99;i>0;i--)print("%i %s on the wall, %i %s.%sTake one down and pass it around %i %s on the wall."::format(i,c=(b="bottle%s of beer")%(i>1)?"s":"",i,c,"\n",i,c))print("0 %s on the wall, 0 %s.%sGo to the store and buy some more, 99 bottles of beer on the wall."::format(c=b%"s",c,"\n"))
Prolog (SWI), 312 bytes
w(X):-write(X).
e:-w('.'),nl.
t(X):-w(X),b(X).
b(B):-B>1,w(' bottles of beer').
b(B):-B=1,w(' bottle of beer').
c(B):-t(B),w(' on the wall').
r(N):-N=0,w('Go to the store and buy some more, '),c(99),e.
r(N):-N>0,w('Take one down and pass it around, '),c(N),e,nl.
s(X):-X>0,c(X),w(', '),t(X),e,N is X-1,r(N),s(N).
Java 8, 245 bytes
i->{String b=" bottle",o=" of beer",n=" on the wall",t=b+o,w=b+'s'+o,e=".\n";while(--i>0)out.print(i<2?i+t+n+", "+i+t+e+"Go to the store and buy some more, 99"+w+n+e:i+w+n+", "+i+w+e+"Take one down and pass it around, "+~-i+(i<3?t:w)+n+e+'\n');}
Outputs the whole of the lyrics with a trailing newline at the end.
Explanation (slightly ungolfed):
i->{
/*
* t = " bottle of beer";
* w = " bottles of beer";
*/
String b=" bottle",o=" of beer",n=" on the wall",t=b+o,w=b+'s'+o,e=".\n";
while(--i>0) // taking advantage of input from lambda statement
out.print(i<2?i+t+n+", "+i+t+e+"Go to the store and buy some more, 99"+w+n+e
:i+w+n+", "+i+w+e+"Take one down and pass it around, "+~-i+(i<3?t:w)+n+e+'\n');
/*
* if i<2:
* print 'n bottles' in singular form and the final part of the lyrics through simple concatenation
* else:
* print 'n bottles' in plural form plus 'n-1 bottles' through the use of the ternary operator and
* '~' - a unary operator that, when placed in the order above, decreases the value of i by 1
*/
}
Python, 172 bytes
a="\n%s bottles of beer on the wall"
t="\n\nTGaok et oo nteh ed oswtno raen da npda sbsu yi ts oamreo umnodr e"
d=99
while d:print(a%d*2)[:-12]+t[d==1::2]+a%(d-1or 99);d-=1
Explanation:
a="\n%s bottles of beer on the wall"
Stores the first line of the lyrics with a formatted argument.
t="\n\nTGaok et oo nteh ed oswtno raen da npda sbsu yi ts oamreo umnodr e"
Stores the third line. The characters at even indices make up Take one down and pass it around, and the characters at odd indices make up Go to the store and buy some more.
d=99
Counter variable for the current number of bottles, initialized to 99.
while d: d-=1
In Python (and most other languages), a non-zero integer is truthy, while 0 is falsey. This while loop (although kind of hacky) repeats until d is 0, subtracting 1 from d every time.
print + + ;
I used only one print statement to save bytes, and just added multiple strings together.
(a%d*2)[:-12]
Formats the first line with the number of bottles, repeats it, and chops off the on the wall part from the first line to make the second line.
t[d==1::2]
Extended slicing. Takes every other character, starting from the first character if d is not 1, but starting from the second character is d is 1. In Python, booleans can be implicitly converted to integers, so true would turn into 1, and false would turn into 0.
a%(d-1or 99)
Just the first line again, except this time with one less bottle. Again, anything except 0 is truthy, so if d-1 is 0, it will give 99 instead.
PowerShell (204 bytes)
$b='bottles of beer';$w="on the wall";$p="Take one down and pass it around";99..2|%{"$_ $b $w, $_ $b.`n$p, $($_-1) $w.`n"};$b=$b.remove(6,1);"1 $b $w, 1 $b.`nGo to the store and buy some more, 99 $b $w."
Edit (now 198 bytes as per @BradC comments, thx buddy!):
$b=' bottles of beer';$w=" on the wall";$p="Take one down and pass it around";99..2|%{"$_$b $w, $_$b.`n$p, $($_-1)$w.`n"};$b=$b.remove(6,1);"1$b$w, 1$b.`nGo to the store and buy some more, 99$b$w."
Julia 0.6.0 (256 bytes)
b=" bottle";d=" of beer";w=" on the wall, ";t="Take one down and pass it around,";i=99;k=println;while i>0 (i>1)&&(k(i,b*"s",d,w,i,b*"s",d);k(t,i,b*"s",d,w));(i==1)&&(k(i,b,d,w,i,b,d));i-=1 end;k("Go to the store and buy some more, ",99,b*"s",d,w[1:end-2])
I know there is already a Julia answer, but I wanted to tackle it anyway! I only have a few bytes more then the other Julia so maybe I can find a way to chop some here and there!
Ly, 272 bytes
(99)1[psu" bottles of beer on the wall, "&olu" bottles of beer.\n"&ol1-sp"Take one down and pass it around, "&olu" bottles of beer on the wall.\n"&ol1G]pu" bottle of beer on the wall, 1 bottle of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."&o
T-SQL, 671 653 517 Bytes
Saw an Oracle one so I thought of doing it but I went for a cursor... Not competition level but still a lot of fun =)
DECLARE @q CHAR(15) = 'bottles of beer',@w CHAR(11)='on the wall',@e CHAR(33)='Take one down and pass it around,',@r INT=99,@i INT=1,@ INT=99 WHILE(@>=1)BEGIN SET @i=@-1 IF(@>1)BEGIN PRINT CONVERT(VARCHAR(2),@)+' '+@q+' '+@w+', '+CONVERT(VARCHAR(2),@)+' '+@q+'.'+CHAR(10)+@e+' '+CONVERT(VARCHAR,@i)+' '+@q+' '+@w+'.'+CHAR(13)END ELSE BEGIN PRINT CONVERT(VARCHAR(1),@)+' bottle of beer '+@w+', '+CONVERT(VARCHAR(1),@)+' bottle of beer.'+CHAR(10)+'Go to the store and buy some more, 99 '+@q+' '+@w+'.'END SET @=@-1 END
Proper indent:
DECLARE @q CHAR(15) = 'bottles of beer',
@w CHAR(11) = 'on the wall',
@e CHAR(33) = 'Take one down and pass it around,',
@r INT = 99,
@i INT = 1,
@ INT = 99
WHILE (@ >= 1)
BEGIN
SET @i = @ -1
IF (@ > 1)
BEGIN
PRINT
CONVERT(VARCHAR(2), @)+' '+@q+' '+@w+', '+CONVERT(VARCHAR(2), @)+' '+@q+'.'+CHAR(10)+
@e+' '+CONVERT(VARCHAR, @i)+' '+@q+' '+@w+'.'+CHAR(13)
END
ELSE
BEGIN
PRINT
CONVERT(VARCHAR(1), @)+' bottle of beer '+@w+', '+CONVERT(VARCHAR(1), @)+' bottle of beer.'+CHAR(10)+
'Go to the store and buy some more, 99 '+@q+' '+@w+'.'
END
SET @ = @-1
END
TLDCode, 235 bytes
='1'#99#p${e# bottle#PG(#s#P)v# of beer on the wall, #Pe# bottle#PG(#s#P)v# of beer.#Pn-(#Take one down and pass it around, #Pe# bottles of beer on the wall.#Pnn)[#Go to the store and buy some more, 99 bottles of beer on the wall.#P]}=
- we first clear the stack of the implicit input
- We start by pushing a 1 onto the stack, then pushing 99, since that is the first line.
- Then we define a repeatable code block that will repeat the amount of times equal to the value of the top of the stack (99)
- The first thing that is done on each repeat is printing the top of the stack.
- Followed by pushing and printing" bottle" and then if the top of the stack(99) is greater than the next in the stack(1) push and print an "s". Then we remove the top of the stack(the result of the comparison)
- Push and print " of beer on the wall, " followed by the printing the top of the stack(99).
- then we do step 4 again
- then we push and print " of beer." followed by printing a new line
- we then decrement the top of the stack (98)
- we then define a block that only executes if the top of the stack is true, or an integer greater than 0
- this just pushes and prints the second line
- then we define a block that only executes if the top of the stack is false or not greater than 0
- this pushes the last line
- we clear the stack to avoid the implicit printing
Ohm, 166 164 131 bytes (CP437)
Ohm has been updated a lot since I first posted this! Now I'm using some new features.
98@R≥î:_Θ▀a▀_Ωü▀5≡axÿx}iöܪ├┬ï°∙╟╕Ö√²┬zτα█▀_≤îΘ..ÑÑ;1Θ▀a▀1Ω▀â"190└δ*6²H"╥╨;√⌡ÄwîFδh#|a≡Ω█≡5▓Θ╕Ç≈└hÑqûI▀J
D≤y.sa·▀╖+╫Ä▀a
Θ▀Ö$k·}Qy╦▀
Explanation
The main wire contains a lot of compressed strings, which are delimited by ▀.
Main wire:
98@R Push the range 98...1.
≥î Increment each.
: Map each number n:
_Θ Call the second helper wire on n.
▀a▀ Push ", ".
_Ω Call the first helper wire on n.
ü Push a space.
▀...▀ Push "of beer.\nTake one down and pass it around, "
_≤îΘ Call the second helper wire on n-1.
..ÑÑ Push a period and two newlines.
; (end map)
1Θ Call the second helper wire on 1.
▀a▀ Push ", "
1Ω Call the first helper wire on 1.
▀...▀ Push " of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."
J Join the entire stack together. Implicitly output.
First helper wire:
D Duplicate TOS.
≤ Decrement.
y Get sign (0 or 1).
.sa· Repeat 's' that many times.
▀╖+╫Ä▀ Push " bottle"
a Swap top two elements.
Second helper wire:
Θ Call the first helper wire.
▀Ö$k·}Qy╦▀ Push " of beer on the wall"
PHP, 269 263 260 bytes
function f($p){return" bottle".($p-1?"s":"");}function b($b){$o=" of beer";$w=" on the wall";while($b){$n=f($b);echo"<p>$b$n$o$w, $b$n$o.<br>";echo--$b?"Take one down and pass it around, $b":"Go to the store and buy some more, 99";$n=f($b);echo"$n$o$w.</p>";}}
Readable version:
function f($p) {
return " bottle" . ($p-1 ? "s" : "");
}
function b($b) {
$o = " of beer";
$w = " on the wall";
while ($b) {
$n = f($b);
echo "<p>$b$n$o$w, $b$n$o.<br>";
echo --$b ? "Take one down and pass it around, $b"
: "Go to the store and buy some more, 99";
$n = f($b);
echo "$n$o$w.</p>";
}
}
Call b(99) and away you go!
Almost certainly could use some more optimization.
Windows Batch, 279 bytes
some optimization later
@echo off
set A=99
set B= bottle
set C=s of beer
set D= on the wall
:l
echo %A%%B%%C%%D%, %A%%B%%C%.
set/a A-=1
if %A%==1 set C=%C:~1%
if %A%==0 (echo Go to the store and buy some more, 99%B%s%C%%D%.
exit)else (echo Take one down and pass it around, %A%%B%%C%%D%.
echo.)
goto l
(my first post here, code actually from 2016)
C(GCC), 389 bytes
char*c="%1d %3$s of %4$s on the %5$s, %1d %3$s of %4$s.\n\0Take one down and pass it around, %2d %3$s of %4$s on the %5$s.\n\0Go to the store and buy some more, %1d %3$s of %4$s on the %5$s.\n";main(){int k=99;while(k!=0){printf(&c[0],k,k,k==1?"bottle":"bottles","beer","wall");if(1){printf(&c[49],k,k,"bottles","beer","wall");k--;}else{k=99;printf(&c[114],k,k,"bottles","beer","wall");}}}
Used some things I never thought I'd use. I actually don't know if it is supposed to loop after the end.
Ungolfed version:
char* c = "%1d %3$s of %4$s on the %5$s, %1d %3$s of %4$s.\n\0Take one down and pass it around, %2d %3$s of %4$s on the %5$s.\n\0Go to the store and buy some more, %1d %3$s of %4$s on the %5$s.\n";
main() {
int k = 99;
while (1) {
printf(&c[0], k, k, k == 1 ? "bottle" : "bottles", "beer", "wall");
if (k != 1) {
printf(&c[49], k, k, "bottles", "beer", "wall");
k--;
} else {
k=99;
printf(&c[114], k, k, "bottles", "beer", "wall");
}
}
}
This can be still golfed more.
Japt, 157 127 bytes
1oL w £A=X+` Þ¤{X-1?'s:P} Þ8`;B=A+` e Ø!` +".
{B}, {A}.
{´X?`Take e ܵ d ps ÂÐ`:`Go e ÐJe d ¿y Ñ Ú`}, "ìéHn
Markdown hates unprintables (unlike the shoco string compression library), so here's a hexdump:
00000000: 316f 4c20 7720 a341 3d58 2b60 20de ada4 7b58 1oL w £A=X+` Þ.¤{X
00000012: 2d31 3f27 733a 507d 208f 20de 3860 203d 412b -1?'s:P} . Þ8` =A+
00000024: 6020 8d20 9065 20d8 2160 3b42 2b22 2e0a 0a7b ` . .e Ø!`;B+"...{
00000036: 427d 2c20 7b41 7d2e 0a7b b458 3f60 5461 6b65 B}, {A}..{´X?`Take
00000048: 208d 6520 dcb5 2084 6420 7086 7320 8a20 c2d0 .e ܵ .d p.s . ÂÐ
0000005A: 9860 3a60 476f 2091 2090 6520 d04a 6520 8464 .`:`Go . .e ÐJe .d
0000006C: 20bf 7920 d120 20da 9060 7d2c 2022 c3ac e948 ¿y Ñ Ú.`}, "ìéH
0000007E: 6e n
This could probably be made shorter by saving the repeated sections to variables. Absolutely correct, past me. Japt is now the shortest language without a built-in!
SOGL 0.8.2, 123 bytes
³0=?"¡θ9‘}"⁵εα⁸‘⁴1≠? s+}+→@MHM{@⁽t⁾"¹u?«◄/⅞┐⌡u¹E³‘oo"ā)≡⁰≤τ¹‘o"5|░H׀│P¬2h⁶─#‘⁴0=?M"Zø‼;3σΠg℮╥╝ņΟXž∆‘}⁽OH@o"Θ┘θΖγ┘ψψ╚⅛╔⁷‘oøO
First of all, the function:
this function is ran with a number on the stack - the bottle count and pushes "x/no more bottle(s)"
³0=?"¡θ9‘}"⁵εα⁸‘⁴1≠? s+}+→@ full; example here is 0
→@ replace "@" in the further code with the code below [0]
³ triplicates the number [0, 0, 0]
0=? } if equal to 0 stack -> [0, 0, 1]
"¡θ9‘ push "no more" (this can leave garbage) [0, 0, "no more"]
"⁵εα⁸‘ push " bottle" [0, 0, "no more", " bottle"]
⁴ duplicate the 2nd from top of the stack (number or "no more") [0, 0, "no more", " bottle", "no more"]
1≠? } if not equal to 1 then [0, 0, "no more", " bottle"]
s+ append "s" [0, 0, "no more", " bottles"]
+ add together [0, 0, "no more bottles"]
And the rest of the code:
MHM{@⁽t⁾"¹u?«◄/⅞┐⌡u¹E³‘oo"ā)≡⁰≤τ¹‘o"5|░H׀│P¬2h⁶─#‘⁴0=?M"Zø‼;3σΠg℮╥╝ņΟXž∆‘}⁽OH@o"Θ┘θΖγ┘ψψ╚⅛╔⁷‘oøO
MH push 100-1 = 99 (bottle count)
M{ repeat 100 times
@ the function defined previously
⁽t⁾ output with the 1st letter uppercase (doesn't pop, newline)
"¹u?«◄/⅞┐⌡u¹E³‘o append " of beer on the wall, "
o append the previous functions result
"ā)≡⁰≤τ¹‘o append " of beer."
"5|░H׀│P¬2h⁶─#‘ push "take one down and pass it around, "
⁴0=? } if the original bottle count = 0
M push 100 (new bottle count)
"Zø‼;3σΠg℮╥╝ņΟXž∆‘ push "go to the store and buy some more, "
⁽O output with the 1st letter uppercase (hardcoding would've been longer)
H decrease the bottle count
@o run that function and output its result
"Θ┘θΖγ┘ψψ╚⅛╔⁷‘o append " of beer on the wall."
øO output an empty line
could probably be golfed 1-3 bytes removing repetition like " of beer on the wall, " and " of beer on the wall."
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.
C Preprocessor, 753 bytes
#ifndef T
#define N
#define T 9
#define G(A,B) I(A,B)
#define I(A,B) A##B
#define X Take one down and pass it around,
#define Y G(bottle,s) of beer
#define Z Y on the wall
#define E(x) G(T,x) Z, G(T,x) Y.
#define F(x) X G(T,x) Z.
#endif
E(9)
F(8)
N
E(8)
F(7)
N
E(7)
F(6)
N
E(6)
F(5)
N
E(5)
F(4)
N
E(4)
F(3)
N
E(3)
F(2)
N
E(2)
#if T+0
F(1)
N
E(1)
F(0)
N
E(0)
#if T<2
#undef T
#define T
#elif T<3
#undef T
#define T 1
#elif T<4
#undef T
#define T 2
#elif T<5
#undef T
#define T 3
#elif T<6
#undef T
#define T 4
#elif T<7
#undef T
#define T 5
#elif T<8
#undef T
#define T 6
#elif T<9
#undef T
#define T 7
#else
#undef T
#define T 8
#endif
F(9)
N
#include __FILE__
#else
#define s
X 1 Z.
N
1 Z, 1 Y.
#undef s
Go to the store and buy some more, 99 Z.
#endif
It is my privilege to submit this C preprocessor solution to this catalog. Note that this is a pure C Preprocessor solution (or, as I prefer to call it, a C Preprocessor solution). To my knowledge this is the first such solution to be posted to a catalog (there are a few claimed "C preprocessor" solutions around, but they're really things like C programs using the C preprocessor to generate strings).
5 bytes could be saved if I exploited the file name (e.g. changing #include __FILE__ to #include "f").
If anyone can help golf this further let me know.
F#, 210 201 263 241 bytes
let B n=sprintf"%d bottle%s of beer"n (if n>1 then"s"else"")
for n=99 downto 1 do printfn"%s on the wall, %s.\n%s on the wall.\n"(B n)(B n)(if n>1 then"Take one down and pass it around, "+B(n-1)else"Go to the store and buy some more, "+B 99)
Missed the "Go to the store and buy some more" part ..
S.I.L.O.S, 360 bytes
a=97
def q print z bottle v beer L Line g wall x IntNoLine h the c around
qL 99 zs of v on h g, 99 zs of v.
lbls
q Take one down and pass it c,
a+1
qx a
qL zs of v on h g.
qx a
q zs of v on h g,
qx a
qL zs of v.
a-2
if a s
qL Take one down and pass it c, 1 z of v on h g.
qL 1 z of v on h g, 1 z of v.
q Go to h store and buy some more, 99 zs of v on h g.
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");
}
}
}
dc, 269 237 bytes
299si[lid1-dsi3/li3>vdn[ bottle]P1<n]sm[[s]P]sn[ of beer]so[ on the wall]sp[, ]sq46sr10ss[[Take one down and pass it around]Pq]st[d4<t[Go to the store and buy some more]P]su[99+]sv[lmxloPlpPlqPlmxloPlrPlsPluxlqPlmxloPlpPlrPlsdPP3<z]dszx
Shaved off about 30 bytes by replacing two counters w/ 1 299/3 counter; couple of unnecessary variable loads replaced w/ stack duplications; code point 46 instead of [.].
R, 138 225 bytes
a='bottles of beer on the';for(i in 99:1)cat("",i,a,"wall,",i,"bottles of beer.\n","Take one down and pass it around,",i-1,a,"wall.\n\n")
a='bottles of beer on the'
for(i in 99:2)
cat("",i,a,"wall,",i,"bottles of beer.\n","Take one down and pass it around,",i-1,a,"wall.\n\n")
cat(1,a,"wall,","1 bottle of beer.\nGo to the store and buy some more,",99,a,"wall.")
EDIT-- missed the change in the last verse.
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.
Maple, 233 bytes
Added (unnecessary) newlines for code readability:
seq(printf("%d %s of beer on the wall,\n%d %s of beer.\nTake one down, pass it around,\n%d %s of beer on the wall.\n\n",
i,`if`(i<>1,"bottles","bottle"),
i,`if`(i<>1,"bottles","bottle"),
i-1,`if`(i-1<>1,"bottles","bottle")),
i=99..1,-1);
Common Lisp (Lispworks), 431 bytes
(defun f()(do((i 99(- i 1)))((= i 2))(format t"~S bottles of beer on the wall, ~S bottles of beer.~%Take one down and pass it around, ~S bottles of beer on the wall.~%~%" i i(- i 1)))(format t"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.~%"))
Ungolfed:
(defun 99-Bottles-of-Beer ()
(do ((i 99 (- i 1))) ((= i 2))
(format t "~S bottles of beer on the wall, ~S bottles of beer.~%Take one down and pass it around, ~S bottles of beer on the wall.~%~%" i i (- i 1)))
(format t "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.~%"))
Ruby, 237 (thanks primo!) 227 bytes
99.downto(2){|i|puts "#{i}#{$B=" bottles of beer"}#{$W=" on the wall"}, #{i}#$B,\nTake one down and pass it around, #{i-1}#{i<3?$C=$B.tr('s','') :$B}#$W.\n\n"};puts "1#$C#$W, 1#$C,\nGo to the store and buy some more, 99#$B#$W."
Mostly ungolfed: (old, outdated)
$B="bottles of beer"
$C="bottle of beer"
$W="on the wall"
99.downto(2) { |i|
puts "#{i} #$B #$W, #{i} #$B,\nTake one down and pass it around, #{i-1} #{i==2 ? $C : $B} #$W.\n\n"}
puts "1 #$C #$W, 1 #$C,\nGo to the store and buy some more, 99 #$B #$W."
Try it online:
C#, 267 bytes
()=>{for(int x=99;x>0;){string e="",s="s",t=x>1?s:e,b=" bottle",o=" of beer",w=$"{o} on the wall",a=x+b+t;System.Console.Write($"{a+w}, {a+o}.\n"+(x-->1?$"Take one down and pass it around, {x+b+(x>1?s:e)+w}.\n\n":$"Go to the store and buy some more, 99{b}s{w}."));}};
C# lambda where the output is stdout and without output. You can try it on .NetFiddle.
Code :
()=>{
for (int x=99;x>0;) {
string e="",s="s",t=x>1?s:e,b=" bottle",o=" of beer",w=$"{o} on the wall",a=x+b+t;
System.Console.Write($"{a+w}, {a+o}.\n"+(x-->1
?$"Take one down and pass it around, {x+b+(x>1?s:e)+w}.\n\n"
:$"Go to the store and buy some more, 99{b}s{w}."));
}};
Kudos to Igby Largeman for his solution. I think it is better than mine (shorter if it had use a lambda too).
MIT Scratch 2.0, 184 bytes
Notes: Since this language is graphical, I counted each block/element used, each byte of the strings, and variable invocations as a byte.
Try it online: https://scratch.mit.edu/projects/115797194/#player
Notes: This program does not automatically clear the list after it's run, you have to go to the editor and run the following block:
I have conveniently added it into the project, however it is not part of the program and does not count towards the byte count.
Python 3, 234 bytes
i=99
s='s'
b='%s bottle%s of beer'
o=' on the wall'
y=b%(i,s)
while i:print(y+o+', '+y+'.');i-=1;s=('',s)[i>1];y=b%(i,s);print(('Take one down, pass it around, '+y+o+'.\n','Go to the store and buy some more, 99'+b%(s,'s')+o+'.')[i<1])
with newlines for some more readability
i=99;
s='s';
b='%s bottle%s of beer';
o=' on the wall';
y=b%(i,s)
while i:
print(y+o+', '+y+'.');
i-=1;
s=('',s)[i>1];
y=b%(i,s);
print(('Take one down, pass it around, '+y+o+'.\n','Go to the store and buy some more, 99'+b%(s,'s')+o+'.')[i<1])
makes use of a quirk of booleans to evaluate to zero or one; this allows them to be used as index in two value tuples or lists, and are shorter than the 'proper' equivalent. These pseudo ternaries are used to keep all the loop code on one line.
Retina, 159 bytes
Byte count assumes ISO 8859-1 encoding. The leading linefeed is significant.
99$*1 bottles of beer
1
1$'W, 1$'.¶Take one down and pass it around, $'W.¶¶
1+
$.&
G-3`
W
on the wall
T`s``\b1 .+
.+ \B
Go to the store and buy some more, 99
I can't be believe I (or anyone else) have ever done this in Retina...
Explanation
99$* bottles of beer
We start by replacing the empty input with 99 1s followed by bottles of beer.
1
1$'W, 1$'.¶Take one down and pass it around, $'W.¶¶
Now we replace each of those 1s with the substitution pattern on the second line. Here $' stands for the string after each match, and we use W as a placeholder for later. Note that the occurrences of $' on the first line are "incremented" by prepending a 1. We've got most of the work done already, except that the numbers are in unary instead of decimal, and we've got Ws instead of on the walls and the last verse is off.
1+
$.&
This does the unary-to-decimal conversion by matching each run of 1s and replacing it with its length.
G-3`
This is a "grep" stage. The regex is empty, so it always matches, but the -3 limit means that only lines up to the third from the end are kept, so the last two are discarded. This gets rid of the two extraneous linefeeds at the end.
W
on the wall
Now we substitute our W placeholder. At this point, we've got everything in place except that the last verse is still wrong.
T`s``\b1 .+
This fixes the pluralisation by removing all ss from the match of the regex at the end, which matches anything after a 1 (on the same line).
Note that the last line doesn't have 0 since the unary representation of it is an empty string it wasn't matched by the conversion stage. Instead there will be two spaces in a row.
.+ \B
Go to the store and buy some more, 99
This is the only case where there is no word boundary after a space, so we detect the line like this and replace it with the correct lyrics.
XSLT 1.0 (no EXSLT), 845 bytes
<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"><output method="text"/><template match="/"><call-template name="b"/></template><template name="b"><param name="n" select="99"/><if test="$n>0"><variable name="o"><if test="$n>1"><value-of select="$n -1"/></if><if test="$n=1">99</if></variable><variable name="p"><if test="$n>1">s</if></variable><variable name="q"><if test="$n!=2">s</if></variable><variable name="z"><if test="$n=1">Go to the store and buy some more</if><if test="$n>1">Take one down and pass it around</if></variable><variable name="w" select="concat($n,' bottle',$p,' of beer')"/><value-of select="concat($w,' on the wall, ',$w,'. ',$z,', ',number($o),' bottle',$q,' of beer on the wall. ')"/><call-template name="b"><with-param name="n" select="$n -1"/></call-template></if></template></transform>
With a bit less golf in it:
<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
<output method="text"/>
<template match="/">
<call-template name="b"/>
</template>
<template name="b">
<param name="n" select="99"/>
<if test="$n>0">
<variable name="o">
<if test="$n>1">
<value-of select="$n -1"/>
</if>
<if test="$n=1">99</if>
</variable>
<variable name="p">
<if test="$n>1">s</if>
</variable>
<variable name="q">
<if test="$n!=2">s</if>
</variable>
<variable name="z">
<if test="$n=1">Go to the store and buy some more</if>
<if test="$n>1">Take one down and pass it around</if>
</variable>
<variable name="w" select="concat($n,' bottle',$p,' of beer')"/>
<value-of select="concat($w,' on the wall, ',$w,'. ',$z,', ',number($o),' bottle',$q,' of beer on the wall. ')"/>
<call-template name="b">
<with-param name="n" select="$n -1"/>
</call-template>
</if>
</template>
</transform>
Notes
Text compression
The use of variables as abbreviations isn't as extensive as in other languages; for example, note the repetition of ' bottle' as a constant. In XSLT, the binding of an XPath expression or some arbitrary text to a variable name requires at least 29 characters of overhead, excluding the name and content itself:
<variable name="name" select="expr"/>
<variable name="name">text</variable>
Say, for example, that one would like to replace all instances of the XPath string literal ' bottle' (8 chars) with $b (2 chars). Each substitution saves 6 characters. However, given the definition <variable name="b"> bottle</variable> (38 chars), there is no net profit unless there are 7 or more such sequences to replace.
The use of the <variable/> element is limited to evaluating conditions. The version of XPath used with XSLT 1.0 does not have its own if/else constructs, but XSLT itself does, and <variable/> is necessary to retrieve the results in a useful form.
$n -1
The expression $n -1 appears twice. The space after the $n is required since - is a valid name character in XPath.
Inequalities
Wherever practical, any instance where != originally appeared was changed to use > instead. If the program counted down to 0 instead of resetting to 99 after 1, the plural check for $n would be incorrect at 0.
Tail recursion
The template named b recurses, counting the variable n down by one each time. XSLT provides looping constructs, but they are for traversing structures found in the input document. A task like this one would be substantially easier if we had an input doc containing the countdown (<doc><value>99</value><value>98</value><value>97</value>...</doc>) but at that point we're cheating (or we at least have to count the input doc in our byte count).
Run
Run using xsltproc:
xsltproc 99.xsl 99.xsl
Yes, 99.xsl is passed twice: Once as the XSLT document and then as the XML document to be transformed. An input document must be present because an XSLT processor generally requires one to begin running. (XSLT is designed to define a transformation from an input document to an output document; running a transform solely with command-line parameters as I've done here is atypical.) For this program, any well-formed XML document will suffice as input, and, XSLT being an application of XML, any well-formed XSLT transform is by definition a well-formed XML document.
///, 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 ///).
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 tobottles of beer^decompresses tobottles of beer on the wall!decompresses to^,, where^is the one above.$decompresses to>.\n, where>is the first rule and\nis a newline.@decompresses to$followed byTake 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.
PHP, 172 bytes
<?for(;100>$a=1+$a." bottle$o[21] of beer";$o="
Take one down and pass it around, $b.
".$g="$b, $a.$o")$b="$a on the wall";echo"$g
Go to the store and buy some more, $b.";
The most significant trick is $o[21]. On the first iteration, $o will be undefined, resulting in an empty string. On each iteration after, it refers to the first s of pass.
Scratch, 252 bytes

(scoring used)
Resets, repeats for 98 cycles, then a modified last block for the last line.
If you allow "1 bottles" in the list, this can be golfed down to 133 bytes.

Python 3, 210 bytes
b=" of beer"
s="bottles"+b
t=s[:6]+b
q="on the wall."
p=print
x=99
while x>1:p(x,s,q,x,s+".\nTake one down and pass it around,",x-1,(s,t)[x>1],q);x-=1
p(1,t,q,1,t+".\nGo to the store and buy some more,",99,s,q)
Try it here: https://ideone.com/iX4byJ
T-SQL, 436 323 bytes
WITH _ AS(SELECT 99B UNION ALL SELECT B-1 FROM _ WHERE B>2)SELECT REPLACE(REPLACE(REPLACE(A,'#',' of beer'),'@',' on the wall'),'!',' bottle')FROM(SELECT REPLACE(REPLACE('^!s#@, ^!s#.
Take one down and pass it around, %!s#@.','^',B),'%',B-1)A FROM _ UNION ALL SELECT'1!#@, 1!#.
Go to the store and buy some more, 99!s#@.')A
Grond, 226 chars
p=".";b=" bottle";B=b+'s';o=" of beer";w=" on the wall";i=100;w(--i>0){T=i<3?b:B;h=B+o+w;u=i<2?b+o:B+o;k=i+u;a(k+w+', '+k+p);a(i>1?"Take one down and pass it around, "+(i-1)+T+o+p:"Go to the store and buy some more, 99"+h+p);}
Grond is a new programming languege that I am currently developing. It aims to make Javascript shorter to write, while still being "Javascript". I'm pretty mad that I didn't beat any of the Javascript answers, but the languege is still beta and I am still a n00b. Oh and buy the way, I might not call it grond in the future, but it is a reference to the hammer of the underworld.
Actually, Grond can beat some of the JS answers @ 179 chars, as follows:
f(x=99,z=(a=' on the wall')=>`${x||99} bottle${1-x?'s':''} of beer`+a;x;)a(z()+', '+z`.
`+(--x?'Take one down and pass it around, ':'Go to the store and buy some more, ')+z()+'.')
But that is copying Adam Dally's answer, so I won't do it (unless you all want me to).
Anyway, here is the compiler:
String.prototype.reverse = function() {
return this.split("").reverse().join("");
}
var source = "p='.';b=' bottle';B=b+'s';o=' of beer';w=' on the wall';i=100;w(--i>0){T=i<3?b:B;h=B+o+w;u=i<2?b+o:B+o;k=i+u;a(k+w+', '+k+p);a(i>1?'Take one down and pass it around, '+(i-1)+T+o+p:'Go to the store and buy some more, 99'+h+p);}";
var wc = source; // wc stands for working copy
var lastWC;
while (true) {
lastWC = wc;
wc = wc.reverse();
wc = wc.replace(/\(a(?!\w)/, "(trela"); //alert ,a
wc = wc.replace(/\(f(?!\w)/, "(rof"); // for, f
wc = wc.replace(/\(w(?!\w)/, "(elihw"); //while,w
wc = wc.replace(/\(p(?!\w)/, "(tpmorp"); //prompt,p
wc = wc.replace(/\(vr\./, "(esrever."); //reverse, rv
wc = wc.replace(/\(tm\./, "(chtam."); // match, mt
wc = wc.replace(/\(nj\./, "(nioj."); //join, .jn
wc = wc.replace(/\(pr\./, "(ecalper."); //replace, .rp
wc = wc.replace(/\(ls\./, "(.ecils"); //slice, sl
wc = wc.replace(/\(lt\./, "(esaCrewoLot."); //toLowerCase, tl
wc = wc.replace(/\(ut\./, "(esaCreppUot."); //toUpperCase, tu
wc = wc.reverse();
wc = wc.replace(/\.l(?!\w)/, ".length"); // .lenght, .l
if (lastWC === wc)
break;
}
// quine builtin commented out because it messes things up
wc = " String.prototype.reverse=function(){return this.split('').reverse().join('');} \n var h = ['hello, world', 'Hello, World', 'Hello, World!', 'hello, world!', 'hello world', 'hello world!', 'Hello World', 'Hello World!', 'Hello, world.', 'Hello, World.' ,'hello world.' , 'Hello World.']; /* var q ='" + source + "';*/ " + wc;
eval(wc);
PHP, 226 221 bytes
Minified
<? $w=" on the wall";for($i=99;$i>=0;$i--){if($j&&$i)echo"Take one down and pass it around, $i$j$w.
";$j=" bottle".($i!=1?'s':'')." of beer";if($i)echo"$i$j$w, $i$j.
";}echo"Go to the store and buy some more, 99$j$w.";
Expanded
<?
$w=" on the wall";
for($i=99;$i>=0;$i--){
if($j && $i)
echo "Take one down and pass it around, $i$j$w.
";
$j=" bottle".($i!=1?'s':'')." of beer";
if($i)
echo "$i$j$w, $i$j.
";
}
echo "Go to the store and buy some more, 99$j$w.";
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
Jolf, 193 bytes
Try it here! I can still probably golf a byte or two...
Ώ³γhHΖp{" Ξ\x000k"γΆΆγ"% of beer on the wall, "ζγ"% of ΞΓi
"ζ?wγΆ"Ξ ψone Ξp«Ξit ΞpDΖ"wγ"% of ΞΙon the Ξy
"p{" Ξ\x000k"wγ"Go to the Ξrand buy ΞzδΞB\x00Ε 99 Ξώof ΞΙon the Ξy"1Μw_z~1dΏH
Here's the main concept: this defines a function Ώ that returns the bottle line of an input, calls it 1 for a default, and:
Μw_z~1dΏH
Μ maps
w_z~1 0..99 reversed
dΏH with that function
Ugh that hurt my head.
R, 267 bytes
Not the shortest solution out there for R but it uses a different approach (namely dataframes).
d=data.frame(i=1:99,j=c(99,1:98));d$b=" bottles of beer";d$t="Take one down and pass it around";d[1,3:4]=c(" bottle of beer","Go to the store and buy some more");d$B=d$b[d$j];w=" on the wall";cat(rev(with(d,sprintf("\n%i%s%s, %i%s.\n%s, %i%s%s.",i,b,w,i,b,t,j,B,w))))
Indented, with newlines:
d = data.frame(i=1:99,j=c(99,1:98))
d$b = " bottles of beer"
d$t = "Take one down and pass it around"
d[1,3:4] = c(" bottle of beer","Go to the store and buy some more")
d$B = d$b[d$j]
w = " on the wall"
cat(rev(with(d,sprintf("\n%i%s%s, %i%s.\n%s, %i%s%s.",i,b,w,i,b,t,j,B,w))))
R, 269 bytes
R sometimes can process text without much pain. In this case can't, but the iteration system rocks:
cat(sprintf('\n%s bottles of beer on the wall, %s bottles of beer.Take one down and pass it around, %s bottles of beer on the wall.',99:2,99:2,98:1),'\n1 bottle of beer on the wall, 1 bottle of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.')
PARI/GP, 181 bytes
for(i=1,99,{G=Str("Take one down and pass it around, "b=Str(a=Str(i" bottl"e" of beer")" on the wall")".
"g=Str(b", "a".
"G));e=es);print(g"o to the store and buy some more, "b".")
Using the variable name G conveniently saves a byte. The closing brace doesn't seem to be required to end a multi-line context, strangely.
The shortest solution I know of previous to this is 32 bytes heavier.
C++, 335 bytes
Golfed:
#include <stdio.h>
int main(){for (int c = 99; c >= 2; c--){printf("%i bottles of beer on the wall, %i bottles of beer.\nTake one down and pass it around, %i bottles of beer on the wall.", c, c, c-1);}printf("1 bottle of beer on the wall, 1 bottle of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.");return 0;}
Ungolfed:
#include <stdio.h>
int main()
{
for (int c = 99; c >= 2; c--) {
printf("%i bottles of beer on the wall, %i bottles of beer.\nTake one down and pass it around, %i bottles of beer on the wall.", c, c, c-1);
}
printf("1 bottle of beer on the wall, 1 bottle of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.");
return 0;
}
05AB1E, 167 bytes
Dammit, 167 is waaayyy too long. But this gave me some new ideas to make this a bit shorter.
Code:
99L`[D?ð?“±¥“?D1Q"s "si\ð}?“€‚¬ž€‰€€íÒ, “??ð?“±¥“?D1Q"s "si\ð}?“€‚¬ž.“,Ž“Ÿ†€µ§€€ƒî倕³†, “ª?D?ð?“±¥“?D1Q"s "si\ð}?“€‚¬ž€‰€€íÒ.
“,]“‚œ€„€€›‰€ƒŽŠ€ä€£, 99Ïꀂ¬ž€‰€€íÒ.“ª,
Uses CP-1252 encoding.
Groovy, 213 bytes
Quite simple, probably much more golfing could be done.
b={" $it bottles of beer.\n"}
print ((99..1).collect{"$it bottle${it>1?'s':''} of beer on the wall,"+b(it)+(it>1?"Take one down and pass it around,"+b(it-1):"Go to the store and buy some more,"+b(99))}.join('\n'))
SELECT., 7313057 bytes
This is not a SELECT. program that prints the 99 bottles lyrics. It is a link to a pastebin of a python program that prints a SELECT. program that prints the 99 bottles lyrics. The latter program is over 7 megabytes long, and unsuitable for posting here.
The program that generated this program looks like this:
######GENERATION CODE######
init(185,49,1)
makenum(10)
square()
dec()
dec()
var("99")
loop("main",computei=True,savelist=["99"])
var("i")
go(1)
makeneg1()
multiply(-1)
go(1)
fetch("99")
add(-1)
var("num")
go(1)
makeone()
add(-1)
var("curnum")
go(1)
makenum(10)
go(-1)
intdiv()
go(-5)
var("mod")
go(5)
var("div")
ifnonpositive("tens")
els("tens",True)
digitprintXY(0,0)
endif("tens")
go(1)
fetch("mod")
var("mod")
digitprintXY(6,0)
go(1)
drawstringliteral("bottle",16,0)
go(1)
fetch("curnum")
go(1)
makeneg1()
add(-1)
var("onetest")
ifzero("plural")
go(1)
drawstringliteral("of beer on the wall,",51,0)
els("plural")
go(1)
drawstringliteral("s of beer on the wall,",46,0)
endif("plural")
go(1)
fetch("div")
ifnonpositive("tens")
els("tens",True)
digitprintXY(0,13)
endif("tens")
go(1)
fetch("mod")
digitprintXY(6,13)
go(1)
drawstringliteral("bottle",16,13)
go(1)
fetch("onetest")
ifzero("plural")
go(1)
drawstringliteral("of beer.",51,13)
els("plural")
go(1)
drawstringliteral("s of beer.",46,13)
endif("plural")
go(1)
drawstringliteral("Take one down and pass it around,",0,26)
go(1)
fetch("num")
ifzero("nomore")
go(1)
drawstringliteral("No more bottles ofbeer on the wall.",0,39)
els("nomore",True)
go(1)
makenum(10)
go(-1)
intdiv()
go(-5)
var("mod")
go(5)
ifnonpositive("tens")
els("tens",True)
digitprintXY(0,39)
endif("tens")
go(1)
fetch("mod")
digitprintXY(6,39)
go(1)
drawstringliteral("bottle",16,39)
go(1)
fetch("num")
go(1)
makeneg1()
add(-1)
ifzero("plural")
go(1)
drawstringliteral("of beer on the wall.",51,39)
els("plural")
go(1)
drawstringliteral("s of beer on the wall.",46,39)
endif("plural")
input()
clear()
endif("nomore")
go(1)
endloop("main",savelist=["99"])
go(1)
drawstringliteral("No more bottles of beer on the wall,",0,0)
go(1)
drawstringliteral("no morebottles of beer.",0,13)
go(1)
drawstringliteral("Go to thestore and buy some more,",0,26)
go(1)
drawstringliteral("99 bottles of beeron the wall.",0,39)
writetofile("99bottles.sel")
C, 256 bytes
Nice round number.
*a=" bottles of beer",*b=" on the wall",*c="Take one down and pass it around, ",d=100;main(){while(--d){printf("%d%s%s, %d%s, \n",d,a,b,d,a);d-1&&printf("%s%d%s%s. \n",c,d,a,b);}puts("Go to the store and buy some more, 99 bottles of beer on the wall.");}
With whitespace:
*a=" bottles of beer",
*b=" on the wall",
*c="Take one down and pass it around, ",
d=100;main(){
while(--d){
printf("%d%s%s, %d%s, \n",d,a,b,d,a);
d-1&&printf("%s%d%s%s. \n",c,d,a,b);
}
puts("Go to the store and buy some more, 99 bottles of beer on the wall.");
}
Fun fact: I accidentally posted this on stack exchange and then realised a few minutes later that it was on the wrong post. Ooops.
JavaScript ES6, 298 bytes
for(var a=[" bottles of beer","on the wall","take one down and pass it around","go to the store and buy some more",99];0<a[4];)a[0]=1===a[4]?a[0].replace("s",""):a[0],console.log(a[4]+a[0]+" "+a[1]+", "+a[4]+a[0]+". "+(1===a[4]?a[3]:a[2])+", "+(0===a[4]-1?"99"+a[0]+"s":a[4]+a[0])+" "+a[1]),a[4]--;
x86 MS-DOS .COM file, 176 bytes
Advantages:
- bitwise manipulation allows efficient encoding (However, in the end I settled on a relatively unpacked encoding which is pretty readable, just using the 8th bit of each byte to store spaces. I tried denser encodings that got the data to under 70 bytes, but the program size went up just as much.)
- .COM files are widely supported from MS-DOS 1 through the present (I'm running in dosemu, sticking with 8086 commands only)
Disadvantages:
- conditional jumps can get real obfuscated real quickly
- some simple tasks are hard; it takes ~20 bytes to print the number of bottles
Hex dump (pass this into xxd -r to regenerate the 176-byte file):
0100: be a8 01 bd 63 00 40 75 06 4d 74 f7 be a4 01 8a ....c.@u.Mt.....
0110: 0c 46 8a 1c 46 80 fb 89 75 18 89 e8 b7 0a f6 f7 .F..F...u.......
0120: b7 01 05 30 30 3c 30 92 b4 02 74 02 cd 21 88 f2 ...00<0...t..!..
0130: cd 21 38 2f 79 04 b2 20 cd 21 b2 7f 22 17 4d 75 .!8/y.. .!..".Mu
0140: 05 80 fb 8f 74 02 cd 21 45 43 e2 c9 81 fe ae 01 ....t..!EC......
0150: 76 b5 c3 54 61 6b 65 ef 6e 65 e4 6f 77 6e e1 6e v..Take.ne.own.n
0160: 64 f0 61 73 73 e9 74 e1 72 6f 75 6e 64 47 6f f4 d.ass.t.roundGo.
0170: 6f f4 68 65 f3 74 6f 72 65 e1 6e 64 e2 75 79 f3 o.he.tore.nd.uy.
0180: 6f 6d 65 ed 6f 72 65 2c 20 e2 6f 74 74 6c 65 73 ome.ore, .ottles
0190: ef 66 e2 65 65 72 ef 6e f4 68 65 f7 61 6c 6c 2e .f.eer.n.he.all.
01a0: 0d 0a 0d 0a 1a 53 1d 87 16 89 0f 87 03 9f 33 6d .....S........3m
Explanations:
Bytes 0100 through 0152 (83 bytes) are commands, unassembled using debug:
0100 BEA801 MOV SI,01A8 ; point to 3rd substring
0103 BD6300 MOV BP,0063 ; begin with 99 bottles
0106 40 INC AX ; only used to unset zero flag after last bottle taken
0107 7506 JNZ 010F ; {when referred from 0150...if finished 5th substring:
0109 4D DEC BP ; take down a bottle
010A 74F7 JZ 0103 ; took last bottle, reset 99 bottles (and proceed to 6th)
010C BEA401 MOV SI,01A4 ; or if not last bottle, point to 1st substring}
010F 8A0C MOV CL,[SI] ; load counter for substring
0111 46 INC SI
0112 8A1C MOV BL,[SI] ; load start pointer for substring
0114 46 INC SI
0115 80FB89 CMP BL,89 ; { {check location to print # of bottles,
0118 7518 JNZ 0132 ; if so...
011A 89E8 MOV AX,BP
011C B70A MOV BH,0A
011E F6F7 DIV BH ; divide by 10
0120 B701 MOV BH,01 ; (leave BH=1 for rest of program so [BX] points correctly)
0122 053030 ADD AX,3030 ; convert to ascii numerals
0125 3C30 CMP AL,30 ; {if tens digit > 0,
0127 92 XCHG AX,DX
0128 B402 MOV AH,02 ; (leave AH=2 for rest of program to print to stdout)
012A 7402 JZ 012E
012C CD21 INT 21 ; print tens digit}
012E 88F2 MOV DL,DH
0130 CD21 INT 21 ; print ones digit}
0132 382F CMP [BX],CH ; {check if character's 8th bit is set
0134 7904 JNS 013A ; if so...
0136 B220 MOV DL,20
0138 CD21 INT 21 ; print " "}
013A B27F MOV DL,7F
013C 2217 AND DL,[BX] ; load character without 8th bit
013E 4D DEC BP ; {temporarily check if --bottle count = 0
013F 7505 JNZ 0146
0141 80FB8F CMP BL,8F ; if so, check if at location of "s" to skip
0144 7402 JZ 0148
0146 CD21 INT 21 ; print (unless skipping "s")
0148 45 INC BP ; undo temporary check}
0149 43 INC BX
014A E2C9 LOOP 0115 ; proceed to next encoded character of substring}
014C 81FEAE01 CMP SI,01AE ; check if we just finished the 5th of the 6 substrings
0150 76B5 JBE 0107 ; if the 5th or less, triage further at line 0107
0152 C3 RET ; end after finishing 6th substring
Bytes 0153 through 01a3 (81 bytes) are the pretty readable encoded text
Bytes 01a4 through 01af (12 bytes) are (length,start) pairs pointing to substrings
"Take...around"
", #bottles...wall.CRLFCRLF"
"#bottles...wall"
", #bottles...beer"
".CRLF"
"Go...wall.CRLF"
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 and9s long.The binary is 745,792
1s and0s long.I used the Python 2 code below to generate the code. Input
0for binary and1for 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)))
Microsoft Small Basic, 313 bytes
g=" of beer"
a=" bottles"+g
b=" on the wall"
c="Take one down and pass it around, "
d="."
e="1 bottle"+g
f=", "
i=99
n=Text.GetCharacter(010)
While i>1
TextWindow.WriteLine(i+a+b+f+i+a+d+n+c+(i-1)+a+b+d+n)
i=i-1
EndWhile
TextWindow.WriteLine(e+b+f+e+d+n+"Go to the store and buy some more, 99"+a+b+d)
Lua, 267 263 bytes
q=" bottle"r=q.."s"s=" of beer"t=" on the wall"u="\nTake one down and pass it around, "v="\nGo to the store and buy some more, "w=r..s for n=99,1,-1 do io.write(n,w,t,", ",n,w,".",n>1 and u..n-1 ..(n>2 and w or q..s)or v.."99"..r..s,t,".\n\n")w=(n>2 and w or q..s)end
I didn't see lua under the answers yet, only golflua, correct me if im wrong.
Explatation:
q=" bottle" -- assigning parts of the text to variables in as
r=q.."s" -- long pices as it's practical
s=" of beer"
t=" on the wall"
u="\nTake one down and pass it around, "
v="\nGo to the store and buy some more, "
w=r..s -- bracause r..s/r,s repeats 4 times its shorter to assign it to w
for n=99,1,-1 do
io.write(n,w,t,", ",n,w,".", --putting it together
n>1 and u..n-1 -- "take one down..." or "go to the store..."
..(n>2 and w or q..s) -- "bottels or bottle..."
or v.."99"..r..s,t,".\n\n" -- "n-1" or "99"
)
w=(n>2 and w or q..s) -- this condition repeats 2 times, it changes "bottles" to "bottle"
end
Tryout link: Execute Lua Online.
Type lua in the comandline and then dofile("99bob.lua").
Testrun:
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.
I tried to write the program golfed from the start, that probably wasn't a good idia.
Edit: thanks to manatwork for r=q.."s".
Loader, 515 bytes
Run from a module named m.
~I:set I,B =99
set P =B
decr P
~P:printf "1 bottle of beer on the wall, 1 bottle of beer."
~P:printf "You go to the store and you buy some more, 99 bottles of beer on the wall."
~P:exit
P:printf "%n bottles of beer on the wall, %n bottles of beer." B,B
~P:printf "1 bottle of beer on the wall!, 1 bottle of beer."
decr P
decr B
P:printf "You take one down and you pass it around, %n bottles of beer on the wall." B
~P:printf "You take one down and you pass it around, 1 bottle of beer on the wall."
printf ""
load m
Emacs Lisp, 290 Bytes
(defun b (n) (format "%d bottle%s of beer" n (if (eq n 1) "" "s")))
(defun bw (n) (concat (b n) " on the wall"))
(defun l (n) (concat (bw n) ", " (b n) ".\nTake one down, pass it around, " (bw (- n 1)) ".\n" (if (> n 1) (l (- n 1)) "Go to the store and buy some more.\n")))
(message (l 99))
Java, 290 bytes
class C{public static void main(String[]p){String b=" bottle",s=b+"s",o=" of beer",w=o+" on the wall",c=", ",n=".\n",u;for(int i=99;i>0;){u=i>2?s:b;System.out.println(i+s+w+c+i--+s+o+n+(i>0?"Take one down and pass it around, "+i+u:"Go to the store and buy some more, 99"+b+"s")+w+n);s=u;}}}
Ungolfed:
class C {
public static void main(String[] p) {
String b = " bottle", s = b + "s", o = " of beer", w = o + " on the wall", c = ", ", n = ".\n", u;
for (int i = 99; i > 0;) {
u = i > 2 ? s : b;
System.out.println(i + s
+ w
+ c
+ i--
+ s
+ o
+ n
+ (i > 0 ? "Take one down and pass it around, " + i + u
: "Go to the store and buy some more, 99" + b + "s") + w + n);
s = u;
}
}
}
Ceylon 1.2, 359
alias S=>String;alias I=>Integer;shared void run(){value[b,o,w,t,d]=[" bottle"," of beer"," on the wall","Take one down and pass it around, ",".\n"];S l="1"+b+o;S h(I n)=>"``n``"+b+"s"+o;S f(I n)=>h(n)+w+", "+h(n);S c(I n)=>t+h(n)+w+d+"\n"+f(n);print(d.join{f(99),*(98..2).map(c)}+d+t+l+d+"\n"+l+w+", "+l+d+"Go to the store and buy some more, "+h(99)+w+".");}
Some golfing tricks: Shorter aliases for String and Integer, and the tuple-decomposition-declaration which saves us some S and = (that was only introduced in Ceylon 1.2).
The rest is straightforward extraction of common parts to variables/functions.
Formatted:
// 99 bottles of beer
//
// Question: http://codegolf.stackexchange.com/q/64198/2338
// My answer: http://codegolf.stackexchange.com/a/64522/2338
alias S => String;
alias I => Integer;
shared void run() {
value [b, o, w, t, d] = [
" bottle",
" of beer",
" on the wall",
"Take one down and pass it around, ",
".\n"
];
S l = "1" + b + o;
S h(I n) => "``n``" + b + "s" + o;
S f(I n) => h(n) + w + ", " + h(n);
S c(I n) => t + h(n) + w + d + "\n" + f(n);
print(d.join { f(99), *(98..2).map(c) }
+ d + t + l + d + "\n" + l + w + ", " + l + d +
"Go to the store and buy some more, " + h(99) + w + ".");
}
Milky Way 1.0.2, 255 bytes
99&{~:?{1b_" bottle"_" bottles"}" of beer"+;:>;+:" on the wall, "+;".\n"++"Take one down and pass it around, "<1-:>++<?{1b_" bottle"_" bottles"};>+" of beer on the wall."+<?{_""_"\rGo to the store and buy some more, 99 bottles of beer on the wall."};>+!<}
It's really too long to explain in detail here, but check the docs for info.
Usage
./mw <path-to-code>
Perl 5, 222 bytes
Ungolfed:
$b=" bottles of beer";
$B=" bottle of beer";
$w=" on the wall";
for($i=99;$i>1;$i--){
print"$i$b$w, $i$b.\nTake one down and pass it around, ".($i-1)."$b$w.\n\n";
}
print"1$B$w, 1$B.\nGo to the store and buy some more, 99$b$w.";
Golfed:
$b=" bottles of beer";$B=" bottle of beer";$w=" on the wall";for($i=99;$i>1;$i--){print"$i$b$w, $i$b.\nTake one down and pass it around, ".($i-1)."$b$w.\n\n";}print"1$B$w, 1$B.\nGo to the store and buy some more, 99$b$w.";
I'm convinced there has to be a way to improve this approach with some sort of whitespace collapsing. Is there a special variable in Perl that is printed after alphanumeric characters, that you can set? I wonder...
Either way, I feel pretty content for a 5-minute golf.
CJam, 257 229 bytes
229 Bytes
99:A;"bottles of beer":B;{A" "B" on the wall, "A" "B"."NA(:A;"Take one down and pass it around, "A" "B" on the wall."NN}98*"1 bottle of beer on the wall, 1 bottle of beer."N"Go to the store and buy some more, 99 "B" on the wall."
257 Bytes
99:A;{A" bottles of beer on the wall, "A" bottles of beer."NA(:A;"Take one down and pass it around, "A" bottles of beer on the wall."NN}98*"1 bottle of beer on the wall, 1 bottle of beer."N"Go to the store and buy some more, 99 bottles of beer on the wall."
Mouse-2002, 275 bytes
Mouse hates strings. Actually, it doesn't even know anything about them, because the closest thing to a string you can put on the stack is a char. Anything between " " is printed, but you can't put strings in variables or manipulate them.1
99I:(I.0>^I.1=["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.!"|I.!" bottles of beer on the wall, "I.!" bottles of beer.!Take one down and pass it around, "I.1-!" bottles of beer on the wall.!!"]I.1-I:)$
That's shamefully long, for a stack-based language.
Explained:
99I: ~ i = 99
( ~ while(true)
I.0>^ ~ if i > 0 == false then break
I.1=[ ~ if i == 1 print this string
"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.!"
| I.!" bottles of beer on the wall, "I.!" bottles of beer.!Take one down and pass it around, "I.1-!" bottles of beer on the wall.!!" ~ else print this interpolated one
] ~ end if
I.1-I: ~ i = i-1
) ~ end while
$ ~ end prog
1That's why I'm planning to reimplement and update Mouse into newmouse!
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}
Oracle SQL, 393 326 320 306 324 bytes*l
Grew a few bytes to fix error noted by C.L.
select b||decode(l,0,c||d||', '||b||c||'. Go to the store and buy some more, 99 bottle','s'||c||d||', '||b||'s'||c||'. Take one down and pass it around, '||l||' bottle')||decode(l,1,'','s')||c||d||'.'
from(select level-1 l,level||' bottle' b,' of beer' c,' on the wall' d from dual connect by level <= 99)order by l desc;
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+'.')
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
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.
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
JavaScript ES5, 233 bytes
for(i=100,a=' bottle',b=' of beer',c=' on the wall';i>1;i--,alert(i+a+(i!=1?'s':'')+b+c+', '+i+a+(i!=1?'s':'')+b+'.'+(i>1?'Take one down and pass it around, '+(i-1):'Go to the store and buy some more, '+99)+a+(i==2?'':'s')+b+c+'.'));
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.
Vitsy, 0 Bytes
Seriously ain't got nothin' on me. (@Mego I'm so sorry. ;))
Try it online! (Just hit "Run")
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".
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";
}
CJam, 252 227 220 bytes
I can guarantee that this is not the shortest solution. Oh well, I tried.
" bottles of beer on the wall.
":D;99,W%:){_"%d bottles of"D28/0=+", %d bottles of beer."+e%W$e%{'s=1$1=&!},\_(:M{"
Take one down, pass it around, %d"\(e%D{'s=M1=&!},}{"
Go to the store and buy some more, 99"D+}?+1-+o}%
Try it out here. Any golfing tips are greatly appreciated.
Thanks to @Dennis for helping me shorten this!
Bubblegum, 474 bytes
00000000: e02de601d25d001ce07cc46f3a26b205c864c02a139d .-...]...|.o:&...d.*..
00000016: 166e795c307826823b392997b956fbc8b6c350ce248e .ny\0x&.;9)..V....P.$.
0000002c: 1071a7cb6e24ab42a254bbe0a8be43ad25d657dd967a .q..n$.B.T....C.%.W..z
00000042: 258b807b20b4ceba00a9918ae3e3eed4e23bb85856ef %..{ ............;.XV.
00000058: e1267f9a415e5ca27213fcf0adf089c56057787ec1fe .&..A^\.r.......`Wx~..
0000006e: 3620203a8af3c18b3cc36c43f04307eed88938663114 6 :....<.lC.C....8f1.
00000084: 4de9bb22d200d500dfaae3b7c6eda8da60c7ad0e3496 M.."............`...4.
0000009a: d5df645de0ba1a202c6094f9103fc864a170d4c001d3 ..d]... ,`...?.d.p....
000000b0: d862374c5d4918d17d84d30c1234bb7861a1b3545599 .b7L]I..}....4.xa..TU.
000000c6: 4daaab8a872177daef7ee025d5ec84c4ba56f0840d8f M....!w..~.%.....V....
000000dc: c49023d4506350828b8bfa6287c90b9cdac45b11283f ..#.PcP....b......[.(?
000000f2: 9dd5926301a37d1817468471f0e5f5c38999e5cd9d9b ...c..}..F.q..........
00000108: 3429c1755fd57139c9c66126f899217c3b09395dd205 4).u_.q9..a&..!|;.9]..
0000011e: 6a0332c73adbe8015922be7407dd21f813b1d90a389b j.2.:...Y".t..!.....8.
00000134: d0bc6aac22cc65bdb8dbdd03d863654f06538750c04b ..j.".e......ceO.S.P.K
0000014a: e437a1e0f19dbb0d5d598f3122a31f400245f39c156a .7......]Y.1"..@.E...j
00000160: 06082aaa40ce6f0c822f585b6d1053a8144cf5552831 ..*.@.o../X[m.S..L.U(1
00000176: 3885ffc5d3aa540bc74534253b94406174b4b4e0337d 8.....T..E4%;.@at...3}
0000018c: 607f28b1614429ee7238ecba8f8682446140cbc507f9 `.(.aD).r8.....Da@....
000001a2: 54e2cbed802442331930e963822df3527911b0f42895 T....$B3.0.c.-.Ry...(.
000001b8: e0a1a806829eca36fe4bb623dbc6b87c45c26843f770 .......6.K.#...|E.hC.p
000001ce: ede402da278009d9a19a0000 ....'.......
The above hexdump can be reversed with xxd -r -c 22.
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"))
Scala, 313 298 271 268 bytes
I think I may have reached the limit on this without resorting to string compression algorithms.
object m extends App{val(f,c)=((x:Int)=>s"$x bottle${if(x>1)"s" else ""} of beer"," on the wall");99 to 1 by -1 map(a=>println(s"${f(a)}$c, ${f(a)}.\n${if(a>1)"Take one down and pass it around" else "Go to the store and buy some more"}, ${f(if(a>1)a-1 else 99)}$c."))}
(Semi-)readable version:
object m extends App{
val(f,c)=((x:Int)=>s"$x bottle${if(x>1)"s" else ""} of beer"," on the wall");
99 to 1 by -1 map(a=>println(s"${f(a)}$c, ${f(a)}.\n${if(a>1)"Take one down and pass it around" else "Go to the store and buy some more"}, ${f(if(a>1)a-1 else 99)}$c."))
}
Python3, 258 237 232 bytes
Being strict about spaces and newlines.
i=98;b="bottle";w="on the wall";o="of beer"
while i+1:y=bool(i);s="s"*y;print(i+1,b+s,o,w+",",i+1,b+s,o+".\n"+("Go to the store and buy some more,","Take one down and pass it around,")[y],i or 99,b+"s"*bool(i-1),o,w+"."+"\n"*y);i-=1
Readable (sort of):
i=98
b="bottle"
w="on the wall"
o="of beer"
while i + 1:
y = bool(i)
s = "s" * y
print(
i + 1,
b + s,
o,
w + ",",
i + 1,
b + s,
o + ".\n"
+ (
"Go to the store and buy some more,",
"Take one down and pass it around,"
)[y],
i or 99,
b + "s" * bool(i - 1),
o,
w + "."
+ "\n" * y
)
i -= 1
Default unspecified arguments for print(): sep=' ' and end='\n'.
O 1.2, 169 bytes
{.o" bottle"o.1>{'so}{}?" of beer"o}:b{" on the wall"o}:w9B*..{bw", "o b "."p(.{"Take one down and pass it around, "}{;"Go to the store and buy some more, "}?obw'.p""p}d
(Works with the old Java interpreter. No idea whether is matter of version of interpreter, but the online O Language IDE throws error.)
Sample run:
bash-4.3$ java xyz.jadonfowler.o.O 99.o | tail
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.
golflua, 206 bytes
\b(t)~i.." bottle"..(i>1&"s"|"").." of beer"..t$\c(t)~b" on the wall"..t$i=99@i>0w(c", "..b".")?i<2 ~~$i=i-1w("Take one down and pass it around, "..c".\n")$i=99w("Go to the store and buy some more, "..c".")
Sample run:
bash-4.3$ golflua 99.golflua | tail
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 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.
Dart, 218 bytes
int i=99;b(i)=>'$i bottle${i<2?'':'s'} of beer';w(i)=>b(i)+' on the wall';main(){while(i>0){print(w(i)+', ${b(i)}.\n${--i>0?'Take one down and pass it around, '+w(i):'Go to the store and buy some more, '+w(99)}.\n');}}
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
Perl 5, 159
@c=(@b=(++$n,bottle.'s'x@-,of,beer),on,the,wall),s//Take one down and pass it around, @c.
@c, @b.
/,until/99\D+/;say$'."Go to the store and buy some more, $&"
Based on the solution from eyepopslikeamosquito found here.
Requires the free -M5.010 switch to use "say".
R, 233 Bytes
f=function(n){b="bottles of beer";p=paste0;w="on the wall";cat(n,b,p(w,","),n,p(b,"."),"\n");if(n>1){cat("Take one down and pass it around,",n-1,b,p(w,".\n"));f(n-1)}else cat("Go to the store and buy some more, 99",b,p(w,"."))}
f(99)
longer (non-golf) version
Same functions, same syntax; added only breaks and brackets
f <- function(n) {
b <- "bottles of beer"
p <- paste0
w <- "on the wall"
cat(n, b, p(w, ","), n, p(b, "."), "\n")
if (n > 1) {
cat("Take one down and pass it around,", n - 1, b, p(w, ".\n"))
f(n - 1)
} else {
cat("Go to the store and buy some more, 99", b, p(w, "."))
}
}
f(99)
PHP, 256 bytes
<?php $b=' bottle';$o=' of beer';$t=' on the wall';$i=99;while($i>=1){$s=$i!=1?'s':'';echo "$i$b$s$o$t, $i$b$s$o.\n".($s?"Take one down and pass it around":"Go to the store and buy some more").", ".($i==1&&--$i>-3?99:--$i)."$b".($i!=1?'s':'')."$o$t.\n\n";}
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";
}
BitShift, 342372 bytes
Pre-note: This is probably sub-optimal...
BitShift is a language created by me, which only supports bit-shifting operations on a single value. It is not great for code-golf :')
Since the program is too long to include in this post, it is provided here.
It can be tested here. Be aware that it will take a while to finish.
I am hoping for this challenge to provide a better solution to this problem.
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)}
C#, 274 bytes
Direct copy from my answer on another question (it was popularity, but I just treated it as golf). Never did get around to golfing it further.
class
P{static
void Main(){
for(int i=99;i>0;
)System.Console.Write
(i+"{1}{2}{3}, {0}{1}{2} of beer.\n"+(i>1?
"Take one down and pass it around, {4}{1}{5}{3}.\n\n":
"Go to the store and buy some more, 99{1}s{3}."
),i--," bottle",i>0?"s":"",
" of beer on the wall"
,i,i>1?"s":""
);}}
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.
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.
))
Bash, 235 bytes
e=of\ beer
d="Take one down and pass it around"
c=" on the wall"
b=" bottles "
f=$b
for n in {99..2};{
((n==2))&&f=${f/s}
echo "$n$b$e$c, $n$b$e.
$d, $[n-1]$f$e$c.
"
}
echo "1$f$e$c, 1$f$e.
Go to the store and buy some more, 99$b$e$c."
Readable
e="of beer"
d="Take one down and pass it around"
c=" on the wall"
b=" bottles "
f=$b
for n in {99..2}; {
((n==2)) && f=" bottle "
echo -e "$n$b$e$c, $n$b$e.\n$d, $[n-1]$f$e$c.\n"
}
echo -e "1$f$e$c, 1$f$e.\nGo to the store and buy some more, 99$b$e$c."
As @mego mentions in the comments below, you can easily try it and see the result here: http://ideone.com/6088aJ
Update: I have used @manatwork hints. The readable version is a little bit different from the short version for better understanding.
Go, 287
package main
import."fmt"
func main(){p,s,n:=Printf,"%[1]d bottle%[2]s of beer",`.
`
o:=s+" on the wall"
a,b,c,i,k:=o+`, `+s+n,`Take one down and pass it around, `+o+n+`
`,`Go to the store and buy some more, `+o+n,99,"s"
for 1<i{p(a,i,k)
if i--;i<2{k=""}
p(b,i,k)}
p(a,i,k)
p(c,99,"s")}
There is probably room for further optimization
R, 297 bytes
b='bottles of beer'
w='on the wall'
p=paste
g=gsub
s='$'
x='.'
d=p(g(s,',',b),w)
j=99
i=j:1
l=g(s,x,p(i,d,i,b))
l[j]=g('s','',l[j])
m=p('Take one down and pass it around,',i,d)
o=p(l,m,sep="\n")
o[j]=g('\n.*',g(s,x,p('\nGo to the store and buy some more,',j,d)),o[j])
write(o,"")
PHP, 248 bytes (with pluralisation)
$b=99;$x=function($n){return"$n bottle".($n!=1?'s':'')." of beer";};$y=" on the wall";do{echo"{$x($b)}$y, {$x($b)}.\n";echo--$b?"Take one down and pass it around":"Go to the store and buy some more";$b||$b=99;echo", {$x($b)}$y.\n\n";}while($b<99);
readable:
<?php
$b=99;
$x=function($n){return"$n bottle".($n!=1?'s':'')." of beer";};
$y=" on the wall";
do{
echo"{$x($b)}$y, {$x($b)}.\n";
echo--$b?"Take one down and pass it around":"Go to the store and buy some more";
$b||$b=99;
echo", {$x($b)}$y.\n\n";
}while($b<99);
NOTE: previoius version was 197 bytes but didnt correctly show singular "bottle". see history if interested
PHP, 267 bytes
<?php $i=99;$t="Take one down and pass it around, ";$b=" bottles of beer";$o=" on the wall";echo"99$b$o, 99$b.\n";while(--$i>1)echo"$t$i$b$o.\n\n$i$b$o, $i$b.\n";$B=str_replace('s','',$b);echo"$t$i$B$o.\n\n$i$B$o, $i$B.\nGo to the store and buy some more, 99$b$o.";
Readable version, with comments:
<?php
$i=99;
$t="Take one down and pass it around, ";
$b=" bottles of beer";
$o=" on the wall";
// first one
echo"99$b$o, 99$b.\n";
// decrement from 98 to 2
while(--$i>1) echo"$t$i$b$o.\n\n$i$b$o, $i$b.\n";
// ^^ "Take one down and pass it around, $i bottles of beer on the wall.\n\n ^^
// $i bottles of beer on the wall, $i bottles of beer.\n"
// last one
$B=str_replace('s','',$b); // change "bottles" to "bottle"
echo"$t$i$B$o.\n\n$i$B$o, $i$B.\nGo to the store and buy some more, 99$b$o.";
Perl 5, 243 bytes
A shorter Perl 5 solution is posted as a community wiki solution here.
$}=" bottle";$s='s';$o=" of beer";$w=" on the wall";$i=99;while($i>1){say"$i$}$s$o$w, $i$}$s$o.";$s=''if--$i<2;say"Take one down and pass it around, $i$}$s$o$w.\n"}say"$i$}$s$o$w, $i$}$s$o.";say"Go to the store and buy some more, 99$}s$s$o$w."
Using the free -M5.010 switch for "say" instead of "print".
Cheers.
C, 230 bytes
My first codegolfing and learning C!
#define B "%d bottle%s of beer"
main(i,a){for(i=99;i;i--)a=i<2,printf(B" on the wall, "B".\n%s, "B" on the wall.\n\n",i,"s"+a,i,"s"+a,a?"Go to the store and buy some more":"Take one down and pass it around",a?99:i-1,"s"+(i==2));}
Compiled with gcc -std=c99 -w beer.c
Readable (sort of):
#define B "%d bottle%s of beer"
main(i,a){
for (i = 99; i; i--) {
a=i<2;
printf(B" on the wall, "B".\n%s, "B" on the wall.\n\n",
i, "s"+a, i, "s"+a,
a? "Go to the store and buy some more":"Take one down and pass it around",
a? 99 : i-1, "s"+(i==2));
}
}
My first entry (293 bytes):
#define BOT "bottle%s of beer"
main(){
char *e[]={"Go to the store an buy some more","Take one down and pass it around"};char *z[]={"","s"};
for(int i=99;i>0;i--){int j=i>1?i-1:99;char* s=z[i>1];
printf("%d "BOT" on the wall, %d "BOT". %s, %d "BOT" on the wall.\n",i,s,i,s,e[i>1],j,z[j>1]);}}
Haha, I love all these nasty tricks i applied that i never though could even exist in C!
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!
DStack, 265 bytes
@0
# bottles of beer on the wall, # bottles of beer.
Take one down and pass it around, $ bottles of beer on the wall.
@
@1
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.
@
01SSd99CCcscDtTasd9ttkt
Swift 2.0, 208 239 bytes
After fixing the bottles thing, it's a little longer:
let a:Int->String={"\($0) bottle\($0==1 ?"":"s") of beer"},b=" on the wall"
(1...99).reverse().forEach{print("\(a($0)+b), \(a($0)).\n\(($0==1 ?"Go to the store and buy some more, "+a(99):"Take one down and pass it around, "+a($0))+b).\n")}
Here's the old, shorter version too without handling the s:
let a=" bottles of beer",b=" on the wall",c="Go to the store and buy some more, 99"
(1...99).reverse().forEach{print("\($0)\(a+b), \($0)\(a).\n\(($0==1 ?c:"Take one down and pass it around, \($0)")+a+b).\n")}
C, 249 bytes
#define A(N)printf(N<2?"%s%d bottle%s of beer%s":N^2?N^4?", ":n?"Take one down and pass it around, ":"Go to the store and buy some more, ":".\n\n","",n?n:99,n>9|!n?"s":"",N ?" on the wall":".\n"),
n=99;main(){while(n)A(1)A(3)A(0)--n,A(4)A(1)A(2)0;}
Ungolfed:
#define A(N) \
printf( \
/* format string */ \
N<2 \
? "%s%d bottle%s of beer%s" \
: N^2 \
? N^4 \
? ", " \
: n ? "Take one down and pass it around, ":"Go to the store and buy some more, " \
: ".\n\n", \
/* arguments (ignored if N >= 2) */ \
"", \
(n ? n : 99), \
(n > 9 | !n) ? "s":"", \
N ?" on the wall":".\n"),
n=99;
main() {
while(n) A(1) A(3) A(0) --n, A(4) A(1) A(2) 0;
}
C, 244 242 240 bytes
k;main(i){char*B=" bottle",*G="s of beer",*W=" on the wall";for(i=99;i;k=--i<2)printf("\n%d%s%s%s, %d%s%s.\n%s, %d%s%s%s.\n",i,B,G+k,W,i,B,G+k,k?"Go to the store and buy some more":"Take one down and pass it around",k?99:i-1,B,G+!(i-2),W);}
Compiled as:
gccw -std=c99 -o party party.c
Multiline:
k;
main(i)
{
char *B=" bottle",
*G="s of beer",
*W=" on the wall";
for(i = 99; i; k = --i < 2)
printf("\n%d%s%s%s, %d%s%s.\n%s, %d%s%s%s.\n",
i,B,G+k,W,
i,B,G+k,
k ? "Go to the store and buy some more":
"Take one down and pass it around",
k ? 99 : i-1, B, G + !(i-2), W
);
}
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.
Mouse, 244 bytes
99N:(N.0>^N.!" bottle"N.1>["s"]" of beer on the wall, "N.!" bottle"N.1>["s"]" of beer.!"N.1>["Take one down and pass it around"]N.1=["Go to the store and buy some more"]", "N.1-N:N.0=[99]N.0>[N.]!" bottle"N.1=0=["s"]" of beer on the wall.!!")$
Mouse has very limited capabilities in general, though this is particularly apparent in its handling of strings. The stack can contain only integers; any quoted strings encountered are printed to STDOUT immediately. Further, there is no else construct, so each condition must be stated explicitly.
Ungolfed:
99 N: ~ Initialize a counter
( N. 0 > ^ ~ While N > 0...
N. ! " bottle" N. 1 > ["s"] ~ Print N, conditionally pluralize
" of beer on the wall, "
N. ! " bottle" N. 1 > ["s"]
" of beer.!"
N. 1 > ["Take one down and pass it around"]
N. 1 = ["Go to the store and buy some more"]
", "
N. 1 - N: ~ Decrement the counter
N. 0 = [99] N. 0 > [N.] !
" bottle" N. 1 = 0 = ["s"]
" of beer on the wall.!!" ~ ! inside a string is \n
)$
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.
Groovy, 281 bytes
def s=" of beer on the wall";def b=" bottles";for(int i=99;;)(i>1)?{println i+b+s+", "+i+b+" of beer.\nTake one down and pass it around, "+--i+(i==1?" bottle":b)+s+".\n"}():{println "1 bottle"+s+", 1 bottle of beer.\nGo to the store and buy some more, 99"+b+s+".";System.exit(0)}()
dis is best idea
C++, 289 bytes
Golfed:
#include <cstdio>
void main(){char*s=" bottles of beer",*t=" on the wall",*u=" bottle of beer";for(int i=99;i>1;--i)printf("%i%s%s, %i%s.\nTake one down and pass it around, %i%s%s.\n\n",i,s,t,i,s,i-1,i<3?u:s,t);printf("1%s%s, 1%s.\nGo to the store and buy some more, 99%s%s.",u,t,u,s,t);}
Works in Microsoft Visual Studio. Though some compilers may require that void main be changed to int main and a return value provided. This increases the size to 297:
#include <cstdio>
int main(){char*s=" bottles of beer",*t=" on the wall",*u=" bottle of beer";for(int i=99;i>1;--i)printf("%i%s%s, %i%s.\nTake one down and pass it around, %i%s%s.\n\n",i,s,t,i,s,i-1,i<3?u:s,t);printf("1%s%s, 1%s.\nGo to the store and buy some more, 99%s%s.",u,t,u,s,t);return 0;}
Ungolfed:
#include <cstdio>
void main()
{
char* s = " bottles of beer";
char* t = " on the wall";
char* u = " bottle of beer";
for(int i = 99; i > 1; --i)
{
printf("%i%s%s, %i%s.\nTake one down and pass it around, %i%s%s.\n\n", i, s, t, i, s, (i - 1), (i < 3 ? u : s), t);
}
printf("1%s%s, 1%s.\nGo to the store and buy some more, 99%s%s.", u, t, u, s, t);
}
Link to demo.
Pyth, 157 156 150 149 148 145 bytes
L+b%" bottle%s of beer on the wall."<\stbVK99s[PyKJ", "<13yK\.)++?=tK"Take one down and pass it around""Go to the store and buy some more"Jy|K99k
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.
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>
>
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.
Matlab, 254
b=@(n)[' bottle','r'+eye(n~=1),' of beer'];o=' on the wall';f=@fprintf;
for k=99:-1:1;f(['%d',b(k),o,', %d',b(k),'.\n'],k,k);
if k>1;f('Take one down and pass it around, %d',k-1);
else;f('Go to the store and buy some more, 99');
end;f([b(k-1),o,'.\n\n']);end
PHP, 274 269 bytes
<?php $a=' bottles';for($i=99;$i>0;$i--){$d="Take one down and pass it around, ".($i-1)."$a<br><br>";if($i==1){$a=rtrim($a,'s');$d="Go to the store and buy some more, 99 bottles";}$d.=" of beer on the wall.";$s.="$i$a of beer on the wall, $i$a of beer.<br>".$d;}echo$s;

