Take one down and pass it around...

Happy St. Patrick’s Day: 99 Bottles of Beer in 1500 Programmiersprachen

Dominik Mohilo

© Shutterstock.com / Svetlana_Okeana

JAXenter wünscht einen fröhlichen St. Patrick’s Day! Aus gegebenem Anlass möchten wir unseren Lesern ein Internetphänomen ins Gedächtnis rufen, das seinen Ursprung im Jahr 1994 hat und zur Art und Weise passt, wie der Feiertag landläufig gefeiert wird – also feuchtfröhlich: Die 99 Bottles of Beer – in 1500 verschiedenen Programmiersprachen und Variationen.

Zugegeben, es ist noch ein wenig früh, sich vollends in Feierlaune zu begeben: Der St. Patrick’s Day wird erst am morgigen Samstag, 17. März, zelebriert. Besonders in Irland und den USA wird der St. Patrick’s Day als buntes Volksfest (mit Paraden und Festivals und ähnlichen Events) gefeiert, bei dem – ganz ähnlich unserem Fasching bzw. Karneval – die Leute oft ein wenig zu tief ins Glas schauen. In besagtem Glas befindet sich nicht selten grün eingefärbtes Bier, sogar ganze Flüsse werden zuweilen mit pflanzlichen und umweltverträglichen Farbstoffen in das typisch irische Grün gefärbt.

99 Flaschen Bier

Es ist nicht schwer, vom St. Patrick’s Day auf das Thema Bier und von dort aus zum Lied „99 Bottles of Beer“ zu kommen. Für alle, die den Song nicht kennen: Der Text ist ziemlich redundant, es wird in jeder Strophe eine Flasche Bier von der Wand genommen und dabei heruntergezählt:

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

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

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

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

Im Jahr 1994, als das Internet noch unschuldig und die Bandbreite noch stark begrenzt (und teuer!) war, kam ein Spaßvogel darauf, die gesamten Lyrics des Liedes auf einer Mailing-Liste zu teilen. Natürlich dauerte es nicht lange, bis einer der Leser – ein Entwickler – darauf kam, dass lediglich sechs Codezeilen in BASIC den gleichen Zweck erfüllen würden, wie die 200 Zeilen schriftlicher Textdarstellung. Um der Verschwendung von Bandbreite also Einhalt zu gebieten, erstellte er den folgenden Code:

REM BASIC Version of 99 Bottles of beer
FOR X=100 TO 1 STEP -1
PRINT X;"Bottle(s) of beer on the wall,";X;"bottle(s) of beer"
PRINT "Take one down and pass it around,"
PRINT X-1;"bottle(s) of beer on the wall"
NEXT

Klar, dass sich das Ganze über die letzten 24 Jahre verselbstständigt hat, mittlerweile gibt es 1500 unterschiedliche Versionen des Quelltextes in allen möglichen Programmiersprachen. Die Webseite 99-bottles-of-beer.net führt sie alle. Dort ist es auch möglich, den Code für neue Sprachen hochzuladen und seine Stimme für die beliebtesten Variationen abzugeben.

Die Kommentarfunktion auf der Webseite ist ein unendlicher Quell lustiger Momente. Ein Gast kommentierte etwa, dass das Java-Beispiel zeige, warum die Sprache als „bloated“ gelte:

/* 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"};
  }

Irgendwie verständlich, wenn man sich das Beispiel anschaut. Unter den 1500 Programmiersprachen sind logischerweise auch Sprachen, die in Unternehmen eher selten verwendet werden, die Aufgabe aber mit weitaus weniger Zeilen Code zu meistern im Stande sind. Mit LOLCODE wird der Quelltext beispielsweise deutlich kürzer als mit Java:

BTW LOLCODE version of 99 Bottles of beer
BTW By Mike Gogulski (http://www.gogulski.com/) 13 July 2007
BTW LOLCODE is a programming language by and for lolcats
BTW http://www.lolcode.com/
BTW
BTW Tested with:
BTW   sjlol version 1.1 for lolcode 1.0
BTW     Win32 binary: http://www.rit.edu/~sjl7678/sjlol.zip
BTW     Home: http://lolcode.com/implementations/sjlol 
BTW     Online interpreter: http://wealhtheow.rh.rit.edu:8080/index
BTW       (Doesn't work with comments, so delete all "BTW" lines)
BTW
BTW Save as 99BOTTLZ.LOL, start with "sjlol 99bottlz.lol"
BTW
BTW LOLCATZ CNT SPEL 2 GUD
BTW
HAI
    VISIBLE "O HAI! IM IN UR BEERZ!"
    I HAS A VAR
    LOL VAR R 99
    IM IN YR LOOP
        VISIBLE VAR!
        VISIBLE " BOTTLZ OF BEER N TEH WALL, "!
        VISIBLE VAR!
        VISIBLE " BOTTLZ OF BEER!"
        VISIBLE "TAKE 1 DWN, PAS IT AROUN, "!
        NERFZ VAR!!
        IZ VAR LIEK 0?
            YARLY
                VISIBLE "NO MOAR"!
            NOWAI
                VISIBLE VAR!
        KTHX
        VISIBLE " BOTTLZ OF BEER N TEH WALL!"
        IZ VAR LIEK 0?
            GTFO
        KTHX
    KTHX
    VISIBLE "GIEV MOAR PLZ! KTHXBAI!"
KTHXBYE

Manch ein Entwickler lässt sich sogar dazu hinreißen, seinen Code optisch in Form von ASCII-Kunst zu präsentieren, so ist der Quelltext für JavaScript in einer großen Darstellung der Zahl 99 erstellt worden, in der Sprache Brainfuck stellt der Code eine große Bierflasche dar und in DNA# wurde – wenig überraschend – der Code in Form einer Helix gebaut.

Vielleicht erstellt ja einer unserer Leser morgen zur Feier des Tages eine neue Version des Programms, Inspiration gibt es auf der Webseite des Projektes. Fehlen tun etwa noch die Versionen in TypeScript, Frege und Swift. Die Top 10 der 99-Bottles-of-Beer-Varianten gibt es hier.

Wir wünschen unseren Lesern einen fröhlichen St. Patrick’s Day!

Geschrieben von
Dominik Mohilo
Dominik Mohilo
Dominik Mohilo studierte Germanistik und Soziologie an der Goethe-Universität in Frankfurt. Seit 2015 ist er Redakteur bei S&S-Media.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.