Listen Sie alle multiplikativen Partitionen von n auf

28

Bei einer positiven Zahl n werden alle unterschiedlichen multiplikativen Partitionen von n in einem beliebigen geeigneten Format ausgegeben.

Eine multiplikative Partition von n ist eine Menge von ganzen Zahlen, alle größer als eins, so dass ihr Produkt n ist . Beispielsweise hat 20 die folgenden unterschiedlichen multiplikativen Partitionen:

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

Die Reihenfolge spielt keine Rolle, so 2 * 2 * 5ist die gleiche Partition wie 2 * 5 * 2.


Beispiele:

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}
orlp
quelle
Related
Meilen

Antworten:

6

Brachylog , 16 Bytes

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

Dies ist eine Funktion (kein vollständiges Programm), die eine positive Zahl als Eingabe verwendet und alle multiplikativen Partitionen davon generiert . (Ich habe auch die Verwendung von eingebauten Primfaktoren in dieser Lösung vermieden, hauptsächlich, weil ich nicht sicher war, ob sie helfen würden; ich könnte auch irgendwann eine eingebaute Lösung ausprobieren.)

Probieren Sie es online! (Um die Funktion hier in ein vollständiges Programm umzuwandeln, wurde zusätzlicher Code hinzugefügt. Wenn Sie TIO die oben gezeigte Funktion direkt zur Verfügung stellen, wird die Funktion ausgeführt, die Ausgabe jedoch nirgends gedruckt, was als Demonstration nutzlos ist .)

Dieses Programm ist wirklich enttäuschend für mich, da es hauptsächlich um Fehler im Brachylog-Interpreter und Mängel in seiner Spezifikation geht, anstatt das Problem tatsächlich zu lösen. aber der Dolmetscher ist was er ist. (Selbst mit dem Programm wie diesem verbraucht der Interpreter viel mehr Speicher als es logischerweise sein sollte und stürzt aufgrund von Speichermangel ab, aber zum Glück schafft er es bei kleinen Problemen, zuerst die gewünschte Ausgabe zu erzeugen.) In einer hypothetischen "perfekten Version von Brachylog" Sie könnten einfach schreiben ~*.o.:{>1}a,, was 4 Bytes kürzer wäre, aber ich musste zusätzliche Einschränkungen hinzufügen, um dem Interpreter ein wenig zu helfen. (Ich mag Brachylog nicht wirklich und würde mich lieber an Prolog halten, aber es brauchte ähnliche Hinweise, damit das Programm funktioniert und sie sind viel länger zu schreiben. Also ist es Brachylog.)

Erläuterung:

Wie üblich besteht ein Brachylog-Programm aus einer Reihe von Einschränkungen. Standardmäßig beschränkt die erste Einschränkung die Eingabe auf ein unbekanntes Element (das ich A nennen werde ), die zweite Einschränkung beschränkt A auf ein zweites unbekanntes Element B usw., bis die Ausgabe erreicht ist. Einige Zeichen, wie z. B. {}, können diesen allgemeinen Ablauf ändern. Daher verwende ich einen anderen Satz von Buchstaben (z. B. X / Y ), um Unbekannte in verschachtelten Prädikaten darzustellen.

>       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

Es ist immer noch unklar, wie das Programm funktioniert. Versuchen wir also, die Einschränkungen ein wenig zu vereinfachen. C , D , G , H und ich sind alle gleich (und gleich der Ausgabe). E und F sind auch gleich (und gleich der Eingabe). Unsere Einschränkungen beschränken sich also auf Folgendes:

  • A ist die Länge von B und der Ausgabe und ist kleiner als die Eingabe.
  • B besteht aus allen Einsen und ist nicht besonders nützlich (es ist Teil des Programms, weil im vorhandenen Brachylog-Interpreter :{1<}adas linke Argument eine begrenzte Länge haben muss oder der Interpreter in eine Endlosschleife gerät).
  • Die Ausgabe besteht ausschließlich aus Zahlen größer als 1 (dh größer als das entsprechende Element von B ).
  • Das Produkt der Elemente der Ausgabe ist gleich der Eingabe.
  • Die Ausgabe bleibt durch Sortieren unverändert (dh in sortierter Reihenfolge).

Übrigens habe ich nicht explizit angegeben, dass alle Elemente der Ausgabe Ganzzahlen sind. Dies scheint erforderlich zu sein. Brachylogs Constraint-Solver kann jedoch keine Nicht-Ganzzahlen verarbeiten, sodass nur die Lösungen erstellt werden, die Ganzzahlen enthalten.

Offensichtlich ist "die Länge der Ausgabe kleiner als die Eingabe" immer dann wahr, wenn die Ausgabe eine multiplikative Partition der Eingabe ist (weil 2 x > x für alle nichtnegativen x , dh positive 2 x ). Wir können diese Einschränkung also ignorieren. Es dient nur dazu, dem Brachylog-Dolmetscher eine Arbeitsstrategie für die Bewertung des Programms zu geben. Die anderen Einschränkungen (dass die Ausgabe sortiert ist, dass ihr Produkt die Eingabe ist und dass ihre Elemente alle größer als 1 sind) sind die Definition einer multiplikativen Partition, und daher ist diese Funktion im Grunde nur eine direkte Implementierung der Frage.


quelle
6

Brachylog 1, 14 Bytes

:{$pp~c:*ao}fd

Probieren Sie es online!

Brachylog 2, 11 10 Bytes, Sprachnachstellung

{ḋp~c×ᵐo}ᵘ

Probieren Sie es online!

Maltysen beantwortete diese Frage in 17 Byte Pyth, und ich fand eine 16-Byte-Brachylog-Lösung, bei der die Spezifikation der Frage in Brachylog übersetzt wurde. Während ich das tat, schrieb Dennis eine 15-Byte-Jelly-Lösung. Also musste ich auf 14 Bytes runter. Dies ist eine Funktion , die die Eingabe als Argument verwendet und eine Liste aller Partitionen zurückgibt (und nicht wie bei meiner anderen Lösung einen Generator).

Einige Zeit, nachdem ich diese Antwort geschrieben hatte, gelang es Dennis und mir, die Jelly-Lösung auf 11 Byte zu reduzieren. Es stellt sich heraus, dass es eine neue Version von Brachylog gibt, mit einer terseren Syntax. Es datiert die Challenge nach, zählt also eigentlich nicht, könnte aber die 11-Byte-Summe zu sehr verwalten, sobald es veröffentlicht wird. Spätere Überarbeitungen der Sprache (inspiriert von anderen Herausforderungen) können, wie hier zu sehen, bis zu 10 betragen. Die beiden Programme sind identisch, der einzige Unterschied besteht in der Syntax.

Im Gegensatz zu meiner anderen Lösung, die nicht viel von "Golf-Primitiven" Gebrauch machte, sondern das Problem direkt ansprach, ignoriert diese so gut wie die gesamte Kraft der Brachylog-Einschränkungen und gibt stattdessen den besten Jelly-Eindruck ab und schreibt eine Kette von Einschränkungen, für die Das linke Argument ist bereits bekannt (und daher wirken die Einschränkungen einfach wie Jelly-Monaden und nicht wie ausgereifte Einschränkungen). Es wird daher derselbe Algorithmus wie bei der Pyth-Lösung von @ Maltysen verwendet, was wahrscheinlich der einfachste Weg ist, dies unter Verwendung typischer Golf-Primitive zu lösen. (Interessanterweise wäre die "Just State the Problem" -Lösung in meiner anderen Antwort kürzer, wenn der Brachylog-Interpreter keine Bugs / Mängel aufweist, obwohl er keine Golf-Primitive verwendet. Eines Tages muss ich ein "verbessertes Brachylog" schreiben. um eine gute Lösung für diese Art von Problem zu finden; Brachylog ist, was Golfsprachen angeht, eigentlich sehr ausführlich.)

Das Programm besteht aus einem Generator und einem Wrapper. Hier ist zunächst eine Erklärung des Generators:

$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

Damit ist das Problem fast gelöst, aber am Ende werden viele Partitionen mehrmals generiert. Wir brauchen also einen Wrapper, um die Lösungen zu deduplizieren:

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

{…}ᵘ      Convert generator to list of unique elements

quelle
Warum nicht deine exsting Antwort redigieren?
Downgoat
3
@Downgoat: Die beiden Antworten verwenden völlig unterschiedliche Ansätze. Die Algorithmen sind unterschiedlich, die verwendeten Sprachmerkmale sind größtenteils unabhängig und dergleichen. Es würde keinen Sinn machen, das ältere durch das neuere zu ersetzen (und ich hätte das neue vielleicht auch veröffentlicht, wenn es länger wäre). In diesem Metapost wird empfohlen, in solchen Situationen separate Antworten zu veröffentlichen.
1
Ich weiß nicht, ob Sie das wissen, aber Sie können die Ausgabe abrufen, indem Sie das Argument in TIO auf eine Variable setzen (dh einen Großbuchstaben). Zum Beispiel .
Fatalize
5

Mathematica, 61 Bytes

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

Definiert einen (rekursiven) unären Operator, ±der die Liste der Partitionen zurückgibt.

Martin Ender
quelle
Benötigt Mathematica nicht das Semikolon am Ende?
Pavel
@Pavel Nein, das Semikolon unterdrückt nur die Ausgabe im interaktiven Notizbuch. Vielen Dank für den Hinweis, übrigens habe ich versehentlich ein Semikolon am Ende gelassen.
Martin Ender
4

Pyth - 17 Bytes

Nimmt alle Permutationen der Primfaktorisierung, partitioniert dann jede Partition und erzeugt dann alle Partitionen, behält dann nur verschiedene Partitionen bei.

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

Test Suite .

Maltysen
quelle
4

Python 2, 70 Bytes

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]

Gibt eine Liste sortierter Listen aus. Zum Beispiel f(20)ist [[2, 2, 5], [2, 10], [4, 5], [20]].

xnor
quelle
Da der in Python integrierte Integer-Typ keine Grenzen hat, ist Gleitkommazahl keine akzeptable Lösung, da Ungenauigkeiten die Antwort für zu große Eingaben aufheben.
Orlp
@orlp Ok, dann zurück zu Python 2.
Xnor
TL; DR Ich denke, 998 ist keine zu große Eingabe ;-) IMO ist ein echter cooler Code, eher wie Latenz O(n)und Vergleich mit dem Python 2-Konkurrenten könnte mehr O(n^4)Stil sein - während f (998) Speicher sprengen könnte oder Hardware während des Laufs abstürzen könnte Zeit von ca. 80 Tagen mit dem anderen Algorithmus konvergiert dieser hier nach ca. 7 Millisekunden auf meiner Maschine, um das Ergebnis zu erzielen [[2, 499], [998]]. IMO könnte das Problem mehr sein, dass für N > 998die RecursionError: maximum recursion depth exceeded in comparisonStopps der oben genannte Python 3-Code ... Viel Spaß beim Golfen :-)
Dilettant
@Dilettant Ich bin mir nicht sicher, ob dies O(n^4)für meine Python2-Übermittlung ausreicht: D Unter Berücksichtigung des Testfalls 998 wird mein Code neunmal ausgeführt und die (n+r-1)! / r! / (n-1)!Anzahl der Tupel jedes Mal berechnet , wenn er rlinear von 2 auf n ansteigt 9 - 2. Aber hey, zumindest müssen Sie das Rekursionslimit nicht
anpassen
@TuukkaX Vorbehalt: Ich habe den Code nicht analysiert, nur überflogen und die Entwicklung der Laufzeiten zwischen den beiden Kandidaten für einige N bis 41 verglichen, dann dachte ich, ich lege einfach den Kommentar fest ;-) Stapel und Rekursion oft fleischfreundlich, aber dann fordern Sie, wie tief Fragen in unangenehmen Situationen eingeben ... Ich hoffe, ich habe es unscharf genug für die Menge an Forschung geprägt, die in ging.
Dilettant
3

Jelly , 14 13 11 Bytes

Ḋx³ŒPQP=¥Ðf

Probieren Sie es online!

Ich war mir ziemlich sicher, dass die Lösung von @ Dennis's Jelly verbessert werden könnte. Leider habe ich es nicht geschafft, den Brachylog-Rekord zu schlagen, aber ich habe es geschafft, ihn zu binden. Update : Mit Hilfe von @Dennis wurde es jetzt verbessert. Ich denke, Jelly nimmt die Krone zurück.

Dieses Programm ist unglaublich ineffizient und hat eine O (2 n 2 ) -Leistung (weshalb der obige Testfall dies für Eingabe 4 zeigt). Es endet schnell bei 4, sehr langsam bei 5, und es ist möglicherweise praktisch nicht möglich, für größere Zahlen zu laufen.

Interessanterweise wurde das Brachylog verbessert, indem von einer Lösung, die das Problem beschrieb (in der Brachylog gut ist), zu einer Lösung übergegangen wurde, die einen Algorithmus verwendete, der auf der Faktorisierung der Eingabe basierte (in der Jelly gut ist). In der Zwischenzeit wurde die Gelee-Lösung verbessert, indem man sich von ihren Stärken entfernte und zu einer Lösung zurückkehrte, die nur das Problem beschreibt.

Erläuterung:

Ḋ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

Da die Ausgabe von Ḋxsortiert ist, muss jede Untersequenz auch sortiert werden, sodass wir sie nicht einzeln sortieren müssen. Der Teil "Dieselbe Ausgabe in verschiedenen Reihenfolgen ist ein Duplikat" des Problems und der Teil "Alle Werte in der Ausgabe sind> 1" des Problems wird von der Generation gelöst. Abgesehen davon geht es hier im Grunde genommen darum, "alle Listen zu finden, für die P=³", was wir (auf unglaublich ineffiziente Weise) tun , indem wir alle fraglichen Listen generieren und dann die falschen herausfiltern.

(Es ist klar, dass jemand eine Mischung aus Jelly und Brachylog sowie einen wirklich guten Beschränkungslöser erfinden muss , damit wir etwas in der Art von {P=³}~Deduplizierungscode schreiben und das Programm in einer viel kürzeren Länge lösen können. Das könnte sein in einiger Entfernung.)


quelle
Bitte, jemand findet hier einen Sparcharakter. Ich würde einen "Bytekrieg" lieben, bei dem die Einträge jedes Mal um ein Byte kürzer werden. Es werden hier genug Bytes für strukturelle Teile des Programms verschwendet, so dass es den Anschein hat, dass dies verbesserungsfähig ist.
1
He, ich wollte gerade etwas Ähnliches posten. (Sollte öfter auffrischen.) 2rKann werden , und P=³$$kann werden P=¥.
Dennis
P=¥funktioniert nicht , wenn ich es in den Dolmetscher versuchen, obwohl ich bin mir nicht ganz sicher , warum (logisch, es sollte funktionieren, und es war eines der Dinge , die ich versuchte , während die Post zu schreiben, ich habe gerade versucht wieder sicher zu machen, es macht definitiv nicht das, was ich erwartet hatte). Ich denke, es gibt unsere Ein-Byte-Einsparung :-)
1
Ich habe nicht auf ein anderes Detail geachtet. Sie würden ersetzen µmit ¹als auch, wie µmacht den wiederholten Bereich das neue linke Argument.
Dennis
Ja natürlich. Jetzt sind wir bei 11, mit viel weniger Charakteren, was mir das Gefühl gibt, viel besser zu sein. (Ich verwendete ³eher als ¹nur für die Sorte.)
2

JavaScript (ES6), 74 67 Byte

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)));

Löst das Problem direkt rekursiv: Für jede ganze Zahl m von 2 bis n nehmen wir jede der Partitionen von n / m mit einem minimalen Element von m (um doppelte Partitionen zu vermeiden) und hängen m an . (Für jedes m , das n nicht teilt , ergibt dies das leere Array, da sich keine Anordnung von ganzen Zahlen mit einer Dezimalstelle multipliziert.) Wir definieren einen Basisfall des leeren Arrays für 1 , um eine unendliche Rekursion zu vermeiden.

ETHproductions
quelle
1

Python2, 198 191 172 180 Bytes

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]

Ein volles Programm. Dies könnte erheblich verbessert werden, daher sind Vorschläge herzlich willkommen!

Ausgänge von 1 bis einschließlich 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,)
Yytsi
quelle
Funktioniert das überhaupt? Es handelt sich um einen Testfall 4 -> {2, 2}, {4}, eine solche Ausgabe wird in Ihrem Protokoll nicht angezeigt.
Borsunho
@Borsunho Als ich die alte Version zurückrollte, vergaß ich +1 zu addieren int(math.log(n,2)), was das verursachte. +2 Bytes und es wird funktionieren. Vielen Dank!
Yytsi
Sie haben nicht importiert, mathaber verwenden math.log.
Orlp
@orlp habe ich ...? In der dritten Zeile.
Yytsi
@ TuukkaX Entschuldigung, ich habe nur die obersten Zeilen für Importe angesehen, da sie fast immer da sind ... Abgesehen davon len(bin(n))-2ist es kürzer als int(math.log(n,2)).
Orlp
1

Clojure, 91 Bytes

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

Beispiel läuft:

(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})

Der Wert selbst wird als einzelne Zahl (nicht als a list) zurückgegeben, andere werden als Listen ausgegeben. Das nam Ende könnte ersetzt werden [n], um es auch zu einer Sequenz oder (list n)zu einer Liste zu machen.

NikoNyrh
quelle
0

J, 35 Bytes

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

Basierend auf Lösung einer zeitlich begrenzten Faktorisierungsaufgabe.

Diese Version ist viel ineffizienter und läuft in Fakultätszeit basierend auf der Anzahl der Primfaktoren. Erstellt Partitionen durch Generieren von Fakultätszahlen.

Probieren Sie es online!(Versuchen Sie nicht große Werte online!)

Erläuterung

([:~.]<@/:~@(*//.)"$~#\#: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
Meilen
quelle
0

D, 95 Bytes

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]);

Nur eine rekursive Lösung. In g(n,r), rist die Partition bisher und nder Wert, der noch in Faktoren zerlegt werden muss. Um jede ungeordnete Partition nur einmal zu erhalten, sortieren wir die Faktoren rin nicht aufsteigender Reihenfolge. Das letzte Element von rbeginnt mit 2dem kleinstmöglichen Faktor und wird nin jeder Kopie unmittelbar vor jeder Ausgabeoperation überschrieben .

Für n = 60ist die Ausgabe wie folgt:

[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]

Probieren Sie es online!

Gassa
quelle
Verwenden Sie die Vorlagen, Gassa, verwenden Sie die Vorlagen: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ý
Auf jeden Fall ist dies nicht einmal eine gültige Antwort, da Sie importieren müssen std.stdiound std.rangeEingaben 1nichts ausgeben sollten, nicht [1].
Zacharý
0

D, 109 Bytes

import std.stdio;void g(T)(T n,T[]r=[2]){if(n-1){for(T i=r[0];i*i<=n;i++)n%i?0:g(n/i,i~r);r[$-1]=n;r.write;}}

Probieren Sie es online!

Zacharý
quelle