Buenas, en ese caso, lo que tendrias que hacer es recorrer cada una de las denominaciones, de la mayor a la menor. En cada vuelta, deberías restar el valor de esa denominación, si todavía quedan tickets disponibles y si el valor del ticket no es mayor a lo que falta para cubrir el total. Y básicamente, es eso. Necesitás un par de variables de control y algunos contadores y la base del esquema estaría.
Un ejemplo de esto aplicado (lo probé con un par de valores y funciona, pero lo hice al vuelo así que puede tener algunos errores o puede no ser lo más óptimo; el $montoMaximo te convendría tomarlo dinámicamente)
Código PHP:
<?php
$tickets[] = array('valor'=>1,'cantidad'=>10); // 10
$tickets[] = array('valor'=>2,'cantidad'=>10); // 20
$tickets[] = array('valor'=>5,'cantidad'=>10); // 50
$tickets[] = array('valor'=>10,'cantidad'=>10); // 100
$tickets[] = array('valor'=>20,'cantidad'=>10); // 200
$tickets[] = array('valor'=>50,'cantidad'=>10); // 500
$montoMaximo = 890;
$montoRequerido = 538;
$checkSuma = 0;
$tab = ' ';
$resultado = array();
for ($i=count($tickets)-1;$i>=0;$i--) {
$arrTicketActual = $tickets[$i];
$cantidad = $arrTicketActual['cantidad'];
$valor = $arrTicketActual['valor'];
// echo "VALOR::$valor<br>";
$cantTicketsValor = 0;
// mientras:
// 1) haya tickets
// 2) el valor del ticket sea menor o igual a lo que falta para completar lo pedido
// 3) lo acumulado sea menor a lo pedido
while ($cantidad > 0 && $montoRequerido - $checkSuma >= $valor && $checkSuma < $montoRequerido) {
$checkSuma += $valor;
$cantidad--;
$cantTicketsValor++;
// echo "$tab" . "CANTIDAD: $cantidad <br>";
}
if ($cantTicketsValor > 0) {
$resultado[] = array('valor'=>$valor,'cantidad'=>$cantTicketsValor);
}
}
if ($checkSuma !== $montoRequerido) {
echo "NO SE PUDO ENTREGAR LA SUMA PEDIDA<br>";
echo "suma entregada:$checkSuma<br>";
echo "suma pedida:$montoRequerido<br>";
} else {
echo "OK:<br>";
foreach($resultado as $r) {
echo "$tab" . "Valor Ticket:{$r['valor']}<br>";
echo "$tab" . "Cantidad Ticket:{$r['cantidad']}<br>";
}
}
/**
echo '<pre>';
print_r($resultado);
echo '</pre>';
*/
?>
Un tema: Tendrías que ver si necesitás más validaciones y, si estás usando base de datos, tené en cuenta que no va a ser realmente "seguro" a menos que uses transacciones (creo que en mysql se puede hacer a partir de la versión 5, este artículo explica el problema --en inglés--:
http://www.samspublishing.com/articl...p=29312&rl=1); La idea sería bloquear las tablas mientras estás haciendo las cuentas. Podría pasar (al menos en teoría, y creo que tendrías que tener bastante mala leche) una situación como la siguiente. Supongamos que el usuario A pide $100. Hay $150 en total, todos tickets de $50 (para simplificar). Mientras estás haciendo los cálculos, entra el usuario B y pide también $100. Pero la consulta a la base va a devolver que hay $150 disponibles, porque como está procesándose, el pedido de A no hizo ninguna actualización en la base.
Entonces, terminás de calcular el pedido A, le das $100 y descontás 2 tickets de la base. Pero cuando termines de calcular el pedido de B, también le vas a dar $100, cuando en realidad sólo te quedan $50.
Bueno, todo esto en realidad es hilar más bien fino, si no estás haciendo algo tipo home banking o por el estilo, un error de este tipo tal vez sea un probabilidad (baja) aceptable.
Suerte
Califa