Work out change [cerrado]

10

Está escribiendo un programa para una caja registradora automática. El usuario necesita un cambio con la menor cantidad de monedas utilizadas. Escriba un programa que tome una cantidad (digamos $ 1.53) y proporcione un cambio en las denominaciones de los EE. UU., En este caso: 1 billete de un dólar, 1 x cincuenta centavos y 3 x un centavo. El programa más corto será el ganador. Puntos de bonificación por soportar otras monedas (es decir, denominaciones del Reino Unido) y monedas inusuales (1, 2, 3 centavos)

Tiene estas denominaciones de EE. UU .: 1 centavo, 5 centavos, 10 centavos, 25 centavos, 50 centavos, 1 dólar (billete o moneda), 2 dólares, 5 dólares, 10 dólares.

Tiene estas denominaciones del Reino Unido: 1 penique, 2 peniques, 5 peniques, 10 peniques, 20 peniques, 50 peniques, £ 1, £ 2, £ 5 (billete o moneda), £ 10.

Thomas O
fuente
3
Esto probablemente necesita un poco de aclaración. En primer lugar, probablemente debería especificar que queremos el menor número de monedas (lo que hace que la pregunta de bonificación sea un poco más interesante, por ejemplo, {1c, 49c, 50c} y 98c rompe un algoritmo ingenuo). En segundo lugar, un formato de entrada / salida es útil. Los detalles específicos sobre el manejo de valores imposibles de obtener (para monedas inventadas) ayudarían. Por último, es posible que desee enumerar las denominaciones aquí para que las personas no necesiten buscarlo si no están familiarizados con él.
Nabb
¿Cómo funcionan los puntos de bonificación? ¿Solo si hay un empate para el programa más corto?
gnibbler
@gnibber, citando a Stephen Fry: "[los puntos están] imparcialmente determinados por una consultoría de atención al cliente seleccionada demográficamente, desglosada por edad y sexo, es decir, yo".
Thomas O
Voy a pedir 50 centavos porque todavía no he visto una moneda de 50 centavos. Pero aparentemente existen: usmint.gov/kids/coinnews/circulating/50centCoin.cfm
Martin York

Respuestas:

2

Windows PowerShell, 108 111 117

Primer intento, sin golf hasta ahora:

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

Notas de implementación:

  1. Acepta la cantidad a devolver a través de la tubería.
  2. Acepta la lista de denominaciones de moneda a través de la línea de comando.
  3. La cantidad se puede dar con un signo de moneda; eso se eliminará (de hecho, cualquier cosa no numérica).
  4. La lista de denominaciones no necesita ser ordenada.
  5. El programa generará el mayor cambio más pequeño que la cantidad solicitada que se puede lograr con las denominaciones dadas, es decir, 1.5 para 1.53 si falta la moneda de 1 centavo.

Si 3 y 4 no necesitan ser satisfechos (es decir, yo controlo el formato de entrada ;-)), entonces el siguiente programa es suficiente (71):

$i=+"$input"
$args|%{$a=[math]::floor($i/$_)
if($a){$i-=$a*$_
"$a×$_"}}
Joey
fuente
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}  

O

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 más) da

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

Para otras denominaciones, simplemente cambie la tabla racional {10, ...., 5 / 100,1 / 100}

Dr. belisario
fuente
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");}

Más legible:

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");
}

Solo maneja moneda estadounidense. Toma el valor como un valor de coma flotante en la línea de comando (debe tener el 0 inicial para valores inferiores a 1 dólar). No acepta $ como parte del valor. Emite el número de cada tipo de billete / moneda en una línea separada. Por ejemplo, una entrada de 1.53 da como resultado:

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

Jonathan M Davis
fuente
1

Mathematica, 51 bytes

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

entrada

[1,53]

salida

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


Mathematica, 82 bytes - CON BONIFICACIÓN--

(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}]

salida

15 +15 +7 +0.2 +0.2 +0.2 +

J42161217
fuente
Umm, esta pregunta usa diferentes denominaciones del duplicado.
ericw31415
OP no especifica el formato de entrada / salida.
J42161217
Esta pregunta no usa billetes de 100 dólares y no hay bonificación.
ericw31415
ok.fixed y guardado algunos bytes! En cuanto a la bonificación, le solicito amablemente que lea la pregunta nuevamente. Especialmente la parte .. "Puntos de bonificación por apoyar otras monedas"
J42161217
¡Vaya, supongo que no lo vi entonces!
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")

Utiliza un algoritmo codicioso.

ericw31415
fuente