Two Things

Gaming and Programming.. maybe programming for some games, who knows. Either way, I'm a geek, right?

Adventures in Interviewing #1: The Coin Jar

Interviewing for a programming position usually involves some sort of programming test - either verbally, or on a whiteboard, or occasionally something more interesting.  I've dug around my emails for some of the more interesting (or challenging) ones.  I don't expect to get much feedback from these, but felt like posting them anyway.

This is the first in the series.

Implement a coin jar in C#. The coin jar will only accept US coinage and has a volume of 32 fluid ounces. Additionally, the jar has a counter to keep track of the total amount of money collected and has the ability to reset the count back to $0.00.

Evaluation

My first consideration is how complex to make this thing.  They did not give any guidance about time frames to complete it, whether they wanted actual code that would compile versus a text file of pseudocode, whether they wanted unit tests, etc.  The above was the sole beginning and end of it.  Since this was the third question in an overall coding "test", I decided to give them a working solution that would compile and met the requirements - and nothing further (no unit tests).  In hindsight, the lack of unit tests might have been my undoing for this specific position, but without any feedback from them on my chosen solution, I really don't know.

So now we need to figure out some stuff.  Since this seems to be a volume question, we need to know the volume of standard US coins, and the volume of the jar.  Mister Google helps us out there.

US Mint Coin Specifications
Fluid Ounce to Cubic Centimeter Calculator

Of course there's other considerations too - the capacity of the jar would also be influenced by its physical dimensions and whether the jar cylindrical or rectangular.  For the coins themselves, how the coins fall into the jar, and the mixture of coins have an impact on just how many the jar could "hold" before it became full.  But I think that these considerations are likely out of scope for an interviewing question, so I took the perfect storm approach - the coins would fall perfectly and magically arrange themselves inside a jar that changes its shape magically so that all available space would be used, as long as 32 fluid ounces of coins were involved.

Bases covered, time to start coding.  I decided to make this a console application, as it would be less code and could be sent back to them as a text document that they could cut/paste into VStudio or whatever to compile.

The Classes

So obviously we need a couple of classes here - a Coin class, and a Jar class.

public class Coin {
    public string CoinName { get; set; }
    public double Diameter { get; set; }
    public double Thickness { get; set; }
    public int CoinValue { get; set; }

    //Note: Volume is the cylindrical volume of the coin.  BoxVolume is the effective space occupied by the coin.
    //Not using Volume in this implementation but for sake of completeness it's present.
    public double Volume { get { return Math.Pow((Diameter / 2), 2) * Math.PI * Thickness; } }
    public double BoxVolume { get { return Diameter * Diameter * Thickness; } }

    public Coin(string name, double diameter, double thickness, int coinValue) {
      CoinName = name;
      Diameter = diameter;
      Thickness = thickness;
      CoinValue = coinValue;
   }
}

The class is pretty straight forward - a few relevant properties and a couple of calculations. I included two Volume calculations - one for the actual cylindrical calculation and a more simple "box volume" to see how much space the coin as a whole takes up. The actual volume would be useful if going into granular determination of how the coins mesh together, but for this project in my magic jar, I just wanted their basic volume.

public class Jar {
    //define the volume of the jar in cubic millimeters
    //source.. http://www.asknumbers.com/CubicCentimeterToOunce.aspx
    const double UsFluidOunceInCubicMM = 29573.5296;

    private double _volumeRemaining;
    private int _totalCoinValue;

    //storing the individual coins would allow for future functionality such as
    //listing a count by coin type, removing all quarters, etc.
    private List _bankedCoins;

    public Jar(int fluidOunces) {
      _volumeRemaining = fluidOunces * UsFluidOunceInCubicMM;
      _totalCoinValue = 0;
      _bankedCoins = new List();
    }

    public bool AddCoin(Coin coinToAdd) {
      //check to see if there's enough space in the jar to hold the coin
      if (coinToAdd.BoxVolume < _volumeRemaining) {
        _bankedCoins.Add(coinToAdd);
        _totalCoinValue += coinToAdd.CoinValue;
        _volumeRemaining -= coinToAdd.BoxVolume;
        return true;
      }
      return false;
    }

    //return the current value of the jar's contents
    public int GetCurrentValue() {
      return _totalCoinValue;
    }

    //empty the jar of coins
    public void EmptyTheJar() {
      _totalCoinValue = 0;
      _bankedCoins.Clear();
    }
  }

For the Jar class, again, some basic properties and a magic number to convert fluid ounces into cubic millimeters (the online calculator was in centimeters, but changed it to millimeters here to match the dimensions of the coins.. the alternative was to convert the coins into cubic centimeters.. six of one, half dozen the other..).  As an unneeded caveat, I added a collection to the Jar class to store individual coins, in case someone wanted to remove all of a particular coin type, or count up the dimes, etc.  The rest is pretty self-explanatory.. a method to get the current value inside the jar, and empty it -- the latter a requirement of the problem.

The Program

All that's left is to write the program to initialize everything and print out a few test statements.

class Program {

    //define the allowed coins.  using a dictionary for easier lookup.
    private static Dictionary<int, Coin> _allowedCoins = new Dictionary<int, Coin>();
    private static Jar _theCoinJar;

    static void Main(string[] args) {
      //define the jar for 32 fluid ounces
      _theCoinJar = new Jar(32);

      //define the coins.. just in case the dimensions change
      //current source.. http://www.usmint.gov/about_the_mint/?action=coin_specifications
      _allowedCoins.Add(1, new Coin("Penny", 19.05, 1.55, 1));
      _allowedCoins.Add(5, new Coin("Nickel", 21.21, 1.95, 5));
      _allowedCoins.Add(10, new Coin("Dime", 17.91, 1.35, 10));
      _allowedCoins.Add(25, new Coin("Quarter", 24.26, 1.75, 25));
      _allowedCoins.Add(50, new Coin("Half Dollar", 30.61, 2.15, 50));

      //usage
      AddCoin(10);
      AddCoin(5);
      AddCoin(25);
      AddCoin(50);
      AddCoin(75); //should be rejected.
      Console.WriteLine("The jar contains {0} cents.", _theCoinJar.GetCurrentValue()); //should be 90 cents
      _theCoinJar.EmptyTheJar();
      Console.WriteLine("The jar contains {0} cents.", _theCoinJar.GetCurrentValue()); //should be 0 cents
    }

    static void AddCoin(int coinValue) {
      if (_allowedCoins.ContainsKey(coinValue)) {
        if (_theCoinJar.AddCoin(_allowedCoins[coinValue])) {
          Console.WriteLine("{0} added to the jar.", _allowedCoins[coinValue].CoinName);
        }
        else {
          Console.WriteLine("The jar doesn't have enough space for a {0}.", _allowedCoins[coinValue].CoinName);
        }
      }
      else {
        Console.WriteLine("Please insert a standard US coin.");
      }
    }
  }

Set up a couple of global variables to hold the coin dictionary and the jar itself, define the individual coins, add a method to add the coins into the jar with some rudimentary error checking to see if the jar is full, or an invalid coin is dropped in.. and that's it. 

Loading