Convenience Store (Code Challenge)

  • Page Owner: Not Set
  • Last Reviewed: 2019-09-27

Convenience Store

Given a total due and an array representing the amount of change in your pocket, determine whether or not you are able to pay for the item. Change will always be represented in the following order: quarters, dimes, nickels, pennies.

To illustrate: changeEnough([25, 20, 5, 0], 4.25) should yield true, since having 25 quarters, 20 dimes, 5 nickels and 0 pennies gives you 6.25 + 2 + .25 + 0 = 8.50.

Examples

changeEnough([2, 100, 0, 0], 14.11) ➞ false

changeEnough([0, 0, 20, 5], 0.75) ➞ true

changeEnough([30, 40, 20, 5], 12.55) ➞ true

changeEnough([10, 0, 0, 50], 3.85) ➞ false

changeEnough([1, 0, 5, 219], 19.99) ➞ false

Notes

quarter: 25 cents / $0.25
dime: 10 cents / $0.10
nickel: 5 cents / $0.05
penny: 1 cent / $0.01

Tests

changeEnough([2, 100, 0, 0], 14.11) == false
changeEnough([2, 100, 0, 0], 14.11) == false
changeEnough([0, 0, 20, 5], 0.75) == true
changeEnough([30, 40, 20, 5], 12.55) == true
changeEnough([10, 0, 0, 50], 13.85) == false
changeEnough([1, 0, 5, 219], 19.99) == false
changeEnough([1, 0, 2555, 219], 127.75) == true
changeEnough([1, 335, 0, 219], 35.21) == true

Additional Posts

This didn't seem easy until I actually started typing it. I'm going to mark it as a spoiler, since I answered really early. That being said. 102 characters.

! changeEnough = (x, y) => x.map((x, i) => x * [.25, .10, .05, .01][i]).reduce((a, c) => a += c, 0) >= y

This one seemed simple. I wrote it for maximum clarity.

void Main()
{
	ChangeEnough(new[] { 2, 100, 0, 0 }, 14.11).Dump(); // ➞ false
	ChangeEnough(new[] { 0, 0, 20, 5 }, 0.75).Dump(); //true
	ChangeEnough(new[] { 30, 40, 20, 5 }, 12.55).Dump(); // ➞ true
	ChangeEnough(new[] { 10, 0, 0, 50 }, 3.85).Dump(); // ➞ false
	ChangeEnough(new[] { 1, 0, 5, 219 }, 19.99).Dump(); // ➞ false
}

public bool ChangeEnough (IList<int> change, double amount)
{
	if(change.Count() != 4)
	{
		throw new ArgumentException("Change list must have exactly four elements.");
	}
	
	const double QUARTER = .25;
	const double DIME = .1;
	const double NICKEL = .05;
	const double PENNY = .01;
	
	return (change[0] * QUARTER) + (change[1] * DIME) + (change[2] * NICKEL) + (change[3] * PENNY) >= amount;
}

Edit

Inspired by John, I rewrote it as an extension method, using a mapping function.

(I only learned a few months ago that the Select LINQ extension can take a second parameter which represents the index of the element.)

new[] { 2, 100, 0, 0 }.IsEnoughFor(14.11).Dump(); // ➞ false
new[] { 0, 0, 20, 5 }.IsEnoughFor(0.75).Dump(); //true
new[] { 30, 40, 20, 5 }.IsEnoughFor(12.55).Dump(); // ➞ true
new[] { 10, 0, 0, 50 }.IsEnoughFor(3.85).Dump(); // ➞ false
new[] { 1, 0, 5, 219 }.IsEnoughFor(19.99).Dump(); // ➞ false

public static class Extensions
{
	public static bool IsEnoughFor(this IList<int> change, double amount)
	{
		return change.Select((c, i) => c * new double[] { .25, .1, .05, .01 }[i]).Sum() >= amount;
	}
}

I decided to try it without a lookup table, using just the maths. The formula could probably be simplified but I'm just not that smart.

let changeEnough = (coins, change) => coins.map((count, x) =>count * (Math.pow((3 - x) + 1 + Math.floor((3 - x) / 3), 2) + Math.abs((((3 - x) + 1) % 3) - 1))).reduce((acc, val) => acc + val, 0) >= (change * 100);