Ver Mensaje Individual
  #4 (permalink)  
Antiguo 13/11/2006, 22:09
califa010
 
Fecha de Ingreso: enero-2006
Ubicación: Buenos Aires, Argentina
Mensajes: 299
Antigüedad: 18 años, 4 meses
Puntos: 5
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 '&nbsp;&nbsp;&nbsp;&nbsp;';

$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 && $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

Última edición por califa010; 13/11/2006 a las 22:26