Skip to content

Instantly share code, notes, and snippets.

@enapupe
Created October 3, 2012 15:01
Show Gist options
  • Save enapupe/3827407 to your computer and use it in GitHub Desktop.
Save enapupe/3827407 to your computer and use it in GitHub Desktop.
<?php
namespace Obiz\Challenges\CashMachine;
class WithdrawException extends \Exception {
}
class CashMachine {
/**
* Available bill values in the ATM. Consider quantities are unlimited.
*/
private $bills = array(2, 5, 10, 20, 50, 100);
private $money_left;
private $cash = array();
function __construct() {
rsort($this->bills);
}
/**
* Returns the bills that should be distributed for a given withdraw amount and available bills,
* MINIMIZING the total number of distributed bills.
* Ex: getBills(72) => array(2 => 1, 20 => 1, 50 => 1).
*
* @param int $withdrawAmount How much we want to withdraw from the ATM
* @throws WithdrawException if the exact amount cannot be gathered with the available bills.
* @return array Associative array representing the bills that should be distributed by the cash machine.
*/
public function getBills($withdrawAmount) {
$this->cash = array();
$this->money_left = $withdrawAmount;
while ($this->money_left > 0) {
if ($this->money_left < min($this->bills)) {
throw new WithdrawException('This amount cannot be paid.');
}
$bill = $this->configureBills();
$this->cash[] = $bill;
$this->money_left -= $bill;
}
return array_count_values($this->cash);
}
private function configureBills() {
foreach ($this->bills as $bill) {
$division = $this->money_left / $bill;
$rest = $this->money_left % $bill;
if ( ($division >= 1) && ( $rest > (min($this->bills)+1) || ($rest === min($this->bills)) || ($rest === 0) ) ) {
return $bill;
}
}
return min($this->bills);
}
}
$atm = new CashMachine;
print_r($atm->getBills(52));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment