Перерахуйте всі мультиплікативні розділи n


28

Враховуючи додатне число n , виведіть усі різні мультиплікативні розділи n у будь-якому зручному форматі.

Мультиплікативний розділ n - це набір цілих чисел, усіх більший, ніж одне, таким, що їх добуток дорівнює n . Наприклад, 20 має такі різні мультиплікативні розділи:

2 * 2 * 5
2 * 10
4 * 5
20

Порядок не має значення, тому 2 * 2 * 5такий же розділ, як і 2 * 5 * 2.


Приклади:

1 -> {}
2 -> {2}
4 -> {2, 2}, {4}
20 -> {2, 2, 5}, {2, 10}, {4, 5}, {20}
84 -> {2, 2, 3, 7}, {2, 2, 21}, {2, 14, 3}, {2, 6, 7}, {2, 42}, {4, 3, 7}, {28, 3}, {4, 21}, {6, 14}, {12, 7}, {84}


Відповіді:


6

Брахілог , 16 байт

>~l:{1<}a.*?,.=o

Це функція (не повна програма), яка приймає позитивне число як вхідний і генерує всі мультиплікативні її розділи. (Я також уникав використовувати будь-які вбудовані основні факторизації в цьому рішенні, в основному тому, що я не був впевнений, що вони допоможуть; я можу спробувати більш вбудоване важке рішення в якийсь момент.)

Спробуйте в Інтернеті! (Додано додатковий код навколо цієї функції, щоб перетворити його на повну програму; якщо ви надаєте функцію, показану вище, TIO безпосередньо, вона запустить функцію, але не надрукує її вихід ніде, що є марним в якості демонстрації .)

Ця програма мене справді розчаровує, оскільки значна частина її працює навколо помилок у перекладачі Брахілога та недоліків у його специфікації, а не насправді вирішення проблеми; але перекладач - це те, що він є. (Навіть при такій програмі перекладач використовує набагато більше пам'яті, ніж це було б логічно, і виходить з ладу через виснаження пам'яті, але, на щастя, при невеликих проблемах, вдається спочатку створити бажаний вихід.) У гіпотетичній "ідеальній версії Брахілог" Ви можете просто написати ~*.o.:{>1}a,, що було б на 4 байти коротше, але мені потрібно було додати додаткових обмежень, щоб трохи допомогти перекладачеві. (Мені Брахілог не дуже подобається, і я б скоріше дотримувався Prolog, але для його роботи потрібні подібні підказки, щоб програма працювала і вони писали набагато довше. Тож Brachylog це.)

Пояснення:

Як завжди, програма Брахілог - це набір обмежень; за замовчуванням перше обмеження обмежує вхід проти невідомого (яке я називаю A ), друге обмеження обмежує A проти другого невідомого B і так далі, поки ми не досягнемо результату. Деякі символи, наприклад {}, можуть змінити цей загальний потік, тому я використовую інший набір букв (наприклад, X / Y ) для представлення невідомих вкладених предикатів.

>       A is smaller than the input
~l      B has length A
  1<    X is 1, Y is larger
:{1<}a  For each element X of B, it corresponds to an element Y of C
.       C, the output, and D are all identical
*       E is the product of D's elements
?       E, the input, and F are all identical
,       There's no constraint between F and G
.       G, the output, and H are all identical
=       H and I are identical, and need to be evaluated early
o       The output can be produced by sorting I

Досі незрозуміло, як працює програма, тому спробуємо трохи спростити обмеження. C , D , G , H і я всі однакові (і рівні виходу). E і F також однакові (і рівні вхідному). Отже, наші обмеження зводяться до цього:

  • A - довжина B і виходу, і менша за вхід.
  • B складається з усіх пунктів 1 і не є особливо корисним (це частина програми просто тому, що в існуючому інтерпретаторі Брахілог :{1<}aпотрібен лівий аргумент, щоб мати обмежену довжину, інакше інтерпретатор переходить у нескінченний цикл).
  • Вихід повністю складається з чисел, більших за 1 (тобто більше, ніж відповідний елемент B ).
  • Добуток елементів виходу дорівнює вводу.
  • Вихід не змінюється шляхом його сортування (тобто в упорядкованому порядку).

До речі, я чітко не вказав, що всі елементи виводу є цілими числами, що може здатися необхідним; однак вирішувач обмежень Брахілога не може обробляти не цілі числа, тому він може створювати лише ті рішення, які містять цілі числа.

Зрозуміло, що "довжина виводу менша, ніж вхід" буде істинною, коли вихід є мультиплікативним розділом входу (тому що 2 x > x для всіх негативних x , тобто позитивних 2 x ). Тож ми можемо нехтувати цим обмеженням; це лише дати перекладачеві Брахілога робочу стратегію оцінювання програми. Інші обмеження (що сортування результатів, що його продукт є входом, і що його елементів у всіх більше 1) є визначенням мультиплікативного розділу, і тому ця функція є в основному лише прямою реалізацією питання.


6

Брахілог 1, 14 байт

:{$pp~c:*ao}fd

Спробуйте в Інтернеті!

Брахілог 2, 11 10 байт, виклик після публікації мови

{ḋp~c×ᵐo}ᵘ

Спробуйте в Інтернеті!

Малтісен відповів на це запитання в 17 байтах Pyth, тому я придумав 16-байтове рішення Brachylog, яке працювало, перекладаючи специфікацію питання на Brachylog. Поки я робив це, Денніс написав 15-байтове рішення желе. Тому мені довелося спуститися до 14 байт. Це функція, яка сприймає дані як аргумент і повертає список усіх розділів (а не генератор, як у моєму іншому рішенні).

Через деякий час після того, як я написав цю відповідь, нам із Деннісом вдалося спільно досягти розчину Jelly до 11 байт. Виявляється, з’явилася нова версія Brachylog, з більш стислим синтаксисом; він відкладає виклик, тому насправді не рахується, але він міг би керувати загальним значенням 11-байт, як тільки він вийшов; пізніші зміни мови (натхненні іншими викликами) можуть сягати 10, як це бачимо тут. Дві програми однакові, з тією лише різницею, як синтаксис.

На відміну від мого іншого рішення, яке не дуже використовувало «гольфістичні примітиви», а навпаки, заявляло проблему безпосередньо, це ігнорує майже всю силу обмежень Брахілога і робить натомість найкраще враження про Желі, написавши ланцюг обмежень, для яких лівий аргумент вже відомий (і, таким чином, обмеження просто діють як желейні монади, а не повномасштабні обмеження). Тому він використовує той же алгоритм, що і рішення Pyth @ Мальтісена, і це, мабуть, найпростіший спосіб вирішити це за допомогою типових примітивів для гольфу. (Цікаво, що рішення "просто заявити проблему" в моїй іншій відповіді було б коротшим, якби не помилки / недоліки в інтерпретаторі Брахілогу, незважаючи на відсутність використання примітивів для гольфу. Якось мені потрібно написати "вдосконалений брахілог" для того, щоб отримати гарне рішення для подібної проблеми; оскільки мови для гри в гольф, брахілог насправді багатослівний.)

Програма складається з генератора і навколо нього обгортки. По-перше, ось пояснення генератора:

$pp~c:*ao  ḋp~c×ᵐo
$p         ḋ        Prime factor decomposition of the input
  p         p       Generate all permutations
   ~c        ~c     Generate all inverse concatenations (i.e. partitions)
     :*a       ×ᵐ   Take the product of each list element in each partition
        o        o  Sort each partition

Це майже вирішує проблему, але ми закінчуємо генерувати багато розділів багато разів кожен. Тому нам потрібна обгортка, щоб подвоїти рішення:

:{…}fd
:{…}f     Convert generator to list
     d    Remove duplicate elements

{…}ᵘ      Convert generator to list of unique elements

Чому б не відредагувати свою швидку відповідь?
Пуховик

3
@Downgoat: У двох відповідях використовуються абсолютно різні підходи; алгоритми різні, мовні функції, які використовуються, здебільшого є незалежними тощо. Не було б сенсу замінювати старіший на новіший (і, можливо, я б опублікував новий, навіть якщо він довший). Цей мета-пост підказує, що розміщення окремих відповідей є кращим у подібній ситуації.

1
Я не знаю, чи знаєте ви це, але ви можете отримати вихід, встановивши аргумент на TIO як змінну (тобто велику літеру). Наприклад .
Фаталізувати

5

Математика, 61 байт

±1={{}}
±n_:=Union@@(Sort/@Append[n/#]/@±#&/@Most@Divisors@n)

Визначає (рекурсивний) одинарний оператор, ±який повертає список розділів.


Хіба математика не потребує крапки з комою в кінці?
Павло

@Pavel ні, крапка з комою просто пригнічує вихід у інтерактивний ноутбук. Дякую, що вказали на це, btw, я випадково залишив крапку з комою.
Мартін Ендер

4

Pyth - 17 байт

Бере всі перестановки основної факторизації, потім розділяє кожен, а потім продукує всі розділи, тоді зберігає лише окремі розділи.

{mS-*Md1s./M.p+1P

Тестовий сюїт .


4

Python 2, 70 байт

f=lambda n,k=2,l=[]:n/k and(n%k<1)*f(n/k,k,l+[k])+f(n,k+1,l)or 1/n*[l]

Виводить список відсортованих списків. Наприклад f(20)є [[2, 2, 5], [2, 10], [4, 5], [20]].


Оскільки вбудований цілий тип Python не має обмежень, плаваюча точка не є прийнятним рішенням, оскільки неточності порушать відповідь на занадто великі входи.
orlp

@orlp Добре, потім поверніться до Python 2.
xnor

TL; DR Я думаю, що 998 не надто великий вхід ;-) IMO справжній класний код, більше схожий на затримку O(n)та порівняння з конкурентом Python 2, можливо, буде більш O(n^4)стильним - тоді як f (998) може підірвати пам'ять, або апаратне забезпечення може загинути протягом запуску час, приблизно, 80 днів з іншим алгоритмом, цей тут збігається через прибл. 7 мілісекунд на моїй машині, щоб отримати результат [[2, 499], [998]]. ІМО проблема може бути більш , що для зупиняється над Python 3 код ... щасливий грати в гольф :-)N > 998RecursionError: maximum recursion depth exceeded in comparison
Dilettant

@Dilettant Не впевнений, чи O(n^4)достатньо навіть для мого подання Python2: D Зважаючи на тестовий випадок 998, мій код буде працювати 9 разів і (n+r-1)! / r! / (n-1)!щоразу обчислювати кількість кортежів, де rлінійно зростає з 2, і n 9 - 2. Але ей, принаймні вам не доведеться налаштовувати межу рекурсії ...
Yytsi

@TuukkaX Caveat: Я не проаналізував код, просто проглянув і порівняв розробку часу виконання двох кандидатів на кілька N до 41, тоді я подумав, що я просто виконую коментар ;-) часто стоїть і рекурсія м'яса легко, але тоді закликайте до питань глибокого типу в неприємних ситуаціях ... сподіваюся, що я створив це досить нечітко для кількості досліджень, які пройшли.
Dilettant

3

Желе , 14 13 11 байт

Ḋx³ŒPQP=¥Ðf

Спробуйте в Інтернеті!

Я був досить впевнений, що рішення @ Jelnis Jelly можна було покращити. На жаль, мені не вдалося побити рекорд Брахілога, але мені вдалося зв'язати його. Оновлення : за допомогою @Dennis допомога вдосконалена зараз; Я здогадуюсь, що желе забирає назад корону.

Ця програма неймовірно неефективна, має продуктивність O (2 n 2 ) (саме тому тестовий випадок наведено вище для введення 4). Він завершується швидко на 4, дуже повільно на 5, і, можливо, неможливо практично запустити для більшої кількості.

Цікаво, що Брахілог був вдосконалений шляхом переходу від рішення, яке описувало проблему (яка Брахілог хороша в), до рішення, яке використовувало алгоритм, заснований на факторизації вхідних даних (в чому Jelly добре); тим часом рішення Jelly було покращено, відступивши від своїх сильних сторін і повернувшись до рішення, яке якраз і описує проблему.

Пояснення:

Ḋx³ŒPQP=¥Ðf
Ḋ              List of integers from 2 to the input (apparently undocumented)
 x³            Make a number of copies of each that's equal to the input
   ŒP          Take all (possibly noncontiguous) subsequences of that list (!)
     Q         Remove duplicates
         Ðf    Filter, keeping elements where:
      P=         their product is equal to {the original input, by default}
        ¥      Parse preceding two links as a unit

Оскільки вихід Ḋxсортується, кожну послідовність необхідно також сортувати, і тому нам не доведеться їх сортувати окремо. Таким чином, частина проблеми "один і той же вихід у різних порядках є дублікатом", а частина "всі значення на виході є> 1" частиною проблеми, яку вирішує покоління. Крім того, що ми в основному робимо тут, це "знайти всі списки, для яких P=³", що ми робимо (неймовірно неефективно) шляхом генерування всіх спірних списків, а потім відфільтрування неправильних.

(Зрозуміло, що хтось повинен винайти гібрид Jelly і Brachylog, плюс дійсно хороший вирішувач обмежень, щоб ми могли написати щось у рядках {P=³}~плюс якийсь код дедупликації та вирішити програму значно меншою довжиною. Це може бути якась відстань, однак.)


Будь ласка, хтось тут знайде характер заощаджень. Я б хотів "байтову війну", в якій записи постійно отримують один байт коротше. Тут є достатньо байтів, витрачених на структурні частини програми, що, здається, це може бути незмінним.

1
Хе, я просто збирався розмістити щось вражаюче схоже. (Потрібно частіше оновлюватись.) 2rМоже стати , і P=³$$може стати P=¥.
Денніс

P=¥не спрацьовує, коли я спробую це в інтерпретаторі, хоча я не зовсім впевнений, чому (логічно, це повинно працювати, і це було однією з речей, які я намагався під час написання публікації; я просто спробував це ще раз, щоб переконатися, це точно не робить те, що я очікував). робить, однак, я думаю, що там є наш однобайтовий заощадження :-)

