Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Daniel Ribeiro

[DESAFIO] Caixa Eletrônico

Recommended Posts

Fala pessoal! Como estão?

 

Primeiramente, gostaria de me desculpar com todos aqueles que prestaram o seu precioso tempo para participar do desafio que propus, visto que estive ausente por um tempo relativamente grande devido a questões profissionais.

 

Estou de volta e aqui está o meu código inicial para a resolução do problema proposto pelo desafio:

 

 

<?php

class ATM {

/**
 * Error message.
 */
const ERROR_AVAILABILITY = 'There are no bills available to reach the amount of cash requested';

/**
 * Bills available on the ATM.
 *
 * @var array
 */
private $bills = array(
	1 => 99999 ,
	2 => 99999 ,
	5 => 99999 ,
	10 => 99999 ,
	20 => 99999 ,
	50 => 99999 ,
	100 => 99999
);

/**
 * Check if the array of bills has a odd number bill.
 *
 * @param boolean $returnBill [optional] If set to true, the return value
 * will be the bill itself as an integer number.
 * @return boolean
 */
public function hasOddBill( $returnBill = false ) {
	if( array_key_exists( 1 , $this->bills ) ) {
		if( $this->bills[1] != 0 ) {
			return ( $returnBill ) ? ( int ) 1 : ( bool ) true;
		} else {
			return false;
		}
	} else if( array_key_exists( 5 , $this->bills ) ) {
		if( $this->bills[5] != 0 ) {
			return ( $returnBill ) ? ( int ) 5 : ( bool ) true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

/**
 * Returns an array with all the bills necessary to reach the requested
 * amount of cash.
 *
 * @param integer $amountOfCash
 * @return array
 */
public function getDistribution( $amountOfCash ) {
	if( ( ( $amountOfCash % 2 ) != 0 ) ) {
		if( ( $this->hasOddBill() == false )
				|| ( ( $this->hasOddBill( true ) != 1 ) && ( $amountOfCash == 1 || $amountOfCash == 3 ) ) ) {
			return trigger_error( self::ERROR_AVAILABILITY , E_USER_ERROR );
		}
	}

	$distribution = array( );

	foreach( array_reverse( $this->bills , true ) as $bill => $availability ) {
		if( ( $bill > $amountOfCash ) || ( $availability == 0 ) ) continue;

		while( ( $amountOfCash - $bill ) >= 0 ) {
			if( ( ( $amountOfCash - $bill ) == 1 ) || ( ( $amountOfCash - $bill ) == 3 ) ) {
				if( $this->hasOddBill( true ) != 1 ) break;
			}

			$amountOfCash -= $bill;
			$distribution[$bill]++;
		}
	}

	if( ( empty( $distribution ) ) || ( $amountOfCash > 0 ) ) {
		return trigger_error( self::ERROR_AVAILABILITY , E_USER_ERROR );
	}

	return $distribution;
}

}

 

Sobre o código, poderão perceber que o algorítimo resolve o problema proposto com o mínimo de dependência à implementação.

 

Como dito anteriormente, todas as questões inicialmente propostas estão sendo resolvidas neste código, como a questão de adição ou remoção de notas do array inicial.

 

Para testar, basta descomentar a linha que adiciona a nota de 1 ao array, para ver como o algorítimo se comporta.

 

A ideia agora é seguirmos em frente com a implementação do desafio, extendendo-o a novas fronteiras.

 

Espero que ainda tenha gente interessada! Um abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Uhn... Legal, mas tá disparando Notice. Exemplo (com as notas originais):

 

$atm = new ATM ();
print_r ( $atm->getDistribution ( 6 ) );

Saída:

Notice: Undefined offset: 2 in C:\Program Files (x86)\Zend\Apache2\htdocs\forum\array.php on line 69

Array ( [2] => 3 )

 

Além disto, quando não dá pra fazer a distribuição das notas, ele não dá nenhum erro. Por exemplo, se tirar a nota de dois e tentar sacar os mesmos R$ 6,00, a saída é:

 

Array ( )

 

Não está errado, mas achei estranho.

 

Enfim, resolve o problema, mas está disparando Notices...

 

Carlos Eduardo

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Matias

 

Saquei... a tentativa de sacar o valor de 6 sem a nota de 2 foi algo que realmente não havia pensado. Neste caso, basta realizar a simples verificação, ao final do script, se o array está vazio. Se estiver é porque não foi possível entregar a quantia com as notas disponíveis.

 

Sobre os notices, não costumo me preocupar muito com eles. Aliás, por estar sem o error_reporting setado aqui, acabei nem percebendo eles.

 

Não vejo a necessidade de alterar o código para evitar isso. Mas honestamente, porque não vejo problema com o que ele está notificando.

 

Você acha que isso pode causar um problema? Abraço.

 

OBS: Código corrigido no post anterior.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Saber se os Notices vão atrapalhar ou não, só comparando a versão "errada" com a versão corrigida, isto é, sem eles e ver se em situações identicas há diferenças no resultado.

 

Sobre o código retornar um array vazio que deva ser condicionado para determinação de um transação perfeita/possível ou não, vejo isso como sendo o mesmíssimo caso do meu código, quando há a indisponibilidade da nota de um real.

 

Quero dizer, essa "comparação" quem faria seria o próprio usuário, após ter recebido um grande monte de nada pelo ATM.

 

Já no meu caso, mesmo que tapado vá num caixa que é lógico e evidente que não será capaz de efetuar o saque perfeito, há, de qualquer forma, a entrega de pelo menos alguma coisa.

 

Dito isso, basta comprovar com seu trigger_error() que aborta a operação sem ao menos tentar (ATM Preguiçoso :P )

 

O seu código resolve o problema (à la Gerson), masnão é bem um ATM, apesar de pensar parcialmebte como um.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Saber se os Notices vão atrapalhar ou não, só comparando a versão "errada" com a versão corrigida, isto é, sem eles e ver se em situações identicas há diferenças no resultado.

 

Sobre o código retornar um array vazio que deva ser condicionado para determinação de um transação perfeita/possível ou não, vejo isso como sendo o mesmíssimo caso do meu código, quando há a indisponibilidade da nota de um real.

 

Quero dizer, essa "comparação" quem faria seria o próprio usuário, após ter recebido um grande monte de nada pelo ATM.

 

Já no meu caso, mesmo que tapado vá num caixa que é lógico e evidente que não será capaz de efetuar o saque perfeito, há, de qualquer forma, a entrega de pelo menos alguma coisa.

 

Dito isso, basta comprovar com seu trigger_error() que aborta a operação sem ao menos tentar (ATM Preguiçoso :P )

 

O seu código resolve o problema (à la Gerson), masnão é bem um ATM, apesar de pensar parcialmebte como um.

 

Bruno, sobre os notices, não me referi ao notice genérico em sí e o que ele representa, mas sim ao notice específico que está sendo exibido para o meu código. Quis dizer que não me preocupo com a razão pela qual o notice está sendo exibido. Entendeu?

 

Sobre o código retornar um array vazio, não está retornando. Isso era apenas um erro que esqueci de corrigir antes de postar. Teste você mesmo, removendo a nota de um real, ou qualquer nota que desejar, para ver como o algorítimo se comporta.

 

Utilizo um trigger_error() porque é um algorítimo pensado para resolver um problema específico, "solto", independente, não necessariamente conectado à realidade. Isso se comprova ao analisarmos os ATM reais, que já tem as quantias exatas para saque, sem permitir ao usuário sacar uma quantia qualquer.

 

Esse desafio foi proposto para resolvermos um simples problema de lógica, não para implementarmos um ATM que saiba como responder a diversas requisições de um usuário qualquer.

 

E o meu código resolveu o problema, juntamente com o código do Matias, se não me engano.

 

Gostaria de ver o pessoal tentando resolver esse problema de lógica também nos códigos já iniciados mas não terminados para o escopo do desafio.

 

Um abraço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não querendo ressuscitar, mas já ressuscitando:

 

<?php

class ATM {

private $notas = array( 2, 5, 10, 20, 50, 100 );
private $notas_usadas = array( 0, 0, 0, 0, 0, 0 );
private $notas_disponiveis = array( 80, 100, 400, 60, 90, 70 );

function __construct( $valor ) {
	$this->valor = $valor;
	$this->valor_final = 0;
	$this->saque();
}

function __destruct() {
	$this->valor;
	$this->valor_final;
}

function saque() {
	for( $handle = ( sizeof( $this->notas ) - 1 ); $handle >= 0; $handle -- ) {
		for( $i = 1; ( $this->valor_final + $this->notas[$handle] ) <= $this->valor; $i ++ ) {
			$this->valor_final += $this->notas[$handle];
			$this->notas_usadas[$handle] += 1;
			if( $i == $this->notas_disponiveis[$handle] ) break;
		}
	}
$this->resultado();
}

function resultado() {
	if( $this->valor_final < $this->valor ) {
		echo "O valor solicitado não corresponde com as notas disponíveis.";
	} elseif( $this->valor_final == $this->valor ) {
		print ("Valor retirado: ".$this->valor_final.". Valor solicitado: ".$this->valor.".\nNotas usadas:\nR$100,00 -> ".$this->notas_usadas[5]."\nR$50,00 -> ".$this->notas_usadas[4]."\nR$20,00 -> ".$this->notas_usadas[3]."\nR$10,00 -> ".$this->notas_usadas[2]."\nR$5,00 -> ".$this->notas_usadas[1]."\nR$2,00 -> ".$this->notas_usadas[0]);
	} else {
		echo "Erro inesperado.";
	}
	return;
}
}

?>

 

Código básico, sou iniciante, acho que não preciso comentar as linhas para vocês entenderem.

 

PS: Sim, eu aprendi a usar __construct e __destruct nos tutoriais que eu arranjei, não faço classes sem essas funções. /bj

Compartilhar este post


Link para o post
Compartilhar em outros sites

De uma maneira simples:

<?php
function notas($valor) {
	$money = $valor; //Salva nova variável chamada money
	$i = $a = $soma = 0; //Constantes
	$notas = array(50,100,20,10,2,5); //Notas disponíveis para saque
	rsort($notas); //Coloca array em ordem descrescente
	while ($i < count($notas)) {
		$qtd[$i] = floor($valor/$notas[$i]); //Menor quantidade de notas da maior possível
		$soma += $qtd[$i]; //Soma a quantidade de notas a cada loop
		$valor = $valor-($qtd[$i]*$notas[$i]); //Subtrai a quantidade de dinheiro já calculada do valor
		$i++;
	}
	$money = number_format($money, 2, ",", ".");

	/* Exibe resultado */
	echo "A quantidade mí­nima de notas para sacar R$ $money é de $soma, sendo:";
	echo "<ul>";
	while ($a < count($notas)) {
		echo "<li>R$ ".number_format($notas[$a], 2, ",", ".")." -> $qtd[$a]</li>";
		$a++;
	}
	echo "</ul>";
}
notas(1234);
?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Opa Galera segue meu código :thumbsup:

 

<?php
class atm{
private $valorescaixa = array('2'=>999999, '5'=>999999, '10'=>999999, '20'=>999999, '50'=>999999, '100'=>999999);
private $valoresrequisitados =  array('2'=>0, '5'=>0, '10'=>0, '20'=>0, '50'=>0, '100'=>0);
private $v=0;
public $vsaque=0;


public function __construct($vsaque) {
	$this->vsaque=$vsaque;
   }							

function testev(){
	$this->v=$this->vsaque;
	if($this->valorescaixa['100']>0 and $this->v>=100){
		$this->valoresrequisitados['100']=(int)($this->v/100);	
		$this->v=$this->v%100;	
	}
	if($this->valorescaixa['50']>0 and $this->v>=50){
		$this->valoresrequisitados['50']=(Int)($this->v/50);	
		$this->v=$this->v%50;	
	}
	if($this->valorescaixa['20']>0 and $this->v>=20){
		$this->valoresrequisitados['20']=(int)($this->v/20);	
		$this->v=$this->v%20;	
	}
	if($this->valorescaixa['10']>0 and $this->v>=10){
		$this->valoresrequisitados['10']=(int)($this->v/10);	
		$this->v=$this->v%10;	
	}
	if($this->valorescaixa['5']>0 and $this->v>=5 and (($this->v%5)%2)==0){
		$this->valoresrequisitados['5']=(int)($this->v/5);	
		$this->v=$this->v%5;	
	}
	if($this->valorescaixa['2']>0 and $this->v>=2){
		echo $this->v;
		$this->valoresrequisitados['2']=(int)($this->v/2);	
		$this->v=$this->v%2;	
	}
	$this->validar();

}
private function validar(){
	if($this->v!=0) die('nao e possivel retirar esse valor Temos somente notata de 2,5,10,50,100');
	if($this->valoresrequisitados['100']>$this->valorescaixa['100'] or $this->valoresrequisitados['50']>$this->valorescaixa['50'] or
	$this->valoresrequisitados['20']>$this->valorescaixa['20'] or $this->valoresrequisitados['10']>$this->valorescaixa['10'] or
	$this->valoresrequisitados['5']>$this->valorescaixa['5'] or $this->valoresrequisitados['2']>$this->valorescaixa['2']) die('Não é possivel retirar esse valor NOTAS INSUFICIENTEs');
	else{
		$this->sucesso();	
	}
}
private function sucesso(){
	$this->valorescaixa['100']-=$this->valoresrequisitados['100'];
	$this->valorescaixa['50']-=$this->valoresrequisitados['50'];
	$this->valorescaixa['20']-=$this->valoresrequisitados['20'];
	$this->valorescaixa['10']-=$this->valoresrequisitados['10'];
	$this->valorescaixa['5']-=$this->valoresrequisitados['5'];
	$this->valorescaixa['2']-=$this->valoresrequisitados['2'];

	echo "Operacao realizada com sucesso<br />";
	echo "<br /> Notas de 100 =".$this->valoresrequisitados['100'];
	echo "<br /> Notas de 50 =".$this->valoresrequisitados['50'];
	echo "<br /> Notas de 20 =".$this->valoresrequisitados['20'];
	echo "<br /> Notas de 10 =".$this->valoresrequisitados['10'];
	echo "<br /> Notas de 5 =".$this->valoresrequisitados['5'];
	echo "<br /> Notas de 2 =".$this->valoresrequisitados['2'];

}
}

$caixa = new atm(1923899);
$caixa->testev();
unset($caixa);

?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.