列出n的所有乘法分区


28

给定的正数Ñ,输出的所有不同的乘法分区Ñ以任何方便的格式。

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}


Answers:


6

Brachylog,16个字节

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

这是一个函数(不是完整程序),将正数作为输入并生成该函数的所有乘法分区。(我还避免在此解决方案中使用任何素数分解内置函数,主要是因为我不确定它们是否会有所帮助;有时我也可能会尝试使用更内置函数的解决方案。)

在线尝试!(此处已在函数周围添加了额外的代码,以使其成为完整的程序;如果直接向TIO提供上面显示的函数,它将运行该函数,但不会在任何地方打印其输出,这对于演示没有用)

这个程序真的让我很失望,因为它大部分都是针对Brachylog解释器中的错误和其规范中的缺陷而工作的,而不是实际解决问题。但是解释器就是它。(即使使用这样的程序,解释器也会使用比逻辑上更多的内存,并且由于内存耗尽而导致崩溃,但是幸运的是,在一些小问题上,解释器设法首先产生了所需的输出。)在假设的“ Brachylog的完美版本”中您可以只写~*.o.:{>1}a,,它要短4个字节,但是我需要添加额外的约束来帮助解释器一点点。(我不太喜欢Brachylog,并且宁愿坚持使用Prolog,但是它需要类似的提示才能使程序正常工作,并且编写它们的时间更长。所以Brachylog是这样。)

说明:

像往常一样,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

尚不清楚该程序如何工作,所以让我们尝试简化一些约束。CDGHI都相同(并等于输出)。EF也相同(并等于输入)。因此,我们的约束可以归结为:

  • AB和输出的长度,并且小于输入的长度。
  • B由全1组成,并且不是特别有用(它是程序的一部分,只是因为在现有的Brachylog解释器中,:{1<}a需要其左参数具有受限制的长度,否则解释器进入无限循环)。
  • 输出完全由大于1(即大于B的相应元素)的数字组成。
  • 输出元素的乘积等于输入。
  • 通过对输出进行排序不会改变输出(即按排序顺序)。

顺便说一句,我没有明确指定输出的所有元素都是整数,这似乎是必需的。但是,Brachylog的约束求解器无法处理非整数,因此它将方便地仅生成涉及整数的解决方案。

显然,“输出的长度小于输入”将是真每当输出是输入的乘法分区(因为2 X > X为所有非负X,即正2 X)。因此,我们可以忽略该约束;只有这样才能为Brachylog解释器提供评估程序的工作策略。其他约束(输出是排序的,其乘积是输入,并且其元素都大于1)是乘法分区的定义,因此,此功能基本上只是问题的直接实现。


6

Brachylog 1,14个字节

:{$pp~c:*ao}fd

在线尝试!

Brachylog 2,11个 10字节,语言晚于挑战

{ḋp~c×ᵐo}ᵘ

在线尝试!

Maltysen用17个字节的Pyth回答了这个问题,所以我想出了一个16字节的Brachylog解决方案,该解决方案通过将问题的规范翻译为Brachylog来工作。当我这样做时,Dennis编写了一个15字节的Jelly解决方案。所以我不得不减少到14个字节。该函数将输入作为参数,并返回所有分区的列表(而不是生成器,与我的其他解决方案一样)。

在我写完这个答案后的一段时间,我和丹尼斯设法将Jelly解决方案缩小到11个字节。事实证明,有一个新版本的Brachylog输出了,具有简短的语法。它推迟了挑战,所以实际上并没有算在内,但是它一发布就可以处理11字节的总数。如此处所示,该语言的后续修订版(受其他挑战的启发)可能低至10。这两个程序是相同的,唯一的区别是语法。

与我的其他解决方案不同,该解决方案没有大量使用“高尔夫原语”,而是直接指出了问题,该解决方案几乎忽略了Brachylog约束的所有功能,而是表现出最佳的果冻印象,为此编写了一系列约束左参数是已知的(因此约束简单地像果冻单子一样起作用,而不是成熟的约束)。因此,它使用与@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

为什么不编辑现有答案?
Downgoat

3
@Downgoat:这两个答案使用完全不同的方法。算法不同,使用的语言功能大多是独立的,等等。用较新的替换旧的是没有意义的(即使更长,我也可能发布了新的)。该元文章表明,在这种情况下,最好发布单独的答案。

1
我不知道您是否知道,但是您可以通过将TIO上的参数设置为变量(即大写字母)来检索输出。例如
致命

5

Mathematica,61个字节

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

定义一个(递归)一元运算符±,该运算符返回分区列表。


数学不是最后不需要分号吗?
Pavel

@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

@orlp好吧,然后回到Python 2。
xnor

TL; DR,我认为998输入不是太大;-) IMO是一个真正的很酷的代码,更像是延迟O(n),与Python 2竞争对手相比可能更具O(n^4)风格-而f(998)可能会耗尽内存或硬件可能在运行时死亡与其他算法相比,估计时间为80天,此算法在大约1200毫秒后收敛。在我的机器上7毫秒可以产生结果[[2, 499], [998]]。IMO的问题可能是更是为N > 998RecursionError: maximum recursion depth exceeded in comparison停止上述的Python 3代码...快乐高尔夫:-)
Dilettant

@Dilettant不知道O(n^4)我的Python2提交是否足够:D考虑到测试用例998,我的代码将运行9次,并(n+r-1)! / r! / (n-1)!每次计算元组的数量,其中rn从2线性增长9 - 2。但是,至少您不必调整递归限制...
Yytsi

@TuukkaX警告:我没有分析代码,只是略过了一下,比较了两个候选对象中运行时间的发展情况,直到N达到41,然后以为我只是提交了注释;-)堆栈和递归通常很容易,但是呼吁在不愉快的情况下有多深的类型问题……希望我对所进行的研究数量足够模糊
Dilettant

3

果冻14 13 11字节

Ḋx³ŒPQP=¥Ðf

在线尝试!

我相当确定@Dennis的Jelly解决方案可以得到改善。不幸的是,我没能击败Brachylog唱片,但我确实做到了。更新:在@Dennis的帮助下,现在已得到改进;我想果冻夺回了桂冠。

该程序效率极低,具有O(2 n 2)性能(这就是上面的测试用例针对输入4显示它的原因)。它在4上快速完成,在5上很慢,并且实际上不可能运行更大的数字。

有趣的是,从描述问题的解决方案(Brachylog擅长的)到使用基于输入分解的算法(Jelly擅长的)的解决方案对Brachylog进行了改进。同时,果冻液由移开提高它的优势,回到一个解决方案,只是描述的问题。

说明:

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

递归直接解决问题:对于从2n的每个整数m,我们取n / m的每个分区其最小元素为m(以避免重复分区),并追加m。(对于任何不除n的m,这将得到一个空数组,因为没有整数排列会乘以十进制。)我们将空数组的基本情况定义为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]

完整的程序。这可以改进很多,因此深深欢迎您提出建议!

输出范围是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

@Borsunho当我回滚旧版本时,我忘记在上添加+1 int(math.log(n,2)),这导致了这一点。+2个字节,它将起作用。谢谢!
Yytsi '16

您尚未导入,math但正在使用math.log
orlp 2016年

@orlp我有...?在第三行。
Yytsi

@TuukkaX对不起,我只看了进口的最上面的几行,因为它们几乎总是在那儿……也就是说,len(bin(n))-2比短int(math.log(n,2))
orlp 2016年


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])
扎卡里

无论如何,这甚至不是一个有效的答案,因为您需要导入std.stdiostd.range,输入1应该什么也不打印[1]
扎卡里

0

D,109位元组

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

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.