1
Не звернули уваги на ще одну деталь. Вам також доведеться замінити µна ¹, що µробить повторний діапазон новим лівим аргументом.
Денніс

О, звичайно. Тож тепер ми знизилися до 11, зі значно меншими персонажами, завдяки чому я відчуваю себе набагато краще. (Я використовував, ³а не ¹просто для сорту.)

2

JavaScript (ES6), 74 67 байт

f=(n,m=2,a=[])=>n>1?m>n?[]:f(n,m+1,a).concat(f(n/m,m,[...a,m])):[a]

for (var i = 1; i < 31; i++) console.log(JSON.stringify(f(i)));

Безпосередньо вирішує задачу рекурсивно: для кожного цілого m від 2 до n ми беремо кожен з розділів n / m з мінімальним елементом m (щоб уникнути дублювання розділів) і додаємо m . (Для будь-якого m , який не ділить n , це дає порожній масив, оскільки жодне розташування цілих чисел не множиться на десятковий.) Ми визначаємо базовий випадок порожнього масиву на 1 , щоб уникнути нескінченної рекурсії.


1

Python2, 198 191 172 180 байт

from itertools import*
n=input()
for i in range(2,len(bin(n))):
 for P in combinations_with_replacement(range(2,n),i):
  if reduce(lambda a,b:a*b,P)==n:print(P)
print[(n,),()][n<2]

Повна програма. Це можна було б значно покращити, тому пропозиції глибоко вітаються!

  • @FlipTack врятував 9 байт!
  • @orlp врятував 19 байт!

Виходи від діапазону від 1 до 31 (включно):

(1,)
(2,)
(3,)
(2, 2), (4,)
(5,)
(2, 3), (6,)
(7,)
(2, 4), (2, 2, 2), (8,)
(3, 3), (9,)
(2, 5), (10,)
(11,)
(2, 6), (3, 4), (2, 2, 3), (12,)
(13,)
(2, 7), (14,)
(3, 5), (15,)
(2, 8), (4, 4), (2, 2, 4), (2, 2, 2, 2), (16,)
(17,)
(2, 9), (3, 6), (2, 3, 3), (18,)
(19,)
(2, 10), (4, 5), (2, 2, 5), (20,)
(3, 7), (21,)
(2, 11), (22,)
(23,)
(2, 12), (3, 8), (4, 6), (2, 2, 6), (2, 3, 4), (2, 2, 2, 3), (24,)
(5, 5), (25,)
(2, 13), (26,)
(3, 9), (3, 3, 3), (27,)
(2, 14), (4, 7), (2, 2, 7), (28,)
(29,)
(2, 15), (3, 10), (5, 6), (2, 3, 5), (30,)
(31,)

Це навіть працює? Існує 4 -> {2, 2}, {4}питання про тестовий випадок , я не бачу такого виводу у вашому журналі.
Борсуньо

@Borsunho Коли я повернув стару версію назад, я забув додати +1 int(math.log(n,2)), що спричинило це. +2 байти, і воно спрацює. Спасибі!
Yytsi

Ви не імпортували, mathале використовуєте math.log.
orlp

@orlp У мене ...? На третьому рядку.
Yytsi

@TuukkaX Вибачте, я переглянув лише найвищі лінії імпорту, оскільки вони майже завжди є ... Це, як кажуть, len(bin(n))-2коротше int(math.log(n,2)).
orlp


1

Clojure, 91 байт

(defn f[n](conj(set(for[i(range 2 n):when(=(mod n i)0)j(f(/ n i))](sort(flatten[i j]))))n))

Приклад виконання:

(map f [20 84])
(#{20 (2 2 5) (4 5) (2 10)} #{(7 12) (2 2 3 7) (2 3 14) (2 2 21) (2 6 7) (6 14) (3 4 7) (3 28) (4 21) (2 42) 84})

Саме значення повертається як одне число (не а list), інші виводяться як списки. В nкінці можна було б замінити, [n]щоб зробити це також послідовністю, або (list n)зробити його списком.



0

J, 35 байт

([:~.]<@/:~@(*//.)"$~#\#:i.@!@#)@q:

Виходячи з рішення задачі з часовою обмеженою факторизацією.

Ця версія набагато неефективніша і працює у фактичний час на основі кількості основних факторів. Створює розділи, генеруючи фактичні числа.

Спробуйте в Інтернеті! (Не пробуйте великих значень в Інтернеті!)

Пояснення

([:~.]<@/:~@(*//.)"$~#\#:i.@!@#)@q:  Input: integer n
                                 q:  Prime factorization
(                              )@    Operate on them
                              #        Length
                            !@         Factorial
                         i.@           Range [0, i)
                     #\                Range [1, i]
                       #:              Mixed based conversion - Creates factoradic values
     ]                                 Get factors
            (    )"$~                  For each factoradic value
               /.                        Partition the factors based on equal
                                         digits in the factoradic value
             */                          Get the product of each block
        /:~@                             Sort it
      <@                                 Box it
 [:~.                                  Deduplicate

0

D, 95 байт

void g(int n,int[]r){for(int i=r[0];i*i<=n;i++)(n%i)?0:g(n/i,i~r);r.back=n;r.writeln;}g(n,[2]);

Просто рекурсивне рішення. В g(n,r), rце розділ поки що, і nце значення все ще залишається для розбиття на фактори. Щоб отримати кожен не упорядкований розділ лише один раз, ми відсортуємо чинники rв порядку, що не збільшується. Останній елемент rзапуску починається 2як найменш можливий коефіцієнт і перезаписується nу кожній копії безпосередньо перед кожною операцією виводу.

Бо n = 60вихід такий:

[3, 2, 2, 5]
[2, 2, 15]
[3, 2, 10]
[5, 2, 6]
[2, 30]
[4, 3, 5]
[3, 20]
[4, 15]
[5, 12]
[6, 10]
[60]

Спробуйте в Інтернеті!


Використовуйте шаблони, Gassa, використовуйте шаблони:void g(T)(T n,T[]r){for(T i=r[0];i*i<=n;i++)n%i0:r;r.back=n;r.writeln;}g(n,[2])
Zacharý

У будь-якому випадку, це навіть не достовірна відповідь, оскільки вам потрібно імпортувати, std.stdioа std.rangeвведення 1нічого не повинно друкувати, не [1].
Zacharý

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.