3
\$\begingroup\$

I was tasked with writing a method which would take in an int (for amount in coins) and then convert the coins, accordingly, by counting how many quarters, dimes, nickels, and pennies were located in the amount. Afterwards, it would return a String which stated each count of individual coin.

public class Coins {

    private static final int QUARTER_VALUE = 25;
    private static final int DIME_VALUE = 10;
    private static final int NICKEL_VALUE = 5;
    private static final int PENNY_VALUE = 1;

    public static String convert(int amount) {
        int currentAmount = amount;
        int quarters = 0;
        int dimes = 0;
        int nickels = 0;
        int pennies = 0;

        String quarterUnit = new String();
        String dimeUnit = new String();
        String nickelUnit = new String();
        String pennyUnit = new String();

        if (amount != 0) {
            quarters = amount / QUARTER_VALUE;

            currentAmount = 
                     amount - (quarters * QUARTER_VALUE);

            dimes = currentAmount / DIME_VALUE;

            currentAmount = 
                     amount - (quarters * QUARTER_VALUE) - (dimes * DIME_VALUE);

            nickels = currentAmount / NICKEL_VALUE;

            currentAmount = 
                     amount - (quarters * QUARTER_VALUE) 
                     - (dimes * DIME_VALUE) - (nickels * NICKEL_VALUE);

            pennies = currentAmount / PENNY_VALUE;
        }

        if (quarters == 1) {
            quarterUnit = " quarter";
        }

        else if (quarters > 1 || quarters == 0){
            quarterUnit = " quarters";
        }

        if (dimes == 1) {
            dimeUnit = " dime";
        }

        else if (dimes > 1 || dimes == 0) {
            dimeUnit = " dimes";
        }

        if (nickels == 1) {
            nickelUnit = " nickel";
        }

        else if (nickels > 1 || nickels == 0) {
            nickelUnit = " nickels";
        }

        if (pennies == 1) {
            pennyUnit = " penny";
        }

        else if (pennies > 1 || pennies == 0) {
            pennyUnit = " pennies";
        }

        StringBuilder conversion = new StringBuilder();

        return conversion.append(quarters)
                         .append(quarterUnit)
                         .append("\n")
                         .append(dimes)
                         .append(dimeUnit)
                         .append("\n")
                         .append(nickels)
                         .append(nickelUnit)
                         .append("\n")
                         .append(pennies)
                         .append(pennyUnit)
                         .append("\n")
                         .toString();
    }

    public static void main(String[] args) {
        String conversionString = convert(89);

        System.out.println(
              new StringBuilder().append("Converted amount equates to: ")
                                 .append("\n"));

        System.out.println(conversionString);
    }
}

Here's the output:

Converted amount equates to: 

3 quarters
1 dime
0 nickels
4 pennies

Is there a more efficient (fewer lines of code or a better OO style) way to implement this?

\$\endgroup\$
  • \$\begingroup\$ Hmm the unit names could be abbreviated to something like nickelUnit = nickels==1 ? " nickel" : (nickels==0||nickels>1 ? " nickels" : "ERROR - negative amount of nickels!"); but I'm not sure you'd really gain much from that. \$\endgroup\$ – FrustratedWithFormsDesigner Sep 9 '13 at 21:08
5
\$\begingroup\$

Highlighting what a few helper classes can do :

Imagine this enum

private enum Coin {
    QUARTER(25, "quarter"), DIME(10, "dime"), NICKEL(5, "nickel"), PENNY(1, "penny", "pennies");
    ...

and a tuple of quotient and remainder :

private static class QuotientAndRemainder {
    private final int quotient;
    private final int remainder;

so the enum can sport this method :

public QuotientAndRemainder divide(int pennies) {
    return QuotientAndRemainder.quotient(pennies / pennyValue).withRemainder(pennies % pennyValue);
}

and this one :

public String format(int amount) {
    return Integer.toString(amount) + ' ' + (amount == 1 ? singular : multiple);
}

then the convert method simply becomes :

public static String convert(int amount) {
    return print(minimalChange(amount));
}

private static String print(Map<Coin, Integer> amounts) {
    StringBuilder builder = new StringBuilder();
    for (Coin coin : amounts.keySet()) {
        builder.append(coin.format(amounts.get(coin))).append('\n');
    }
    return builder.toString();
}

private static Map<Coin, Integer> minimalChange(int amount) {
    int penniesLeft = amount;
    Map<Coin, Integer> amounts = new EnumMap<Coin, Integer>(Coin.class);
    for (Coin coin : Coin.values()) {
        QuotientAndRemainder quotientAndRemainder = coin.divide(penniesLeft);
        amounts.put(coin, quotientAndRemainder.quotient());
        penniesLeft = quotientAndRemainder.remainder();
    }
    return amounts;
}

Adding larger units of currency now simply comes down to adding them to the enum.

\$\endgroup\$
  • \$\begingroup\$ bowmore - Thank you for the valuable feedback! Your divide method inside the QuotientAndRemainder static class only pertains to pennies as does the minimalChange() method. How can I use this for other types of coins? Also, can you show me an example of how I can use these helper classes inside perhaps a main() method? \$\endgroup\$ – PacificNW_Lover Sep 9 '13 at 23:47
  • \$\begingroup\$ QuotientAndRemainder is a static class because I made it an inner class, which is not strictly necessary. divide() and minimalChange() pertain to an amount of pennies just as your original convert() method does. If your input would be an amount of coins then the Coin enum could also be given an 'int toPennies()' method. For my full code see ideone.com/jD666U \$\endgroup\$ – bowmore Sep 10 '13 at 4:47
0
\$\begingroup\$

Your solution is not very Object Oriented, but it works. This is a fine solution. There are many ways you could make the code less verbose, or more Object Oriented, but that is besides the point. I see nothing wrong with the way you implemented it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.