Voting

Category

real language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language Java

(object-oriented version)

Date:04/20/05
Author:Anonymous
URL:n/a
Comments:33
Info:n/a
Score: (3.03 in 323 votes)
/* the main method instantiates drinkers and directs them to
   a newly-instantiated wall of beer.
*/
public class Sing99Bob {
  public static void main(String[] args) {
    ((NeedToFindBeer)(new Drinkers())).pointAtBeer(new WallOfBeer());
  }
}

  interface NeedToFindBeer { void pointAtBeer(WallOfBeer wob); }

  /* an instance of Drinkers, after being pointed at a wall containing
     beer, will periodically take one down.  The singing is driven by
     the taking of the beer.
  */
  class Drinkers extends Thread implements NeedToFindBeer {
    static final int drinkRate = 2;
    WallOfBeer ourBeer;
    public void run() {
      while (ourBeer.takeOne()>0) {
       try { Thread.sleep(drinkRate*1000); } catch (InterruptedException ignore) {}
      }
    }
    public void pointAtBeer(WallOfBeer wob) {
      ourBeer = wob;
      this.start();
    }
  }

  interface Countable { int howMany(); }

  /* an instance of a WallOfBeer will maintain a count of the
     beer bottles.  The wall has an associated Narrator who
     reports each time the number of bottles is changed.
  */
  class WallOfBeer implements Countable {
    static final int full = 99;
    int count = 0;
    WallWatcher ww;
    {
      ww = new Narrator();
      putSome(full);
    }
    void putSome(int some) {
      count += some;
      if (ww!=null) ww.wallEvent(this);
    }
    int takeOne() {
      count--;
      if (ww!=null) ww.wallEvent(this);
      return count;
    }
    public int howMany() { return count; }
  }

  interface WallWatcher { void wallEvent(Countable wob); }

  /* an instance of Narrator sings the verse each time it is
     notified that something has happened to the wall.  This
     narrator attempts to be grammatical, and uses words for
     the bottle count (singers sing words not numerals). The
     singing is paced, not merely lump-dumped to sysout.
  */
  class Narrator implements WallWatcher {
    static final int singspeed = 500;
    public void wallEvent(Countable wob) {
      int b = wob.howMany();
      try {
        System.out.print(bob(b, true)+onwall+", ");
        Thread.sleep(singspeed);
        System.out.print(bob(b, false)+".\n");
        Thread.sleep(singspeed);
        System.out.print((b>0)?takedown:gostore);
        Thread.sleep(singspeed);
        System.out.print((b>0)?bob(b-1, false):bob(WallOfBeer.full, false));
        System.out.print(onwall+".\n");
      } catch (InterruptedException ignore) {}
    }
    static final String bob(int i, boolean c) {
      String word = word(i);
      if (c) word = (word.substring(0, 1).toUpperCase())+word.substring(1);
      return word+" bottle"+((i==1)?"":"s")+" of beer";
    }
    static final String word(int i) {
      if (i==0) return "no more";
      if (i<20) return units[i];
      return tens[i/10]+((units[i%10]=="")?"":"-"+units[i%10]);
    }
    static final String
      onwall = " on the wall",
      takedown = "Take one down and pass it around, ",
      gostore = "Go to the store, get some more, ";
    static final String[]
      tens = {"", "", "twenty", "thirty", "forty",
              "fifty", "sixty", "seventy", "eighty", "ninety"},
      units = {"", "one", "two", "three", "four", "five", "six", "seven",
               "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
               "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
  }

Download Source | Write Comment

Alternative Versions

VersionAuthorDateCommentsRate
exception orientedJarek Ratajski09/08/055
Singing with Java Speech APIKevin Seifert05/04/062
bytecode-version with loaderTilo Dickopp05/23/0610
standard versionSean Russell04/20/0512
Java 5.0 object-oriented versionKvols11/19/053

Comments

>>  kronchev said on 11/29/05 01:00:42

kronchev You know, this is why people think Java is bloated

>>  Glen said on 02/20/06 04:01:44

Glen Exception in thread "main" java.lang.NoClassDefFoundError: ninetyninebottles/java

>>  Vsevolod said on 09/08/07 22:13:10

Vsevolod Excellent!!!

Short and simple, true Java-way :)

>>  Ryan said on 01/06/08 23:56:19

Ryan Yeah but, the other examples just iterate, this one shows how to actually emulate a wall of beer, a singer, and a drinker. The song output is just a symptom of the actions taken by the three players. I think it's very robust, allows for the singing the song at a realistic rate (like a group of humans would), and extensible enough that a multitude of other results could be generated independently and simultaneously with the song.

That being said, yes, you can write for loops in Java as well. But this program shows off how easy it is to use threads and the power of programming to interface in Java. For example, want a different language? Or even a different song? Implement the WallWatcher interface for each version of the song you want, and this program can handle all of them, either singing separately, or even at the same time (if this were a bar with multiple singers in a video game or something).

