Exercício de mudança [fechado]

10

Você está escrevendo um programa para uma caixa registradora automática. O usuário precisa mudar com o menor número de moedas usadas. Escreva um programa que receba uma quantia (digamos US $ 1,53) e altere as denominações americanas - neste caso: 1 x uma nota de dólar, 1 x cinquenta centavos e 3 x um centavo. O programa mais curto será o vencedor. Pontos de bônus por apoiar outras moedas (ou seja, denominações do Reino Unido) e moedas incomuns (1, 2, 3 centavos?)

Você tem essas denominações americanas: 1 centavo, 5 centavos, 10 centavos, 25 centavos, 50 centavos, 1 dólar (nota ou moeda), 2 dólares, 5 dólares, 10 dólares.

Você tem estas denominações do Reino Unido: 1 centavo, 2 centavos, 5 centavos, 10 centavos, 20 centavos, 50 centavos, £ 1, £ 2, £ 5 (nota ou moeda), £ 10.

Thomas O
fonte
3
Provavelmente isso precisa de um pouco de esclarecimento. Primeiro, você provavelmente deve especificar que queremos o menor número de moedas (o que torna a questão do bônus um pouco mais interessante, por exemplo, {1c, 49c, 50c} e 98c quebra um algoritmo ingênuo). Em segundo lugar, um formato de entrada / saída é útil. Informações específicas sobre como lidar com valores inatingíveis (para moedas inventadas) ajudariam. Por fim - convém listar as denominações aqui para que as pessoas não precisem procurar se não estiverem familiarizadas.
Nabb
Como funcionam os pontos de bônus? Apenas se houver um empate para o programa mais curto?
Gnibbler
@gnibber, citando Stephen Fry: "[os pontos] são determinados imparcialmente por uma consultoria de atendimento ao cliente selecionada demograficamente, dividida por idade e sexo - ou seja, eu".
Thomas O
Vou pedir 50c, pois ainda não vi uma moeda de 50 centavos. Mas, aparentemente, eles existem: usmint.gov/kids/coinnews/circulating/50centCoin.cfm
Martin York

Respostas:

2

Windows PowerShell, 108 111 117

Primeira tentativa, até agora não destruída:

$i=+("$input"-replace'[^\d.]')
$args|%{0d+$_}|sort -des|%{$a=[math]::floor($i/$_)
if($a){$i-=$a*$_
"$a×$_"}}

Notas de implementação:

  1. Aceita a quantidade a retornar através do pipeline
  2. Aceita a lista de denominações de moeda via linha de comando
  3. A quantidade pode ser fornecida com um sinal de moeda; isso será retirado (de fato, qualquer coisa não numérica).
  4. A lista de denominações não precisa ser classificada.
  5. O programa produzirá a maior mudança menor que a quantidade solicitada alcançável com as denominações especificadas, ou seja, 1,5 para 1,53 se a moeda de 1 centavo estiver ausente.

Se 3 e 4 não precisam ser satisfeitos (ou seja, eu controlo o formato de entrada ;-)), o seguinte programa é suficiente (71):

$i=+"$input"
$args|%{$a=[math]::floor($i/$_)
if($a){$i-=$a*$_
"$a×$_"}}
Joey
fonte
2

Mathematica: 110 caracteres

Sort[IntegerPartitions[Rationalize@#,Infinity,{10,5,2,1,1/2,1/4,1/10,5/100,1/100}],
    Length@#1<Length@#2&][[1]]&  

Uso

%[0.98]  
{1/100, 1/100, 1/100, 1/10, 1/10, 1/4, 1/2}  

Ou

Tally@Sort[IntegerPartitions[Rationalize@#,Infinity,
                             {10,5,2,1,1/2,1/4,1/10,5/100,1/100}],
     Length@#1<Length@#2&][[1]]&  

(6 caracteres a mais) dá

{{1/100, 3}, {1/10, 2}, {1/4, 1}, {1/2, 1}}

Para outras denominações, basta alterar a tabela racional {10, ...., 5 / 100,1 / 100}

Dr. belisarius
fonte
2

D: 225 caracteres

import std.algorithm,std.conv,std.stdio;void main(string[]args){auto m=args[1].findSplit(".");void p(T,S)(T t,T u,S s){foreach(v;[u,10,5,1]){writefln("%s %s%s",t/v,v,s);t-=(t/v)*v;}}p(to!int(m[0]),20,"");p(to!int(m[2]),25,"/100");}

Mais legivelmente:

import std.algorithm,std.conv,std.stdio;

void main(string[] a)
{
    auto m = a[1].findSplit(".");

    void p(T, S)(T t, T u, S s)
    {
        foreach(v; [u, 10, 5, 1])
        {
            writefln("%s %s%s", t / v, v, s);
            t -= (t / v) * v;
        }
    }

    p(to!int(m[0]), 20, "");
    p(to!int(m[2]), 25, "/100");
}

Lida apenas com moeda dos EUA. Toma o valor como um valor de ponto flutuante na linha de comando (deve ter o 0 inicial para valores abaixo de 1 dólar). Não aceita $ como parte do valor. Emite o número de cada tipo de nota / moeda em uma linha separada. Por exemplo, uma entrada de 1,53 resulta em:

0 20
0 10
0 5
1 1
2 25/100
0 10/100
0 5/100
3 1/100

Jonathan M Davis
fonte
1

Mathematica, 51 bytes

#~NumberDecompose~{10,5,2,1,.5,.25,.1,.05,.01}&

entrada

[1,53]

resultado

{0, 0, 0, 1, 1, 0, 0, 0, 3.}


Mathematica, 82 bytes - COM BÔNUS--

(s=#~NumberDecompose~#2;Row@Flatten@Table[Table[#2[[i]]"+",s[[i]]],{i,Length@s}])&

Entrada

[37,6, {15, 7, 2,5, 1, 0,88, 0,2, 0,01}]

resultado

15 +15 +7 +0,2 +0,2 +0,2 +

J42161217
fonte
Hum, esta pergunta usa diferentes denominações da duplicata.
ericw31415
O OP não especifica o formato de entrada / saída.
J42161217
Esta pergunta não usa notas de 100 dólares e não há bônus.
ericw31415
ok.fixed e salvou alguns bytes! Quanto ao bônus, solicito que você leia a pergunta novamente. Especialmente a parte .. "Pontos de bônus por apoiar outras moedas"
J42161217 17/17
Opa, acho que não vi isso então!
ericw31415
1

Javascript, 84 83 bytes

(n,v=[10,5,2,1,.5,.25,.1,.05,.01],l=[])=>{for(i in v)l[i]=n/v[i]|0,n%=v[i];return l}

(n,v=[10,5,2,1,.5,.25,.1,.05,.01],l=[])=>eval("for(i in v)l[i]=n/v[i]|0,n%=v[i];l")

Usa um algoritmo ganancioso.

ericw31415
fonte