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:24
Info:n/a
Score: (3.57 in 90 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
bytecode-version with loaderTilo Dickopp05/23/069
exception orientedJarek Ratajski09/08/053
Singing with Java Speech APIKevin Seifert05/04/061
Java 5.0 object-oriented versionKvols11/19/053
standard versionSean Russell04/20/0511

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

>>  Anonymous said on 07/13/06 18:14:19

Anonymous You've convinced me to never learn Java

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

Vsevolod Excellent!!!

Short and simple, true Java-way :)

>>  Anonymous said on 10/15/07 03:32:24

Anonymous Dude... the idea is to do as much as you can with the least amount of code.

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

>>  Anonymous said on 03/13/09 07:57:37

Anonymous I can't believe you didn't use a BeerFactory to make a WallOfBeer.

Good work.

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

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: