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ż guard
wymaga Control.Monad
importu. 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ę. x
to liczba, nad którą się kumulujemy (iloczyn dzielników, które pozostają w wartości) i y
jest następną liczbą, którą powinniśmy spróbować podzielić.
| x == y = [[x]]
Jeśli x
jest równy y
, to zakończyliśmy rekurencję. Wystarczy użyć x
jako 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 guard
oś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 y
dzieli x
.
(y:) . map (y *) <$> div x y#2)
Jeśli y
dzieli x
, mamy do wyboru dodanie y
do łańcucha gozinta. W tym przypadku, rekurencyjnie zadzwonić (#)
, wychodząc na co y = 2
się x
równa x / y
, ponieważ chcemy „czynnik out”, które y
po prostu dodaje się do łańcucha. Następnie, bez względu na wynik tego rekurencyjnego wezwania, pomnóż jego wartości przez y
właśnie uwzględnione i y
oficjalnie 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 y
nie dzieli, x
jest to jedyna opcja. Jeśli y
dzieli, x
to 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 1
jest dołączane do każdego łańcucha gozinta, ponieważ (#)
funkcja nigdy nie umieszcza jednych w łańcuchach.