Haskell (Lambdabot), 92 85 bajtów
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)
Potrzebuje Lambdabot Haskell, ponieważ guardwymaga Control.Monadimportu. Główna funkcja jest funkcją anonimową, o której, jak mi powiedziano, jest dozwolona i goli kilka bajtów.
Dzięki Laikoni za zaoszczędzenie siedmiu bajtów.
Wyjaśnienie:
Monady są bardzo przydatne.
x # y
To jest nasza funkcja rekurencyjna, która wykonuje całą rzeczywistą pracę. xto liczba, nad którą się kumulujemy (iloczyn dzielników, które pozostają w wartości) i yjest następną liczbą, którą powinniśmy spróbować podzielić.
| x == y = [[x]]
Jeśli xjest równy y, to zakończyliśmy rekurencję. Wystarczy użyć xjako końca bieżącego łańcucha gozinta i zwrócić go.
| 1 > 0 =
Haskell golf-ism dla „True”. To jest przypadek domyślny.
(guard (mod x y < 1) >>
Działamy teraz na liście monad. W ramach monady listy mamy możliwość dokonywania wielu wyborów jednocześnie. Jest to bardzo pomocne przy znajdowaniu „wszystkiego, co możliwe” czegoś przez wyczerpanie. W guardoświadczeniu jest napisane: „rozważ następujący wybór tylko wtedy, gdy spełniony jest warunek”. W takim przypadku rozważ tylko następujący wybór, jeśli ydzieli x.
(y:) . map (y *) <$> div x y#2)
Jeśli y dzieli x, mamy do wyboru dodanie ydo łańcucha gozinta. W tym przypadku, rekurencyjnie zadzwonić (#), wychodząc na co y = 2się xrówna x / y, ponieważ chcemy „czynnik out”, które ypo prostu dodaje się do łańcucha. Następnie, bez względu na wynik tego rekurencyjnego wezwania, pomnóż jego wartości przez ywłaśnie uwzględnione i yoficjalnie dodaj do łańcucha gozinta.
++
Rozważ również następujący wybór. To po prostu dodaje obie listy razem, ale monadycznie możemy myśleć o tym jako o powiedzeniu „wybierz między robieniem tego, a tym innym”.
x # (y + 1)
Inną opcją jest po prostu kontynuowanie rekurencji i nie używanie wartości y. Jeśli ynie dzieli, xjest to jedyna opcja. Jeśli ydzieli, xto ta opcja zostanie wzięta, podobnie jak druga opcja, a wyniki zostaną połączone.
map (1 :) . (# 2)
Jest to główna funkcja gozinta. Rozpoczyna rekursję od wywołania(#) z argumentem. A 1jest dołączane do każdego łańcucha gozinta, ponieważ (#)funkcja nigdy nie umieszcza jednych w łańcuchach.