nのすべての乗算パーティションをリストします


28

正の数で与えられたN、出力のすべての異なる乗法パーティションN任意の便利なフォーマットです。

nの乗法パーティションは、すべてが1より大きい整数のセットであり、その積は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

Brachylog、16バイト

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

これは、入力として正の数を取り、そのすべての乗算パーティションを生成する関数(完全なプログラムではありません)です。(また、主にそれらが助けになるかどうか確信が持てなかったため、このソリューションで主要な因数分解ビルトインを使用することも避けました。ある時点で、より組み込みの重いソリューションを試すこともできます)

オンラインでお試しください!(ここに関数の周りに追加のコードが追加されて、完全なプログラムになります。上記の関数をTIOに直接提供すると、関数は実行されますが、出力はどこにも出力されず、デモとしては役に立たなくなります)

このプログラムは本当に失望します。その多くは、実際に問題を解決するのではなく、Brachylogインタープリターのバグとその仕様の欠陥に対処しているからです。しかし、通訳はそれが何であるかです。(このようなプログラムでも、インタープリターは論理的に必要以上に多くのメモリーを使用し、メモリーの枯渇によりクラッシュしますが、幸いなことに小さな問題で最初に目的の出力を生成することができます。)を書くことができますが~*.o.:{>1}a,、これは4バイト短くなりますが、インタプリタを少し助けるために余分な制約を追加する必要がありました。(私はBrachylogがあまり好きではなく、むしろPrologに固執しますが、プログラムを機能させるために同様のヒントが必要で、書くのにかなり時間がかかります。したがってBrachylogはそうです。)

説明:

いつものように、Brachylogプログラムは一連の制約です。デフォルトでは、最初の制約は未知(これをAと呼びます)に対して入力を制約し、2番目の制約は出力に到達するまでAを2番目の未知の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

プログラムがどのように機能するかはまだ不明であるため、制約を少し単純化してみましょう。CDGH、およびIはすべて同じ(および出力に等しい)です。EFも同じです(入力と同じです)。したがって、制約は次のように要約されます。

  • ABと出力の長さであり、入力よりも小さいです。
  • Bはすべて1で構成されており、特に有用ではありません(既存のBrachylogインタープリターで:{1<}aは長さを制限するために左引数が必要であるか、インタープリターが無限ループに入るため、プログラムの一部です)。
  • 出力は、1より大きい(つまり、Bの対応する要素より大きい)数値のみで構成されます。
  • 出力の要素の積は、入力と等しくなります。
  • 出力はソートによって変更されません(つまり、ソート順です)。

ちなみに、出力のすべての要素が整数であるように明示的に指定したわけではありません。ただし、Brachylogの制約ソルバーは非整数を処理できないため、整数を含むソリューションのみを生成するのが便利です。

明らかに、「出力の長さは入力よりも短い」というのは、出力が入力の乗法パーティションである場合は常に真になります(すべての非負のx、つまり正の2 xに対して2 x > xであるため)。したがって、その制約を無視できます。Brachylogインタープリターにプログラムを評価するための実用的な戦略を提供するのはそこだけです。他の制約(出力がソートされ、その積が入力であり、その要素がすべて1より大きいこと)は乗法パーティションの定義であるため、この関数は基本的に質問の直接的な実装です。


6

Brachylog 1、14バイト

:{$pp~c:*ao}fd

オンラインでお試しください!

Brachylog 2、11 10バイト、言語postdates挑戦

{ḋp~c×ᵐo}ᵘ

オンラインでお試しください!

Maltysenは17バイトのPythでこの質問に答えたので、質問の仕様をBrachylogに翻訳することで機能する16バイトのBrachylogソリューションを思い付きました。その間、デニスは15バイトのゼリーソリューションを作成しました。そのため、14バイトまで減らす必要がありました。これは、引数として入力を受け取り、すべてのパーティションのリストを返す関数です(他のソリューションのようにジェネレーターではなく)。

この答えを書いてしばらくして、デニスと私は協力してJellyソリューションを11バイトにまで減らすことができました。簡潔な構文を持つBrachylogの新しいバージョンがあります。チャレンジをポストデートするため、実際にはカウントされませんが、11バイトの合計をリリースするとすぐに管理しすぎる可能性があります。この言語のその後の改訂版(他の課題に触発された)は、ここに見られるように10まで低くなる可能性があります。2つのプログラムは同一ですが、唯一の違いは構文です。

「ゴルフプリミティブ」をあまり使用せず、むしろ直接問題を述べた他のソリューションとは異なり、これはBrachylog制約のほとんどすべての力を無視し、代わりに、そのための最高のJelly印象を与えます。左の引数はすでにわかっています(したがって、制約は本格的な制約ではなく、単にJellyモナドのように機能します)。そのため、@ MaltysenのPythソリューションと同じアルゴリズムを使用します。これは、おそらく典型的なゴルフプリミティブを使用してこれを解決する最も簡単な方法です。(興味深いことに、ゴルフプリミティブを使用していないにもかかわらず、Brachylogインタープリターのバグ/欠陥がない場合、他の答えの「問題を述べるだけ」ソリューションは短くなります。いつか「改善されたBrachylog」を書く必要があります この種の問題の良い解決策を得るために; ゴルフ言語が進むにつれて、Brachylogは実際には非常に冗長です。)

このプログラムは、ジェネレーターとその周りのラッパーで構成されています。まず、ジェネレーターの説明を次に示します。

$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

既存の回答を編集してみませんか?
ダウンゴート16

3
@Downgoat:2つの答えはまったく異なるアプローチを使用しています。アルゴリズムは異なり、使用される言語機能はほとんど独立しています。古いものを新しいものに置き換えることは意味がありません(そして、たとえそれがもっと長くても新しいものを投稿したかもしれません)。このメタ投稿は、このような状況では別々の回答を投稿することが望ましいことを示唆しています。

1
これを知っているかどうかはわかりませんが、TIOの引数を変数(大文字)に設定することで出力を取得できます。たとえば
1

5

Mathematica、61バイト

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

±パーティションのリストを返す(再帰的な)単項演算子を定義します。


数学は最後にセミコロンを必要としませんか?
パベル

@Pavelいいえ、セミコロンは対話型ノートブックの出力を抑制します。ところで、これを指摘してくれてありがとう、私は誤って最後にセミコロンを残しました。
マーティンエンダー

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 16

@orlp OK、Python 2に戻ります。
XNOR

TL; DR 998は大きすぎる入力ではないと思います;-) IMOの実際のクールなコード、レイテンシーO(n)とPython 2の競合他社との比較はよりO(n^4)スタイルがありますが、f(998)は実行中にメモリまたはハードウェアが破壊される可能性があります他のアルゴリズムで推定80日間、ここでは約1時間後に収束します。結果を得るために私のマシンで7ミリ秒[[2, 499], [998]]。IMOの問題は、上記のPython 3コードを停止するためN > 998のより多くの可能性がありRecursionError: maximum recursion depth exceeded in comparisonます...ハッピーゴルフ:
Dilettant

@Dilettantわからない場合はO(n^4)私のPython2の提出のためにも十分です:Dは、テストケース998を考えると、私のコードは、9回を実行し、計算されます(n+r-1)! / r! / (n-1)!タプルの量たびに、r2から直線的に成長している、そしてnは9 - 2。でもねえ、少なくとも、あなたは...再帰制限を微調整する必要はありません
Yytsi

@TuukkaX Caveat:コードを分析せずに、ざっと目を通し、Nまでの2つの候補の間で実行時間の開発を比較しました。最大41人までのコメントをコミットしたと思いました;-)スタックと再帰はしばしば簡単ですが、不愉快な状況でどのように深いタイプの質問のためのコール...私はそれをしていった研究の量のためのファジー十分な造語を願っています。
Dilettant

3

ゼリー14 13 11バイト

Ḋx³ŒPQP=¥Ðf

オンラインでお試しください!

@DennisのJellyソリューションを改善できると確信していました。残念ながら、私はBrachylogの記録を破ることができませんでしたが、何とか結びつけることができました。更新:@Dennisの支援により、現在改善されています。ジェリーが王冠を取り戻すと思います。

このプログラムは信じられないほど非効率的で、O(2 n 2)のパフォーマンスを備えています(そのため、上記のテストケースは入力4でそれを示しています)。これは4ですばやく完了し、5で非常にゆっくりと完了し、より大きな数で実行することは実際には不可能な場合があります。

興味深いことに、Brachylogは、問題を説明するソリューション(Brachylogが得意)から、入力の因数分解に基づくアルゴリズムを使用するソリューション(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バイト短くなっていく「バイト戦争」が大好きです。ここでは、プログラムの構造部分に無駄なバイトが十分にあるため、これは改善可能と思われます。

1
へえ、私はちょうど驚くほど似たようなものを投稿しようとしていました。(より頻繁にリフレッシュする必要があります。)2rになることができ、およびP=³$$になることができますP=¥
デニス

P=¥通訳で試してみてもうまくいきませんが、理由は完全にはわかりませんが(論理的にうまくいくはずで、投稿を書いているときに試したものの1つでした。それは間違いなく私が期待していたことをしません)。ただし、1バイトの節約があると思います:

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から2N、我々は、パーティションの各々取るN / Mの最小要素とMを(重複パーティションを避けるために)及びアペンドM。(nを分割しないmの場合、整数の配列は10進数に乗算されないため、空の配列になります。)無限の再帰を避けるために、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}問題のテストケースがありますが、そのような出力はログに表示されません。
ボルスニョ16

@Borsunho古いバージョンをロールバックするときに、に+1を追加するのを忘れてint(math.log(n,2))しまいました。+2バイトで動作します。ありがとう!
Yytsi 16

インポートしていませんmathが、を使用していmath.logます。
orlp 16

@orlp私は...?3行目。
Yytsi 16

@TuukkaXすみません、私はインポートの一番上の行だけを見ました。それらはほとんどいつもそこにあるので...それは言われてlen(bin(n))-2いるより短いですint(math.log(n,2))
orlp 16


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

値自体は(a 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要因に分割するために残された値です。順序付けされていない各パーティションを1回だけ取得するために、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])
ザカリー

インポートする必要があるとして、とにかく、これは、も、有効な回答ではないstd.stdiostd.range、入力は1、何もしないで印刷するべきではありません[1]
ザカリー

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.