Haskell (Lambdabot), 92 85 байт
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)
Потрібен Lambdabot Haskell, оскільки його guard
потрібно Control.Monad
імпортувати. Основна функція - це анонімна функція, яка, як мені кажуть, дозволена, і вона обробляє пару байтів.
Дякуємо Лайконі за збереження семи байтів.
Пояснення:
Монади дуже зручні.
x # y
Це наша рекурсивна функція, яка виконує всю фактичну роботу. x
- це число, яке ми накопичуємо (добуток дільників, які залишаються у значенні), і y
це наступне число, яке ми повинні спробувати поділити на нього.
| x == y = [[x]]
Якщо x
дорівнює, y
то ми закінчуємо повторення. Просто використовуйте x
як кінець поточного ланцюжка gozinta і поверніть його.
| 1 > 0 =
Haskell golf-ism для "Правда". Тобто це справа за замовчуванням.
(guard (mod x y < 1) >>
Зараз ми працюємо всередині монади у списку. У монаді списку ми маємо можливість робити кілька варіантів одночасно. Це дуже корисно, коли вичерпавши «все можливе» чогось. У guard
заяві сказано: "Розгляньте наступний вибір лише тоді, коли умова справжня". У цьому випадку враховуйте наступний вибір лише у випадку y
розділення x
.
(y:) . map (y *) <$> div x y#2)
Якщо y
розділимо x
, ми маємо вибір додати y
до ланцюжка гозінта. У цьому випадку рекурсивно дзвоніть (#)
, починаючи y = 2
з рівня, x
рівного x / y
тому, що ми хочемо "визначити", що y
тільки що додали до ланцюга. Тоді, незалежно від результату цього рекурсивного виклику, множимо його значення на y
щойно розроблені нами дані та додаємо y
до ланцюгу gozinta офіційно.
++
Розглянемо також наступний вибір. Це просто додає два списки разом, але монально ми можемо думати про це як про те, щоб сказати: "вибирай між тим, чи робиш цю справу АБО іншою справою".
x # (y + 1)
Інший варіант - просто продовжувати повторення та не використовувати значення y
. Якщо y
не ділиться, x
то це єдиний варіант. Якщо y
розділити, x
то цей варіант буде прийнятий, як і інший варіант, і результати будуть об'єднані.
map (1 :) . (# 2)
Це основна функція гозінта. Починається рекурсія з виклику (#)
своїм аргументом. A 1
є попередньою для кожного ланцюга gozinta, оскільки (#)
функція ніколи не ставить їх у ланцюги.