Haskell (Lambdabot), 92 85 bytes
x#y|x==y=[[x]]|1>0=(guard(mod x y<1)>>(y:).map(y*)<$>div x y#2)++x#(y+1)
map(1:).(#2)
Necesita Lambdabot Haskell ya que guard
requiereControl.Monad
ser importado. La función principal es una función anónima, que me han dicho que está permitida y elimina un par de bytes.
Gracias a Laikoni por guardar siete bytes.
Explicación:
Las mónadas son muy útiles.
x # y
Esta es nuestra función recursiva que hace todo el trabajo real. x
es el número sobre el que estamos acumulando (el producto de los divisores que permanecen en el valor), y y
es el siguiente número en el que deberíamos intentar dividirlo.
| x == y = [[x]]
Si x
es igual, y
entonces hemos terminado de recurrir. Solo x
úselo como el final de la cadena actual de gozinta y devuélvalo.
| 1 > 0 =
Haskell golf-ism para "Verdadero". Es decir, este es el caso predeterminado.
(guard (mod x y < 1) >>
Estamos operando dentro de la lista mónada ahora. Dentro de la lista de mónadas, tenemos la capacidad de tomar múltiples decisiones al mismo tiempo. Esto es muy útil cuando se encuentra "todo lo posible" de algo por agotamiento. La guard
declaración dice "solo considere la siguiente opción si una condición es verdadera". En este caso, solo considere la siguiente opción si se y
divide x
.
(y:) . map (y *) <$> div x y#2)
Si se y
divide x
, tenemos la opción de agregar y
a la cadena de gozinta. En este caso, llame recursivamente (#)
, comenzando de nuevo y = 2
con x
igual a x / y
, ya que queremos "factorizar" lo que y
acabamos de agregar a la cadena. Luego, cualquiera que sea el resultado de esta llamada recursiva, multiplique sus valores por los y
que acabamos de factorizar y y
agreguemos oficialmente a la cadena de gozinta.
++
Considere la siguiente opción también. Esto simplemente agrega las dos listas juntas, pero monádicamente podemos pensar que dice "elegir entre hacer esto o lo otro".
x # (y + 1)
La otra opción es simplemente continuar recurriendo y no usar el valor y
. Si y
no se divide x
, esta es la única opción. Si se y
divide, x
entonces se tomará esta opción, así como la otra opción, y los resultados se combinarán.
map (1 :) . (# 2)
Esta es la función principal de gozinta. Comienza la recursión llamando (#)
con su argumento. A 1
se antepone a cada cadena de gozinta, porque la (#)
función nunca los pone en las cadenas.