Nice job, very well-designed and robust!

>>  aalku said on 02/13/08 08:05:36

aalku /** MessageFormat version */
public class Bottles {
static final String p1 = "{0, choice, -1#99|0#no more|0<{0}} bottle{0, choice, 0#s|1#|1<s} of beer";
static final String p2 = " on the wall";
static final String p3 = "{0, choice, -1#Go to the store and buy some more|0#Take one down and pass it around}, ";

static final String patterns[] = { p1 + p2 + ", " + p1 + ".", p3 + p1 + p2 + "." } ;

public static void main(String[] args ) {
for (int i = 99; i >= 0; i-- ) {
System.out.println(java.text.MessageFormat.format(patterns[0], i ).replaceFirst("^n", "N" ) ) ;
System.out.println(java.text.MessageFormat.format(patterns[1], i - 1 ) );
}
}
}

>>  Don said on 04/26/08 00:24:05

Don Wow. And people say that Cobol is verbose!!

>>  Dave Salt said on 04/26/08 01:54:23

Dave Salt After seeing this, it's no wonder I like REXX so much.

>>  Regac said on 05/07/08 20:33:48

Regac LOL

If can be written in five lines.
It is interesting though how people can find the most complicated solutions to the simplest of problems.

Cheers

>>  Lee said on 06/26/08 07:53:59

Lee public class NinetyNinebeers {
public static void main(String[] args) {
beer();
}
public static void beer() {
for (int i=99; i>=3; i--){
System.out.println(i+" bottles of beer on the wall, " +i+ " bottles of beer.";);
System.out.println("Take one down and pass it around, "+(i-1)+ " bottles of beer on the wall.";);
System.out.println();
}
System.out.println("2 bottles of beer on the wall, 2 bottles of beer.";);
System.out.println("Take one down and pass it around, 1 bottle of beer on the wall.";);
System.out.println();
System.out.println("1 bottle of beer on the wall, 1 bottle of beer.";);
System.out.println("Take one down and pass it around, no more bottles of beer on the wall.";);
System.out.println();
System.out.println("No more bottles of beer on the wall, no more bottles of beer. ";);
System.out.println("Go to the store and buy some more, 99 bottles of beer on the wall.";);

}
}


how about this?

>>  jjj said on 07/12/08 03:05:22

jjj Interesting thing to note: this program is exactly 99 lines long... =)
Very nice...

>>  Some guy said on 08/20/08 22:37:17

Some guy Yeah Ryan, surely everyone shares your definition of robustness...

>>  almosthuman said on 08/21/08 06:28:57

almosthuman Glen, next time save it as Sing99Bob.java and then try recompiling...java has this silly requirement where the name of the file must be the same as the class containing main...did you download the sdk just for this?

>>  Frankstallone said on 09/20/08 13:34:57

Frankstallone Talk about going out of your way to make the world's largest 99 bottle program. I assume this was done on purpose to make it 99 lines long which is sort of cool.

>>  Alex said on 10/01/08 04:14:12

Alex Why use any of that?

public class Beer {

public static void main(String[] args) {
for (int i = 90; i > 0; i--)
if (i != 1)
System.out.println(i+ " bottles of beer on the wall, " +i+ " bottles of beer. Take one down, pass it around, " +(i-1)+ " bottles of beer on the wall.";);
System.out.println("1 bottle of beer on the wall, 1 bottle of beer. Take it down, pass it around, no bottles of beer on the wall.
}

}

>>  Jim said on 12/18/08 18:00:40

Jim Alex: because anyone can write 99BoB with a decrementing for-loop. (look (1 line ASP.NET in C#, truncated)
for (i=99; i>0; i--) context.Response.Write(String.Format("{0} bottles of beer on the wall, {0} bottles of beer;<br />Take one down, pass it around there'll be {1} bottles of beer on the wall<br />", i, i-1));

It takes a real (ly mad?) programmer to come up with something like this!

Personally, I love this - it's a proper enterprisey solution! Plus, the components are reusable and replacable. It's.... astonishing! I think it's possibly the most verbose and complex solution to a simple problem I've ever liked!

Props!

>>  spangle said on 12/22/08 02:26:14

spangle If you don't understand the beauty of this program, you need to LEARN MORE, not just post your "improvements", in whatever language they may be.

This is starting to sound just like people who post in youtube...

>>  Michael said on 04/27/09 22:07:56

Michael Quite a long example, but does help to demonstrate Javas capabilities, could be made a LOT shorter

>>  Mário Pereira said on 05/06/09 23:04:13

Mário Pereira EXCELLENT!!! This people, is what OOP really means. This is the perfect example of OOP application. And demonstrates the whole power of Java.

Of course it could be made a lot simplier, but people should really get used to application like this one, for the sack of programming future.

Congractullations

>>  Sam Harrison said on 05/13/09 19:36:31

Sam Harrison public class Bottles
{
public static void main(String[] args)
{
int bottles = 99;
while(bottles > 0)
{
System.out.print(bottles + " bottles of beer on the wall, "
+ bottles + " bottles of beer,\nTake one down and pass"
+ " it around, ";);
bottles --;
System.out.println(bottles + " bottles of beer on the wall.";);
System.out.println();
}
}
}

//another way it can be done

>>  John, the Fisherman said on 05/28/09 21:46:12

John, the Fisherman There's a lot of people complaining about the size of the code.

It is *not* about size.

I love this version, looks like a sketch for a movie. 8|D>

>>  Roman said on 05/31/09 19:31:18

Roman Ah, nice one. Here is a shorter version for the satirically challenged:

public class NinetyNineBottlesOfBeerOnAWall {

public static void main(String[] a) {
String e = "", b = " bottle", s = "s", o = " of beer", w = " on the wall", c = ", ",
p = ".", l = "\n", t = "Take one down and pass it around, ", n = "n", m = "o more",
g = "Go to the store and buy some more, ", mbs = m+b+s, opl=o+p+l, owpl=o+w+p+l, owc=o+w+c;
int nn = 99;
for(int i=nn;i>0;i--) {
System.out.print( i + b + (i >1 ? s : e) + owc + i + b + (i >1 ? s : e) + opl +
t + (i-1 > 0 ? i-1 + b + (i-1 >1 ? s : e) : n + mbs) + owpl + l);
}
System.out.print(n.toUpperCase() + mbs + owc + n + mbs + opl + g + nn + b + s + owpl);
}
}

>>  pauldawg said on 09/29/09 04:44:25

pauldawg Someone said that the code could be shorter. But I must admit all I wanted to do was make it longer. Can we define attributes for the beer, such as bottle-color, country of origin, type of beer (ale/lager/pilsner/etc), and brewery of origin? It would also be good to separate the wall into shelves so we know how many bottles fit on each shelf. Also, as we pass the bottle around, how many people are sharing the bottle? What are their respective tolerances for alcohol? How does it affect the pace of the song when someone passes out?

>>  chris said on 12/03/09 05:29:06

chris This is the best use of Java I've seen...You should write the Agile Java books

>>  Me said on 12/04/09 17:07:31

Me Why do you cast the (new Drinkers()) to (NeedToFindBeer) in the beginning?

>>  Roger Heathcote said on 12/24/09 03:47:24

Roger Heathcote Hmm, I would suggest people looking for an open enterprise grade INOCOAGS (integer number of containers on a given surface) solution also consider the following "Advanced, extensible beer/wall framework" written in Python...

http://99-bottles-of-beer.net/language-python-1154.html

>>  LK said on 12/27/09 14:48:19

LK Go read http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
It made me think of that article.

>>  carlos said on 01/10/10 01:45:54

carlos He has not only printed the lyrics. He has create a bar with a wall of beer, a drinker who take beers and a narrator who is singing the song.
That is OOP. And OOP is the same in C++, java, .net, etc.

Nice code.

>>  SHOVAN said on 01/26/10 14:18:44

SHOVAN awesome..u could have make it simpler any time...but this one suggests,how much u love java,object oriented concepts...

>>  Draugo said on 03/10/10 13:26:19

Draugo Simply brilliant. A true OOP programmers solution.

>>  Jabber said on 07/21/10 19:12:28

Jabber Justifying using OOP for this purpose is like a hobo trying to get a drop 99 times after iteration zero!

>>  Bob shaw said on 08/22/10 02:38:23

Bob shaw This isn't multithreaded at all. It creates a new thread, ok, but when it does that the main thread dies.
Also you shouldn't compare strings with '==', unless if you're interested in whether they happen to be in the same place in memory.
You should also consider using the keyword 'private'.

This is really bad java (besides being very verbose ;)

>>  Andrew Main said on 09/14/10 11:06:51

Andrew Main 1. I have to admire the solution design for its richness.
2. But it is so typical of the problem that programmers start with a simple task and over-engineer and over-feature the solution.
3. Compare the BASIC version - go past the BASIC and click on version "2", to see a solution that solves the problem and stops there.
4. While I admire this, a student learning to program would be deterred by it.
5. If we want people to yearn to program, let's stay simple.

>>  barrym said on 09/15/10 04:33:09

barrym @Andrew: I also admire simplicity, and I believe that the simplest solution to a
problem is nearly always the best. However, you cite as an example a program that
is admirably simple but stops before the problem of printing the end of the song is
solved. I love to browse the different versions and different languages to see the
beauty of diversity. I don't frown at the complex solutions because they have their
own appeal, but I do frown on "solutions" that are incorrect or incomplete, because
they serve as poor examples to beginners, hobbyists, and professionals alike.

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: