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?
2 Answers 2
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.
-
\$\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– PacificNW_Lover2013年09月09日 23:47:14 +00:00Commented Sep 9, 2013 at 23:47
-
\$\begingroup\$ QuotientAndRemainder is a static class because I made it an inner class, which is not strictly necessary.
divide()
andminimalChange()
pertain to an amount of pennies just as your originalconvert()
method does. If your input would be an amount of coins then theCoin
enum could also be given an 'int toPennies()' method. For my full code see ideone.com/jD666U \$\endgroup\$bowmore– bowmore2013年09月10日 04:47:40 +00:00Commented Sep 10, 2013 at 4:47
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.
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\$