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)
Precisa do Lambdabot Haskell, pois guard
requer Control.Monad
que seja importado. A função principal é uma função anônima, que me disseram que é permitida e retira alguns bytes.
Agradecemos a Laikoni por salvar sete bytes.
Explicação:
Mônadas são muito úteis.
x # y
Esta é a nossa função recursiva que faz todo o trabalho real. x
é o número que estamos acumulando (o produto dos divisores que permanecem no valor) e y
é o próximo número que devemos tentar dividir nele.
| x == y = [[x]]
Se for x
igual y
, terminamos de repetir. Basta usar x
como o final da corrente gozinta atual e devolvê-lo.
| 1 > 0 =
Haskell golf-ism para "True". Ou seja, este é o caso padrão.
(guard (mod x y < 1) >>
Estamos operando dentro da lista mônada agora. Na mônada da lista, temos a capacidade de fazer várias escolhas ao mesmo tempo. Isso é muito útil ao encontrar "tudo possível" de algo por exaustão. A guard
declaração diz "considere apenas a seguinte opção se uma condição for verdadeira". Nesse caso, considere apenas a seguinte opção se y
dividir x
.
(y:) . map (y *) <$> div x y#2)
Se y
dividir x
, temos a opção de adicionar y
à cadeia gozinta. Nesse caso, chame recursivamente (#)
, começando y = 2
com x
igual a x / y
, pois queremos "fatorar" que y
acabamos de adicionar à cadeia. Então, qualquer que seja o resultado dessa chamada recursiva, multiplique seus valores pelo y
que acabamos de y
fatorar e adicione oficialmente à cadeia gozinta.
++
Considere a seguinte opção também. Isso simplesmente adiciona as duas listas, mas, monadicamente, podemos pensar nisso como dizendo "escolha entre fazer essa coisa OU essa outra coisa".
x # (y + 1)
A outra opção é simplesmente continuar recorrendo e não usar o valor y
. Se y
não se dividir x
, esta é a única opção. Se y
dividir x
, esta opção será usada, assim como a outra opção, e os resultados serão combinados.
map (1 :) . (# 2)
Esta é a principal função gozinta. Inicia a recursão chamando (#)
com seu argumento. A 1
é anexado a todas as cadeias gozinta, porque a (#)
função nunca as coloca nas cadeias.