Vala.dev A personal blog from a hobbist developer.

Programming Challenge: 99 Bottles

99 Bottles of Beer on the Wall in a command line app.


Posted by David Rodriguez

So, today I was bored! I decided to think of something small to make with Vala, and I couldn’t think of anything great. Therefore I decided, since I am still learning the language, to do something simple. Something that every new programmer should try. The 99 Bottles application.

99 Bottles is a simple command line application that writes out the lyrics to the classic, ‘99 bottles of beer on the wall’, song.

The Rules…

For this challenge, a few rules will be set and must be followed. They are as follows:

  1. Create a program that prints out every line to the song “99 bottles of beer on the wall”.
  2. Do not use a list for all of the numbers, and do not manually type them all in. Use a built in function instead.
  3. Besides the phrase “take one down,” you may not type in any numbers/names of numbers directly into your song lyrics.
  4. Remember, when you reach 1 bottle left, the word “bottles” becomes singular.

As a bonus, I decided to add one more (optional) rule to this challenge.

  • If there are no more bottles, make it known that none can be taken down and passed around.

Lets Begin

To start, rule number one says, “Create a program that prints out every line to the song ‘99 bottles of beer on the wall’.” and rule number two says, “Do not use a list for all of the numbers, and do not manually type them all in. Use a built in function instead.” Since we know that the lyrics to ‘99 Bottles’ is very repetitive, mainly changing only the numbers inside of the lyrics. We can use a loop for this.

I personally picked a for loop and a while loop to complete this challenge. The examples in this blog post will be done using for loop. The complete code can be found here on my GitLab page. There you will also find a solution to this challenge, using a while loop as well.

Let’s get started by creating the loop. This lays the foundation down for completing steps one (1), and two (2).

public static int main(string [] argv) {
  int bottles;

  for (bottles = 99; bottles >= 0; bottles--) {

  }
  return 0;
}

Here, we declare an integer variable named ‘bottles’. Inititally this variable will hold a null value. Next comes the structure of the for loop itself. We assign the value of 99 to the ‘bottles’ variable. In this loop, we’re going to count down. Just like in the song.

The lyrics…

After that comes the lyrics (make sure to add these to your loop and not outside of the loop). I believe it is safe to say that we can split the lyrics of this song into two string templates. String templates in Vala are strings prefixed with an ‘@’ symbol are capable of evaluating embedded variables and expressions prefixed with ‘$’. (Learn more about strings in Vala here)

    string lyrics1 = @"$bottles bottles of beer on the wall. $bottles bottles of beer.\n";
    string lyrics2 = @"Take one down, pass it around, $(bottles - 1) bottles of beer of the wall.\n\n";
    stdout.printf(lyrics1);
    stdout.printf(lyrics2);
}

If you were to run this code right now, it actually satisfies most of the requirements for this challenge. Except, we haven’t changed ‘bottles’ to ‘bottle’ inside of the lyrics when there is 1 (one) bottle left. Not to mention, when it reaches 0 (zero) bottles, it states that there are -1 bottles left. This is wrong.

The logic…

Let’s take care of the logic when it comes to numbers and whether or not to use the singluar or plural of beer, depending on the amount of beers left. To do this, we add a simple if and else if statement that runs inside of the loop.

We’ll place it bewteen the string definition of lyrics2 and the printf() function. The if and else if statements will check the current amount of bottles left and adjust the lyrics as necessary, completing this application challenge.

if (bottles == 1) {
  lyrics1 = @"$bottles bottle of beer on the wall. $bottles bottle of beer.\n";
  lyrics2 = @"Take one down, pass it around, $(bottles - 1) bottle of beer of the wall.\n\n";
} else if (bottles == 0) {
  lyrics2 = @"You can't take one down and pass it around, because there are $(bottles) bottles of beer of the wall.\n\n";
}

The complete source code

Below is a copy of the complete source code for this cli application and instructions on compiling and running it. Make sure to save this in a file ending with .vala. For example, 99Bottles.vala.

/**
 * Copyright (c) 2019 Vala.dev (https://vala.dev/). All Rights Reserved.
 * Copyright (c) 2019 David Saul Rodriguez <david@enyutech.io>. All Rights Reserved.
 *
 * This file is subject to the terms and conditions defined in
 * file 'LICENSE.md', which is part of this source code package
 * or at https://vala.dev/legal/source-code-license
 */

public static int main(string [] argv) {
  int bottles;

  for (bottles = 99; bottles >= 0; bottles--) {
    string lyrics1 = @"$bottles bottles of beer on the wall. $bottles bottles of beer.\n";
    string lyrics2 = @"Take one down, pass it around, $(bottles - 1) bottles of beer of the wall.\n\n";
    if (bottles == 1) {
      lyrics1 = @"$bottles bottle of beer on the wall. $bottles bottle of beer.\n";
      lyrics2 = @"Take one down, pass it around, $(bottles - 1) bottle of beer of the wall.\n\n";
    } else if (bottles == 0) {
      lyrics2 = @"You can't take one down and pass it around, because there are $(bottles) bottles of beer of the wall.\n\n";
    }
    stdout.printf(lyrics1);
    stdout.printf(lyrics2);
  }
  return 0;
}

You can run this program without compiling, like so:

# The output of the program will be displayed immediately.
$ vala 99Bottles.vala

Or you can compile and then run the program, like so:

$ valac 99Bottles.vala -o 99Bottles
$ ./99Bottles
99 bottles of beer on the wall. 99 bottles of beer.
Take one down, pass it around, 98 bottles of beer of the wall.

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

If you would like a direct link to the source code, that can be found here.

Summary

Overall, the 99 Bottles challenge isn’t a hard thing to do. If you are absolutely new to programming, I will admit, it can seem like a daunting task. But, truth be told, it was fun and easy. I also got to learn about String Templates in Vala.

Vala is a very fun language. Eventually I will get around to programming small GUI (Graphical User Interface) applications. But for now, I will continue on my programming challenge journey with small, command line based apps. I have no idea what program or challenge will be next though. Maybe you can help with that.

If you have an idea of what you want to see next or a programming challenge you’d like to offer, please feel free to contact me. My personal website acts as an online directory for the best way to both, get a hold of me, and find me online.

Until next time everyone,
David S. Rodriguez II