Ninety-Nine Bottles Of Beer

August 5, 2011

We’ve been working hard for the last few exercises, and it is Friday, so we’ll have a little bit of fun. You all know the song, right?

Your task is to write a program that prints the lyrics to the popular song “Ninety-Nine Bottles Of Beer;” if this program seems too simple for you, make your solution as outlandish as you can — I definitely want to see a solution in Intercal or Brainf*ck. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

Pages: 1 2

13 Responses to “Ninety-Nine Bottles Of Beer”

  1. me said

    already amazingy done in every possibne way : http://99-bottles-of-beer.net/

  2. Kanon said
    UNO - Universal Notation (in development)
    
    #sing(x,y,z)
      $'{x} bottle{x|s} of beer on the wall, {x} bottle{x|s} of beer.
        Take one down and pass it around, {z} bottle{y|s} of beer on the wall',x,y,z
      ?y=0 $'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.'
    
    @99-1:i sing(i,i-1,i-1|'no more')
    

    UNO is based in one simple principle: #=def, $=print, ?=cond, @=loop is all you need to build any algorithm

  3. Bogdan Popa said

    Wrote this a while ago for Rosetta Code:

    #!/usr/bin/env python3
    """\
    {0} {2} of beer on the wall
    {0} {2} of beer
    Take one down, pass it around
    {1} {3} of beer on the wall
    """
    print("\n".join(
        __doc__.format(
            i, i - 1,
            "bottle" if i == 1 else "bottles",
            "bottle" if i - 1 == 1 else "bottles"
        ) for i in range(99, 0, -1)
    ), end=""
    
  4. print '\n'.join('{0} bottle{2} of beer on the wall, {0} bottle{2} of beer!\nTake one down, pass it around,\n{0} bottle{3} of beer on the wall!\n'.format(i, i - 1, i > 1 and 's' or '', i > 2 and 's' or '') for i in range(100, 0, -1))
    
  5. lukaszk said

    ok, sorry :)

    print '\n'.join('{0} bottle{2} of beer on the wall, {0} bottle{2} of beer!\nTake one down, pass it around,\n{1} bottle{3} of beer on the wall!\n'.format(i, i - 1, i > 1 and 's' or '', i > 2 and 's' or '') for i in xrange(99, 0, -1))
    
  6. First time poster. But I’ll give it a shot.

    using System;

    class Program
    {
    static void Main(string[] args)
    {
    for (int number = 99; number > 0; number–)
    {
    int nextNumber = number – 1;
    Console.WriteLine("{0} {1} of beer on the wall, {0} {1} of beer…", number, number > 1 ? "bottles":"bottle" );
    Console.WriteLine("Take one down, pass it around {0} {1} of beer on the wall.", nextNumber, nextNumber != 1 ? "bottles" : "bottle");
    Console.WriteLine();
    }//end for
    }
    }

  7. Try that again.

    using System;
    
        class Program
        {
            static void Main(string[] args)
            {
                for (int number = 99; number > 0; number--)
                {
                    int nextNumber = number - 1;
                    Console.WriteLine("{0} {1} of beer on the wall, {0} {1} of beer...", number, number > 1 ? "bottles":"bottle"  );
                    Console.WriteLine("Take one down, pass it around {0} {1} of beer on the wall.", nextNumber, nextNumber != 1 ? "bottles" : "bottle");
                    Console.WriteLine();
                }//end for
            }
        }
    
  8. My implementation, which uses C++ template metaprogramming with the Boost MPL library, generates the text of the song at compile time. .gist table { margin-bottom: 0; } This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters #include <boost/mpl/assert.hpp> #include <boost/mpl/at.hpp> #include <boost/mpl/back_inserter.hpp> #include <boost/mpl/copy.hpp> #include <boost/mpl/divides.hpp> #include <boost/mpl/empty_sequence.hpp> #include <boost/mpl/equal.hpp> #include <boost/mpl/equal_to.hpp> #include <boost/mpl/fold.hpp> #include <boost/mpl/for_each.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/joint_view.hpp> #include <boost/mpl/less.hpp> #include <boost/mpl/minus.hpp> #include <boost/mpl/modulus.hpp> #include <boost/mpl/push_back.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/string.hpp> #include <boost/mpl/transform.hpp> #include <boost/mpl/vector.hpp> #include <iostream> using namespace boost::mpl; template <typename n> struct NumberInEnglish { // Can't handle >= 100 BOOST_MPL_ASSERT(( less<n, int_<100> > )); typedef int_<10> ten; typedef int_<20> twenty; typedef char_<'–'> dash; typedef vector< string<>, // use Ones vector string<>, // use Teens vector string<'twen','ty'>, string<'thir','ty'>, string<'four','ty'>, string<'fift','y'>, string<'sixt','y'>, string<'seve','nty'>, string<'eigh','ty'>, string<'nine','ty'> > Tens; typedef vector< string<'no ','more'>, string<'one'>, string<'two'>, string<'thre','e'>, string<'four'>, string<'five'>, string<'six'>, string<'seve','n'>, string<'eigh','t'>, string<'nine'> > Ones; typedef vector< string<'ten'>, string<'elev','en'>, string<'twel','ve'>, string<'thir','teen'>, string<'four','teen'>, string<'fift','een'>, string<'sixt','een'>, string<'seve','ntee','n'>, string<'eigh','teen'>, string<'nine','teen'> > Teens; typedef if_< modulus<n, ten>, typename copy< joint_view< typename push_back<typename at<Tens, divides<n, ten> >::type, dash>::type, typename at<Ones, modulus<n, ten> >::type>, back_inserter<string<> > >::type, typename at<Tens, divides<n, ten> >::type > DoubleDigit; typedef typename if_< less<n, ten>, typename at<Ones, n>::type, typename if_< less<n, twenty>, typename at<Teens, minus<n, ten> >::type, typename DoubleDigit::type >::type >::type type; }; BOOST_MPL_ASSERT(( equal< NumberInEnglish<int_<4> >::type, string<'four'> > )); BOOST_MPL_ASSERT(( equal< NumberInEnglish<int_<14> >::type, string<'four','teen'> > )); BOOST_MPL_ASSERT(( equal< NumberInEnglish<int_<20> >::type, string<'twen','ty'> > )); BOOST_MPL_ASSERT(( equal< NumberInEnglish<int_<44> >::type, string<'four','ty-f','our'> > )); template <typename n> struct CountBottles { typedef string<'bott','le'> Bottle; typedef typename copy< joint_view< typename push_back< typename NumberInEnglish<n>::type, char_<' '> >::type, typename if_< equal_to<n, int_<1> >, Bottle, push_back<Bottle, char_<'s'> >::type >::type >, back_inserter<string<> > >::type type; }; BOOST_MPL_ASSERT(( equal< CountBottles<int_<0> >::type, string<'no m','ore ','bott','les'> > )); BOOST_MPL_ASSERT(( equal< CountBottles<int_<1> >::type, string<'one ','bott','le'> > )); BOOST_MPL_ASSERT(( equal< CountBottles<int_<14> >::type, string<'four','teen',' bot','tles'> > )); template <typename n> struct Verse { typedef string<'n'> NL; typedef string<',n'> CommaNL; typedef string<' of ','beer'> OfBeer; typedef string<' on ','the ','wall'> OnTheWall; typedef string<'take',' one',' dow','n, p','ass ','it a','roun','d,n'> TakeOneDownPassItAround; typedef typename transform< vector< typename CountBottles<n>::type, OfBeer, OnTheWall, CommaNL, typename CountBottles<n>::type, OfBeer, CommaNL, TakeOneDownPassItAround, typename CountBottles<typename prior<n>::type>::type, OfBeer, NL, NL >, c_str<_1> >::type strings; }; struct PrintValue { PrintValue(std::ostream& os) : os_(os) {} std::ostream& os_; template <typename T> void operator() (T t) { os_ << T::value; } }; template <typename n> std::ostream& operator<< (std::ostream& os, Verse<n> verse) { boost::mpl::for_each<typename Verse<n>::strings>(PrintValue(os)); }; struct PrintTo { PrintTo(std::ostream& os) : os_(os) {} std::ostream& os_; template <typename T> void operator() (T t) { os_ << t; } }; int main() { boost::mpl::for_each< range_c<int, 1, 100>, lambda< Verse<minus<int_<100>, _1> > >::type>( PrintTo(std::cout)); return 0; } view raw 99bob.cpp hosted with ❤ by GitHub It also generates english words instead of digits (i.e. “forty-four” instead of “44”). Not sure if that was part of the brief or not – wasn’t too hard to implement anyway.
  9. Some timing… I recently wrote two versions of the “song”

    http://www.emmanueloga.com/2011/07/29/drinking-contest.html

    Greetings.

  10. I once SSH’d into my roommate’s mac and ran this little bash script while I was at work and he was home alone.

    for ((i=99; i>0 ; i–));
    do
    let “j = i – 1”;
    say $i bottles of beer on the wall;
    say $i bottles of beer;
    say take one down ;
    say pass it around;
    say $j bottles of beer on the wall;
    done

    Then I denied all knowledge of it, and told him the computer must have just been really bored.

  11. Alex said

    def song(num):
    if num == 0:
    print “Song is over”
    elif num == 1:
    print str(num) + ” bottle of beer on the wall”
    else:
    print str(num) + ” bottles of beer on the wall”
    song(num-1)

  12. Nothing particularly clever, but FWIW… In PLT Racket.

    #lang scheme
    (require srfi/1) ; for iota
    
    ;;; Converts 1 to 99 into words
    ;;; There's a PLaneT package for this: (require (planet neil/numspell:1:2))
    ;;; But I whipped this up before I went to find it
    ;;; Turns out that Neil used the same two lists that I did
    (define (number->words n)
      (let ((uniques '("zero" "one" "two" "three" "four" "five" "six" "seven"
                              "eight" "nine" "ten" "eleven" "twelve" "thirteen"
                              "fourteen" "fifteen" "sixteen" "seventeen" "eighteen"
                              "nineteen"))
            (tens '("twenty" "thirty" "fourty" "fifty" "sixty" "seventy" "eighty"
                             "ninety")))
        (cond ((< n 20)
               (list-ref uniques n))
              ((< n 100)
               (string-append
                (list-ref tens (- (quotient n 10) 2))
                (let ((r (remainder n 10)))
                  (if (= r 0)
                      ""
                      (string-append "-" (list-ref uniques r))))))
              (else #f))))
    
    ;;; There's certainly a better way...didn't think too long about it
    ;;; Unfortunately string-titlecase doesn't do exactly what I want
    (define (capitalize word)
      (let-values (((head tail) (car+cdr (string->list word))))
        (list->string (cons (char-upcase head)
                            tail))))
    
    ;;; Print the lyrics for "Ninety-nine bottles of beer"
    ;;; The value of fall (#t or #f) will determine the variant
    (define (sing-it fall)
      (for-each
       (lambda (n)
         (let ((n-bottles-of-beer
                (string-append
                 (capitalize (number->words n))
                 " "
                 (if (= n 1)
                     "bottle"
                     "bottles")
                 " of beer")))
           (unless (= n 99)
             (displayln (string-append n-bottles-of-beer " on the wall!"))
             (newline))
           (displayln (string-append n-bottles-of-beer " on the wall!"))
           (displayln (string-append n-bottles-of-beer "!"))
           (if fall
               (displayln "If one of those bottles should happen to fall,")
               (displayln "Take one down; pass it around!"))))
       (iota 99 99 -1))
      (displayln "No more bottles of beer on the wall!"))
    
    (sing-it #t)
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: