Interview questions – Change for a dollar

Monday, 22 March 2010 12:19 by James

So, in my quest to become gainfully employed, I am going through the interview process, mainly technical interviews with hands-on developers. Unfortunately, they seem to want people that 1) either *just* graduated from Computer Science school, or 2) can memorize obscure bits of code, and recite the Visual Studio help files verbatim.

At my last interview, I walked in – after a two-hour car ride, and trying to find a parking spot – to a “Hi, let’s write some code on the white board” situation. Ok, I say to myself, “let’s give this a try”. Their first question, “write code to calculate the optimum number of coins to return when giving change after a purchase.”

Hmm, I think. And I stumbled around for a bit, eventually ending up writing some pseudo-code that involved some long division. The Inland Empire .NET User’s Group’s next meeting was the following Tuesday, and I decided to ask them the same question – however they had the luxury of being in a friendly environment with soda and pizza in their fiery little bellies.

Below are the two answers that UG members sent to me, and it got me to thinking. What I would like to do is have you write your code in the comments, so I can see how many different ways there are to write this method.

From member Daniel Lopez, “Just for grins. If you have suggestion on how to make it better, let me know.”

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GiveChange
{
      class Program
      {
            static void Main(string[] args)
            {
                  DoChange(8.92);
            }

            private static void DoChange(double Tendered)
            {
                  double _DecimalPart = Math.Round(1-( Tendered - Math.Floor(Tendered)),2);
                  do
                  {
                        if (_DecimalPart >= .25)
                        {
                              Change.Quarters += 1;
                              _DecimalPart -= .25;
                        }
                        else if (_DecimalPart >= .10)
                        {
                              Change.Dines += 1;
                              _DecimalPart -= .1;
                        }
                        else if (_DecimalPart >= .05)
                        {
                              Change.Nickles += 1;
                              _DecimalPart -= .05;
                        }
                        else 
                        {
                              Change.Pennies += (int)(_DecimalPart * 100);
                              _DecimalPart -= _DecimalPart;
                        }
                  }
                  while (_DecimalPart > 0);

                  StringBuilder sb = new StringBuilder();

                  sb.Append(string.Format( "Quarters: {0}", Change.Quarters));
                  sb.AppendLine();
                  sb.Append(string.Format("Dines: {0}", Change.Dines));
                  sb.AppendLine();
                  sb.Append(string.Format("Nickles: {0}", Change.Nickles));
                  sb.AppendLine();
                  sb.Append(string.Format("Pennies: {0}", Change.Pennies));

                  Console.WriteLine(sb.ToString());
                  Console.ReadLine();            
            }      
      }

      public  static  class Change
      {
            public static int Quarters { get; set; }
            public static int Dines { get; set; }
            public static int Nickles { get; set; }
            public static int Pennies { get; set; }
      }
}

And from member Henry Vander Leest, "Hi James, Was thinking about the comments you made at the meeting about the interview you had the the question about the code to make change. Well, here's my solution... I don't believe I could have written this in 5 minutes under stressful circumstances. Live Long and prosper."

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ChangeMaker1
{
    class Program
    {
        static void Main(string[] args)
        {
            //takes command line arg from 1 to 99 to make change for a dollar
            int quarters;
            int dimes;
            int nickels;
            int pennies;
            int tendered = 100;
            int cost = Convert.ToInt32(args[0]);
 
            int change = tendered - cost;
            quarters = change / 25;
            change -= quarters * 25;
 
            dimes = change / 10;
            change -= 10 * dimes;
 
            nickels = change / 5;
            change -= nickels * 5;
 
            pennies = change;
 
            Console.WriteLine("Quarters {0}, Dimes {1}, Nickels {2},  Pennies {3}, 
This is the change for item costing {4} cents",
quarters, dimes, nickels, pennies, cost ); } } }

I tested both, and they work like a champ. Now I just need to memorize these for my next round of interviews. So tell me, how would you do this “simple” exercise.

Time to work…

James

Comments

March 22. 2010 13:13

Ok, here's my stab at it...

First, a class for defining coin denominations with value and name (sing/plur). The reason for this is that there are different denominations in different countries, and every now and then some countries add or remove available denominations...

internal class Coin
{
    internal Coin(decimal value, string nameSingular, string namePlural)
    {
        Value = value;
        NameS = nameSingular;
        NameP = namePlural;
    }

    internal decimal Value { get; private set; }
    internal string NameS { get; private set; }
    internal string NameP { get; private set; }
}

...once we have that, the available denominations are defined in a single place (here hardcoded, but in real life from app.config/web.config/a database/...:

//define available denominations
internal List<Coin> _availableDenominations = new List<Coin>
{
    //for illustration: new Coin (0.50M, "Half Dollar", "Half Dollars"),
    new Coin (0.25M, "Quarter", "Quarters"),
    new Coin (0.10M, "Dime", "Dimes"),
    new Coin (0.05M, "Nickel", "Nickels"),
    new Coin (0.01M, "Penny", "Pennies")
};

...turning that into change is easy-peasy:

internal List<KeyValuePair<Coin, int>> GetChange(decimal amount)
{
    List<KeyValuePair<Coin, int>> change = new List<KeyValuePair<Coin, int>>();

    //get the paper money out of the way
    amount = amount % 1;

    //find # of each for each denomination
    foreach (Coin coin in _availableDenominations)
    {
        change.Add(new KeyValuePair<Coin, int>(coin, (int)(amount / coin.Value)));
        amount = amount % coin.Value;
    }
    return change;
}

...the above spits out a list of all denominations and counts of each. If we want to turn it into text, a short linq query comes in handy:

internal string SpellOutChange(List<KeyValuePair<Coin, int>> change)
{
    //spell out as text
    return string.Join(", ",
        (
            change
                .Where(c => c.Value > 0)
                .Select(co => co.Value.ToString()
                    + " "
                    + (co.Value == 1 ? co.Key.NameS : co.Key.NameP))
        ).ToArray());
}

KristoferA

March 22. 2010 14:24

Ok, an iterator would be overkill in this case, but just for fun... (replaces GetChange in my previous comment):

internal IEnumerable<KeyValuePair<Coin, int>> GetChange(decimal amount)
{
    //get the paper money out of the way
    amount = amount % 1;

    //find # of each for each denomination
    foreach (Coin coin in _availableDenominations)
    {
        int coinsNeeded = (int)(amount / coin.Value);
        if (coinsNeeded > 0)
        {
            yield return new KeyValuePair<Coin, int>(coin, coinsNeeded);
        }
        amount = amount % coin.Value;
        if (amount == 0)
        {
            yield break;
        }
    }
}

KristoferA

March 22. 2010 19:12

@kristofer I totally forgot about Half Dollars, and I remember now, they did ask about foreign currency. Is this a valid question in a technical interview?

James

James

March 23. 2010 10:33

Ok im learning python right now, so i thought it would be nice to write this. Thats how i did it (the coin is index of changeValues e.g. 0 - quater)

changeValues = (25, 10, 5, 1)

def calculate(change, coin, sum = 0):
    if coin > 3 or sum == change:
        return
    if change >= (sum + changeValues[coin]):
        print changeValues[coin]
        calculate(change, coin, (sum + changeValues[coin]))
    else:
        calculate(change, coin+1, sum)

calculate(69, 0) // test it

Ignas

March 23. 2010 17:14

@James Not sure if it is a valid question, but I guess they're trying to see if the candidate is good at covering possible scenarios.

Personally I don't like tech interview questions (or tech interviews). They make me too nervous, so I don't think I have ever passed (or will ever pass) a tech interview... Smile

KristoferA

March 24. 2010 02:26

Nice f# solution:

let change sum =
    let coins = [0.25m; 0.10m; 0.05m; 0.01m]
    let rec change_rec sum coins =
        match coins with
        | h :: t ->
            let temp = System.Math.Floor((decimal)(sum / h))
            temp :: (change_rec (sum - h*temp) t)
        | [] -> []
    List.zip coins (change_rec (sum - System.Math.Floor(sum)) coins) |> List.map(fun (a, c) -> (a.ToString() + " - " + c.ToString()))

printfn "Change %A:" (change 2.96m)

valera kolupaev

March 24. 2010 05:55

public class getChange{
public static void main(String args){
  double cost = 8.92;//should make sure this has been cleansed and is actually no
  //more than 2 digit places.
  int costInt = (int) cost * 100;
  int remainders = costInt % 25;
  int quarters = costInt / 25;
  int dimes = remainders /10;
  remainders = remainders % 10;
  int nickels = remainders / 5;
  remainders = remainders % 5;
  System.out.println("quarters:"+quarters+" dimes:" +dimes+" nickels:"+nickels+" pennies:"+remainders);
}
//prints out quarters:35 dimes:1 nickels:1 pennies:2
}

But thats just because it doesn't say anything about paper money, could be a vending machine that only has coins etc, doesn't cover bases of what to do if that many coins aren't available etc.

99/100 they aren't looking for the code, they are looking for the critical thinking that requires asking what context they require the code for. if it is a vending machine then you need error handling based on dispensing coins. However they asked for optimal number of coins to return, which is what they got.

Tristan

March 25. 2010 18:06

How about this:

    public static void DoChange(double price, double paid)
    {
        int cents = (int)(100 * (paid-price));
        Console.WriteLine(
            "Quarters {0}, Dimes {1}, Nickels {2},  Pennies {3}",
            (cents/25, (cents%25)/10, (cents%10)/5, cents%5);
    }

Igor Ostrovsky

June 15. 2010 11:05

Wow, this is so inspiring. Everyone should always be looking to better themselves. This really helps.

Übersetzung Deutsch Französisch

June 16. 2010 00:45

    public static void DoChange(double price, double paid)
    {
        int cents = (int)(100 * (paid-price));
        Console.WriteLine(
            "Quarters {0}, Dimes {1}, Nickels {2},  Pennies {3}",
            (cents/25, (cents%25)/10, (cents%10)/5, cents%5);
    }

this equal size component

Best Laptop Computer

James Johnson

My views and opinions on running a .NET User Group, web development, evangelizing, mentoring, utilizing the latest technologies, living as a gringo in a Latin family, and, of course, life in general.

Join BizSpark

BizSpark provides qualified Startups with FREE* software and support getting their idea up and running.
There is no charge for signing up. However a minimal fee of $100 is required when you leave the program.

Recent Comments