Encontré un fragmento de código que estaba escribiendo para la preparación de la entrevista hace unos meses.
Según el comentario que tenía, estaba intentando solucionar este problema:
Dado un valor en dólares en centavos (por ejemplo, 200 = 2 dólares, 1000 = 10 dólares), encuentre todas las combinaciones de monedas que forman el valor en dólares. Solo se permiten monedas de un centavo (1 ¢), monedas de cinco centavos (5 ¢), monedas de diez centavos (10 ¢) y veinticinco centavos (25 ¢).
Por ejemplo, si se dio 100, la respuesta debería ser:
4 quarter(s) 0 dime(s) 0 nickel(s) 0 pennies
3 quarter(s) 1 dime(s) 0 nickel(s) 15 pennies
etc.
Creo que esto se puede resolver tanto de forma iterativa como recursiva. Mi solución recursiva tiene bastantes errores y me preguntaba cómo otras personas resolverían este problema. La parte difícil de este problema fue hacerlo lo más eficiente posible.
fuente
code-golf
=> stackoverflow.com/questions/tagged/code-golfRespuestas:
Investigué esto una vez hace mucho tiempo, y puedes leer mi pequeño artículo al respecto . Aquí está la fuente de Mathematica .
Mediante el uso de funciones generadoras, puede obtener una solución de tiempo constante de forma cerrada al problema. Concrete Mathematics de Graham, Knuth y Patashnik es el libro para esto, y contiene una discusión bastante extensa del problema. Básicamente, se define un polinomio donde el coeficiente n es el número de formas de realizar cambios por n dólares.
Las páginas 4-5 del informe muestran cómo puede usar Mathematica (o cualquier otro sistema de álgebra computacional conveniente) para calcular la respuesta de 10 ^ 10 ^ 6 dólares en un par de segundos en tres líneas de código.
(Y esto fue lo suficientemente largo como para que sean un par de segundos en un Pentium de 75Mhz ...)
fuente
a
como el dominio def
peroa = {1,5,10,25,50,100}
. Debe haber un 5 en la lista de monedas de un centavo. De lo contrario, la redacción fue fantástica, ¡gracias!Nota : Esto solo muestra el número de formas.
Función Scala:
fuente
n1 * coins(0) + n2 * coins(1) + ... + nN * coins(N-1) = money
. Entonces, paramoney=0
ycoins=List(1,2,5,10)
el recuento de combinaciones(n1, n2, n3, n4)
es 1 y la solución es(0, 0, 0, 0)
.money == 0
perocoins.isEmpty
, no debería contar como un sol'n. Por lo tanto, el algoritmo se puede servir mejor si lacoins.isEmpty || money < 0
condición se cumple primero.Favorecería una solución recursiva. Tiene una lista de denominaciones, si la más pequeña puede dividir uniformemente cualquier cantidad de moneda restante, esto debería funcionar bien.
Básicamente, te mueves de las denominaciones más grandes a las más pequeñas.
Recursivamente,
Aquí está mi versión en Python de su problema declarado, por 200 centavos. Tengo 1463 maneras. Esta versión imprime todas las combinaciones y el total del recuento final.
fuente
denominations
no tiene1
como último valor. Puede agregar una pequeña cantidad de código alif
bloque más interno para solucionarlo (como describo en mi respuesta a la otra pregunta).Función Scala:
fuente
Aquí hay un código C ++ absolutamente sencillo para resolver el problema que requería que se mostraran todas las combinaciones.
Pero estoy bastante intrigado por el subproblema de simplemente calcular el número de combinaciones. Sospecho que hay una ecuación de forma cerrada para ello.
fuente
El problema secundario es un problema típico de programación dinámica.
fuente
El código usa Java para resolver este problema y también funciona ... Este método puede no ser una buena idea debido a demasiados bucles, pero en realidad es una forma sencilla.
fuente
Esta es una pregunta realmente antigua, pero se me ocurrió una solución recursiva en java que parecía más pequeña que todas las demás, así que aquí va:
Mejoras:
fuente
Sea C (i, J) el conjunto de combinaciones de hacer i centavos usando los valores del conjunto J.
Puede definir C como eso:
(primero (J) toma de manera determinista un elemento de un conjunto)
Resulta una función bastante recursiva ... y razonablemente eficiente si usa la memorización;)
fuente
semi-hack para sortear el problema de combinación única - forzar orden descendente:
Esto funcionará lento ya que no se memorizará, pero entiendes la idea.
fuente
fuente
Esta es mi respuesta en Python. No usa recursividad:
Salida de ejemplo
fuente
fuente
Ambos: iterar a través de todas las denominaciones de mayor a menor, tomar una de denominación, restar del total requerido, luego recurrir al resto (restringiendo las denominaciones disponibles para que sean iguales o menores al valor de iteración actual).
fuente
Si el sistema monetario lo permite, un simple algoritmo codicioso que toma la mayor cantidad posible de cada moneda, comenzando con la moneda de mayor valor.
De lo contrario, se requiere programación dinámica para encontrar una solución óptima rápidamente, ya que este problema es esencialmente el problema de la mochila .
Por ejemplo, si un sistema monetario tiene las monedas:,
{13, 8, 1}
la solución codiciosa haría el cambio por 24 as{13, 8, 1, 1, 1}
, pero la verdadera solución óptima es{8, 8, 8}
Editar: Pensé que estábamos haciendo cambios de manera óptima, sin enumerar todas las formas de hacer cambios por un dólar. Mi entrevista reciente preguntó cómo hacer cambios, así que salté antes de terminar de leer la pregunta.
fuente
Sé que esta es una pregunta muy antigua. Estaba buscando la respuesta adecuada y no pude encontrar nada que sea simple y satisfactorio. Me tomó algo de tiempo pero pude anotar algo.
Esta es una solución de JavaScript y usa recursividad.
fuente
En el lenguaje de programación Scala lo haría así:
fuente
Este es un algoritmo recursivo simple que toma un billete, luego toma un billete más pequeño de forma recursiva hasta que alcanza la suma, luego toma otro billete de la misma denominación y vuelve a recurrir. Consulte el resultado de muestra a continuación para ver una ilustración.
Imprime lo siguiente:
fuente
Duh, me siento estúpido ahora mismo. A continuación hay una solución demasiado complicada, que preservaré porque es una solución, después de todo. Una solución simple sería esta:
Aquí está la otra solución. Esta solución se basa en la observación de que cada moneda es un múltiplo de las demás, por lo que se pueden representar en términos de ellas.
Entonces, para 37 monedas, por ejemplo:
fuente
Esta entrada de blog resuelve este problema de mochila para las figuras de un cómic de XKCD . Un simple cambio en el
items
dict y elexactcost
valor arrojará todas las soluciones para su problema también.Si el problema fuera encontrar el cambio que usó el menor costo, entonces un algoritmo ingenuo y codicioso que usara la mayor parte de la moneda de mayor valor podría fallar para algunas combinaciones de monedas y cantidad objetivo. Por ejemplo, si hay monedas con valores 1, 3 y 4; y la cantidad objetivo es 6, entonces el algoritmo codicioso podría sugerir tres monedas de valor 4, 1 y 1 cuando es fácil ver que podría usar dos monedas de valor 3 cada una.
fuente
fuente
Encontré este código en el libro "Python para análisis de datos" de O'reily. Utiliza la implementación perezosa y la comparación int y supongo que se puede modificar para otras denominaciones usando decimales. ¡Déjame saber cómo te funciona!
fuente
Esta es la mejora de la respuesta de Zihan. La gran cantidad de bucles innecesarios se produce cuando la denominación es de solo 1 centavo.
Es intuitivo y no recursivo.
fuente
Solución java sencilla:
fuente
fuente
Aquí hay una función de C #:
Úselo así:
Imprime:
fuente
A continuación se muestra un programa de Python para encontrar todas las combinaciones de dinero. Esta es una solución de programación dinámica con orden (n) tiempo. El dinero es 1,5,10,25
Pasamos de la fila dinero 1 a la fila dinero 25 (4 filas). La fila de dinero 1 contiene el recuento si solo consideramos el dinero 1 al calcular el número de combinaciones. El dinero de la fila 5 produce cada columna tomando el recuento en el dinero de la fila r para el mismo dinero final más el recuento 5 anterior en su propia fila (posición actual menos 5). El dinero de la fila 10 usa el dinero de la fila 5, que contiene recuentos de 1,5 y suma en el recuento de 10 anteriores (posición actual menos 10). El dinero de la fila 25 usa el dinero de la fila 10, que contiene los recuentos del dinero de la fila 1,5,10 más el recuento de los 25 anteriores.
Por ejemplo, números [1] [12] = números [0] [12] + números [1] [7] (7 = 12-5) lo que da como resultado 3 = 1 + 2; números [3] [12] = números [2] [12] + números [3] [9] (-13 = 12-25) lo que resulta en 4 = 0 + 4, ya que -13 es menor que 0.
fuente
Solución Java
}
fuente
La siguiente solución java que también imprimirá las diferentes combinaciones. Fácil de comprender. La idea es
por suma 5
La solucion es
Si la suma restante en cada ciclo es menor que la denominación, es decir, si la suma restante 1 es menor que 2, entonces simplemente rompa el ciclo.
El código completo a continuación
Por favor corríjame en caso de errores
}
fuente
Aquí hay una solución basada en Python que usa recursividad y memorización, lo que resulta en una complejidad de O (mxn)
fuente