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:11
Info:n/a
Score: (3.50 in 34 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/051
Java 5.0 object-oriented versionKvols11/19/052
Singing with Java Speech APIKevin Seifert05/04/061
standard versionSean Russell04/20/0510

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?

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: