Ao retirar dinheiro de um caixa eletrônico, solicitamos uma quantia e o caixa decide quantas notas de cada tipo disponível nós receberemos. O algoritmo que faz esta decisão é relativamente simples.
Abaixo coloco uma função que recebe uma solicitação de dinheiro e calcula quantas notas de 100, 50, 10, 5 e 1 serão retornadas ao solicitante:
--Retornando notas do caixa eletrônico
--Notas de 1, 5, 10, 50 e 100
CREATE OR REPLACE FUNCTION caixa_elet (pvalor integer) RETURNS text AS $$
DECLARE
sretorno text;
qnota1 integer;
qnota5 integer;
qnota10 integer;
qnota50 integer;
qnota100 integer;
BEGIN
sretorno := '';
qnota100 := (pvalor - (pvalor % 100))/100;
qnota50 := ((pvalor % 100) - (pvalor % 50)) /50;
qnota10 := ((pvalor % 50) - (pvalor % 10)) /10;
qnota5 := ((pvalor % 10) - (pvalor % 5)) /5;
qnota1 := ((pvalor % 5) - (pvalor % 1)) /1;
sretorno := 'Total: ' || pvalor || chr(10) || 'Notas de 100:' || qnota100 || chr(10) || 'Notas de 50:' || qnota50 || chr(10) || 'Notas de 10:' || qnota10 || chr(10) || 'Notas de 5:' || qnota5 || chr(10) || 'Notas de 1:' || qnota1;
RETURN sretorno; -- Retorna as linhas
END;
$$ LANGUAGE plpgsql;
Chamada da função e resultado apresentado:
SELECT caixa_elet(1078);
"Total: 1078
Notas de 100:10
Notas de 50:1
Notas de 10:2
Notas de 5:1
Notas de 1:3"
SELECT caixa_elet(2189);
"Total: 2189
Notas de 100:21
Notas de 50:1
Notas de 10:3
Notas de 5:1
Notas de 1:4"
Agora, gostaria de fazer algumas perguntas para os programadores de plantão:
- O código da função caixa_elet está correto?
- O código da função caixa_elet pode ser melhorado de que formas?
- Que alterações seriam necessárias para acrescentar notas de 20?
Aguardo suas contribuições nos comentários!
4 comentários:
Caro Cláudio,
Bem legal o algoritmo... a minha sugestão para incrementar a função seria um controle do número de notas disponíveis no caixa eletrônico, até mesmo para poder saber se é possível efetuar a transação.
Para o caso de adicionar a nota de R$20, ou até mesmo de R$2 creio que o mais adequado seria criar uma matriz multidimensional com as notas disponiveis e o valor que cada uma representa para poder fazer o cálculo das quantidades... e até mesmo a qtd de notas disponíveis é importante pois pode ser que nao tenhamos notas de 50 disponiveis e o usuário quer sacar 50 e teremos de disponibilizar 2 de 20 e 1 de 10, sempre dependendo da disponibilidade...
Podemos trocar mais alguma idéia e colocar em prática se vc desejar!
Abraço,
Fabrízio Mello
Oi, Fabrízio!
Realmente teríamos de acrescentar duas verificações:
- primeira, se a quantidade solicitada é maior que a quantidade armazenada no caixa
- segunda, se a quantidade de notas de cada tipo é maior que a quantidade de notas disponíveis.
Nice dispatch and this enter helped me alot in my college assignement. Thanks you for your information.
Este algoritmo funciona perfeitamente para as notas {1,5,10,50,100}. Adicionei outras possíveis variáveis {2,20} e aí surgiu o problema de apropriação de notas que não funcionou. Tomei a liberdade de criar uma nova função (talvez não com a mesma performance da função inicial) porém facilmente adaptável às possíveis notas existentes em determinada Economia.
Para tanto, usei as possibilidades existentes em nossa Economia (desde moedas de R$ 0,01 até notas de R$ 100,00) e funcinou perfeitamente.
CREATE OR REPLACE FUNCTION calcula_moeda (valor NUMERIC) RETURNS text AS $$ DECLARE
notas NUMERIC[12];
quantidade INTEGER[12];
processado NUMERIC;
retorno TEXT;
BEGIN
notas[0] := 0.01;
notas[1] := 0.05;
notas[2] := 0.10;
notas[3] := 0.25;
notas[4] := 0.50;
notas[5] := 1.00;
notas[6] := 2.00;
notas[7] := 5.00;
notas[8] := 10.00;
notas[9] := 20.00;
notas[10] := 50.00;
notas[11] := 100.00;
processado := 0.00;
retorno := 'Total: ' || valor || chr(10) || '----------------------------------';
FOR laco IN REVERSE 11..0 LOOP
quantidade[laco] := 0;
quantidade[laco] := CAST((valor - processado - ((valor - processado) % notas[laco])) / notas[laco] AS INTEGER);
processado := processado + (quantidade[laco] * notas[laco]);
retorno := retorno || chr(10) || 'Especie de ' || notas[laco] || ': ' || quantidade[laco] || ' unidade(s)';
END LOOP;
RETURN retorno;
END;
$$ LANGUAGE plpgsql;
Podemos ver em um exemplo de execução da função:
SELECT calcula_moeda(193.83);
Total: 193.83
----------------------------------
Especie de 100.00: 1 unidade(s)
Especie de 50.00: 1 unidade(s)
Especie de 20.00: 2 unidade(s)
Especie de 10.00: 0 unidade(s)
Especie de 5.00: 0 unidade(s)
Especie de 2.00: 1 unidade(s)
Especie de 1.00: 1 unidade(s)
Especie de 0.50: 1 unidade(s)
Especie de 0.25: 1 unidade(s)
Especie de 0.10: 0 unidade(s)
Especie de 0.05: 1 unidade(s)
Especie de 0.01: 3 unidade(s)
Postar um comentário