查找所有不同的Gozinta链


36

Gozinta链

(受Euler项目#606的启发)

n的gozinta链是{1,a,b,...,n}每个元素正确划分下一个元素的序列。例如,有八个不同的gozinta链用于12:

{1,12}, {1,2,12}, {1,2,4,12}, {1,2,6,12}, {1,3,12}, {1,3,6,12}, {1,4,12} and {1,6,12}.

挑战

编写一个接受正整数(n > 1)并输出或返回给定数字的所有不同gozinta链的程序或函数。

  1. 链条的顺序很重要(升序),链条的顺序无关紧要。
  2. 如果存在这种可能性,您就不能使用内置的解决方案来解决挑战。
  3. 这是

编辑:删除1作为潜在的输入。


4
欢迎来到PPCG。不错的第一个问题!
AdmBorkBork

5
“在偶然的情况下,它存在[(看着你,Mathematica!)]”
Outgolfer的Erik

3
作为AdmBorkBork说,边缘案件一般只增加了,如果他们要挑战的核心重要-如果你想有一个原因,只有[[1]]我会说,如果[1,1]是的gozinta 1然后[1,1,12]是的gozinta 12的是[1,1,1,12],现在我们可以不再“全部退回……”
乔纳森·艾伦

4
您应该对不知道的人说双关语。2|4读为“二进四出”,又名“二进四出”。
mbomb007 '17

1
两个半小时不足以使沙箱正常工作。请参阅沙盒常见问题解答
彼得·泰勒

Answers:


10

Python 3中68 65个字节

编辑: -3字节感谢@notjagan

f=lambda x:[y+[x]for k in range(1,x)if x%k<1for y in f(k)]or[[x]]

在线尝试!

说明

每个gozinta链均由链x末的数字组成,并在其左侧至少有一个约数。对于链的每个除数k,都是不同的。因此,对于每个除数,我们可以找到其所有不同的gozinta链 并追加到它们的末尾,以得到所有不同的gozinta链这些链直接位于的左侧。递归执行此操作,直到返回到位置为止,因为所有gozinta链均以 1开头,这意味着递归已触底。x[1,...,k,x]kxkxx = 1[[1]]

由于Python列表理解功能允许两次迭代,因此代码变得如此简短。这意味着可以将其中找到的值f(k)添加到所有不同除数的相同列表中k


试图这样做,现在为时已晚= /
Rod Rod

3
与迄今为止的其他答案相比,该答案非常快。
ajc2000 '17

-3字节,通过删除不必要的列表拆包。
notjagan

7

外壳,13个字节

ufo=ḣ⁰…ġ¦ΣṖḣ⁰

H.PWiz的方法有些不同,尽管仍然是蛮力的。在线尝试!

说明

基本思想是连接的所有子序列,[1,...,n]并将结果拆分为子列表,其中每个元素将下一个元素划分。其中,我们保留以开头1,以结束n且不包含任何重复项。这是通过内置的“ rangify”完成的。然后保留丢弃重复项。

ufo=ḣ⁰…ġ¦ΣṖḣ⁰  Input is n=12.
           ḣ⁰  Range from 1: [1,2,..,12]
          Ṗ    Powerset: [[],[1],[2],[1,2],[3],..,[1,2,..,12]]
         Σ     Concatenate: [1,2,1,2,3,..,1,2,..,12]
       ġ¦      Split into slices where each number divides next: [[1,2],[1,2],[3],..,[12]]
 fo            Filter by
      …        rangified
   =ḣ⁰         equals [1,...,n].
u              Remove duplicates.

我猜想过滤掉幂集中每个数字除以下的数组会更短吗?
ETHproductions

@ETHproductions不,那再长一个字节
Zgarb

5

果冻9 8字节

ÆḌ߀Ẏ;€ȯ

在线尝试!

使用与Japt答案相似的技术,因此可以在较大的测试用例上非常快速地运行。

怎么运行的

ÆḌ߀Ẏ;€ȯ    Main link. Argument: n (integer)
ÆḌ          Yield the proper divisors of n.
       ȯ    If there are no divisors, return n. Only happens when n is 1.
  ߀        Otherwise, run each divisor through this link again. Yields
            a list of lists of Gozinta chains.
    Ẏ       Tighten; bring each chain into the main list.
     ;€     Append n to each chain.

4

Mathematica,77个字节

FindPath[Graph@Cases[Divisors@#~Subsets~{2},{m_,n_}/;m∣n:>m->n],1,#,#,All]&

形成一个a Graph,其中顶点是Divisors输入的#,边表示适当的可整除性,然后找到All从顶点1到顶点的路径#


1
哇,这很聪明!
JungHwan Min

3

果冻,12 字节

ŒPµḍ2\×ISµÐṀ

一个接受整数并返回整数列表的单子链接。

在线尝试!

怎么样?

我们希望所有在一个和N之间的唯一整数排序列表,这样第一个是一个,最后一个是N,并且所有对都分开。该代码通过检查在相关范围的幂集上是否满足成对除法条件来实现此过滤器,但是仅选择那些增量差总和最大的对象(既以1开头又以N结尾的那些) N-1的增量差异之和,其他差异则较小)。

ŒPµḍ2\×ISµÐṀ - Link: number N
ŒP           - power-set (implicit range of input) = [[1],[2],...,[N],[1,2],[1,3],...,[1,N],[1,2,3],...]
          ÐṀ - filter keep those for which the result of the link to the left is maximal:
  µ      µ   - (a monadic chain)
    2\       -   pairwise overlapping reduce with:
   ḍ         -     divides? (1 if so, 0 otherwise)
       I     -   increments  e.g. for [1,2,4,12] -> [2-1,4-2,12-4] = [1,2,8]
      ×      -   multiply (vectorises) (no effect if all divide,
             -                          otherwise at least one gets set to 0)
        S    -   sum         e.g. for [1,2,4,12] -> 1+2+8 = 11 (=12-1)

等一下n重叠是否减少?:o我怎么从没看到:PI在使用<slice>2<divisible>\<each>:P
HyperNeutrino

使用对Jelly的quicks的最新更改,您可以使用11个字节Ɲ代替2 。
Xcoder先生18年

3

Japt,17个字节

⬣ßX m+S+UR÷ª'1

在线测试!

奇怪的是,将输出生成为字符串比将其生成为数组数组要容易得多。

说明

 ⬠£  ßX m+S+URà ·  ª '1
Uâq mX{ßX m+S+UR} qR ||'1   Ungolfed
                            Implicit: U = input number, R = newline, S = space
Uâ                          Find all divisors of U,
  q                           leaving out U itself.
    mX{         }           Map each divisor X to
       ßX                     The divisor chains of X (literally "run the program on X")
          m    R              with each chain mapped to
           +S+U                 the chain, plus a space, plus U.
                  qR        Join on newlines.
                     ||     If the result is empty (only happens when there are no factors, i.e. U == 1)
                       '1     return the string "1".
                            Otherwise, return the generated string.
                            Implicit: output result of last expression

那么,您的方法是否像其他方法一样避免生成无效链然后对其进行过滤呢?
遮阳伞

@Umbrella Nope,它一次只生成有效除数,一次只除数,因此即使在诸如12000的情况下,它也能如闪电般快速工作:-)
ETHproductions'Aug

非常不错的使用递归的:)而且我切口是¬招!:p
Shaggy

@Shaggy ¬是为什么我实现了一堆基本上“不给X给出参数,或者给Y给出真实参数”的原因之一:P
ETHproductions

3

Mathematica,60个字节

Cases[Subsets@Divisors@#,x:{1,___,#}/;Divisible@@Reverse@{x}]&

用途的无证多ARG的形式Divisible,其中Divisible[n1,n2,...]的回报True,如果n2∣n1n3∣n2等,以及False其他。我们采取所有Subsets的列表的Divisors输入#,然后返回Cases的形式{1,___,#},从而Divisible使TrueReverse除数的d序列。


那么,Divisible基本上是用于验证gozinta链的内置函数吗?
遮阳伞

@Umbrella它不会检查适当的除数。
ngenisis

3

Haskell,51个字节

f 1=[[1]]
f n=[g++[n]|k<-[1..n-1],n`mod`k<1,g<-f k]

递归找到适当除数的gozinta链并追加n

在线尝试!


我认为应该有适当处理的额外信誉1。既然我们共同得出了豁免的结论1,那么删除该案例可以节省10个字节吗?
遮阳伞

@Umbrella 1不是此算法的特殊情况,它是递归的基础情况。仅靠第二个定义方程式只能返回空列表。
Christian Sievers

我懂了。我的解决方案(尚未发布)[[1]]也用作基础。
遮阳伞

3

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)

由于guard需要Control.Monad导入,因此需要Lambdabot Haskell 。主要功能是一个匿名功能,我被告知允许该功能,并且可以节省几个字节。

感谢Laikoni节省了七个字节。

说明:

Monad非常方便。

x # y

这是我们所有实际工作的递归函数。x是我们要累加的数字(保留在值中的除数的乘积),并且y是下一个我们应该尝试除以的数字。

 | x == y = [[x]]

如果x等于,y那么我们就完成了递归操作。只需将其x用作当前gozinta链的末端并返回即可。

 | 1 > 0 =

Haskell高尔夫运动为“ True”。也就是说,这是默认情况。

(guard (mod x y < 1) >>

我们现在在列表monad内部进行操作。在monad列表中,我们可以同时做出多项选择。通过穷举找到某物的“所有可能”时,这非常有用。该guard语句说“如果条件为真,则仅考虑以下选择”。在这种情况下,仅在y除法时考虑以下选择x

(y:) . map (y *) <$> div x y#2)

如果y不分割x,我们可以选择添加y到gozinta链中。在这种情况下,递归调用(#),开始了在y = 2x等于x / y,因为我们要“因素去”是y我们刚才添加到链。然后,无论此递归调用的结果如何,都将其值乘以y我们刚刚得出的结果,并y正式添加到gozinta链中。

++

还要考虑以下选择。这只是将两个列表加在一起,但是单调地我们可以认为它是“选择在执行此操作还是在此其他操作之间选择”。

x # (y + 1)

另一种选择是简单地继续递归而不使用值y。如果y不分割,x则这是唯一的选择。如果y不进行除法,x则将采用该选项以及其他选项,并且将合并结果。

map (1 :) . (# 2)

这是主要的gozinta功能。它通过调用(#)其参数来开始递归。A 1附加在每个gozinta链上,因为该(#)函数永远不会将其放入链中。


1
很好的解释!您可以通过将所有模式保护放在一行中来节省一些字节。mod x y==0可以缩短为mod x y<1。由于允许使用匿名函数,因此您的主函数可以写为无点数map(1:).(#2)
Laikoni '17

3

Haskell中,107个 100 95字节

f n=until(all(<2).map head)(>>=h)[[n]]
h l@(x:_)|x<2=[l]|1<2=map(:l)$filter((<1).mod x)[1..x-1]

也许有更好的终止条件(尝试了类似

f n=i[[n]]
i x|g x==x=x|1<2=i$g x
g=(>>=h)

但时间更长)。由于要检查1重复1s或重复项(nub不在中Prelude)的字节数更多,因此检查是否明智。

在线尝试。


3
(>>=h)for(concatMap h)
Michael Klein


u
真是

3

JavaScript(Firefox 30-57),73个字节

f=n=>n>1?[for(i of Array(n).keys())if(n%i<1)for(j of f(i))[...j,n]]:[[1]]

方便的n%0<1是错误的。


2

果冻,17个字节

ḊṖŒP1ppWF€ḍ2\Ạ$Ðf

在线尝试!


那太快了。不过,您的结果1是出乎意料的。我尚未找到明确的结果1,但我认为是[[1]]。我不能肯定地说这[1,1]是不正确的,除了所有其他结果都在增加序列。有什么想法吗?

@Umbrella您可能希望让答案为1。做任何事情
Xcoder先生

@Umbrella如果这是一个问题,我都可以给+2(替换;€;Q¥€)。
暴民埃里克(Erik the Outgolfer)'17年

2

Mathematica,104个字节

(S=Select)[Rest@S[Subsets@Divisors[t=#],FreeQ[#∣#2&@@@Partition[#,2,1],1>2]&],First@#==1&&Last@#==t&]&

FreeQ[...]可以成为And@@BlockMap[#∣#2&@@#&,#,2,1]
JungHwan Min

非常好!但是我得到了一条额外的消息DeveloperPartitionMap :: nlen:-找不到消息文本->>`为什么?
J42161217

BlockMapDeveloper`PartitionMap内部使用该函数,但是由于它是开发人员函数,因此没有错误消息。该错误是由具有1个或0个元素的列表引起的,不能使用它们进行2个分区。
JungHwan Min

2

Mathematica,72个字节

Cases[Subsets@Divisors@#,{1,___,#}?(And@@BlockMap[#∣#2&@@#&,#,2,1]&)]&

说明

Divisors@#

查找输入的所有除数。

Subsets@ ...

生成该列表的所有子集。

Cases[ ... ]

选择所有与模式匹配的案例...

{1,___,#}

以1开头,以<input>... 结尾

?( ... )

并满足条件...

And@@BlockMap[#∣#2&@@#&,#,2,1]&

左侧元素将右侧元素划分为列表的所有2个分区,偏移量为1。


2

TI-BASIC,76个字节

Input N
1→L1(1
Repeat Ans=2
While Ans<N
2Ans→L1(1+dim(L1
End
If Ans=N:Disp L1
dim(L1)-1→dim(L1
L1(Ans)+L1(Ans-(Ans>1→L1(Ans
End

说明

Input N                       Prompt user for N.
1→L1(1                        Initialize L1 to {1}, and also set Ans to 1.

Repeat Ans=2                  Loop until Ans is 2.
                              At this point in the loop, Ans holds the
                              last element of L1.

While Ans<N                   While the last element is less than N,
2Ans→L1(1+dim(L1              extend the list with twice that value.
End

If Ans=N:Disp L1              If the last element is N, display the list.

dim(L1)-1→dim(L1              Remove the last element, and place the new
                              list size in Ans.

L1(Ans)+L1(Ans-(Ans>1→L1(Ans  Add the second-to-last element to the last
                              element, thereby advancing to the next
                              multiple of the second-to-last element.
                              Avoid erroring when only one element remains
                              by adding the last element to itself.

End                           When the 1 is added to itself, stop looping.

如果可以通过取消Ans> 1检查和循环条件,而又允许因错误而不是正常退出而又节省了5个字节。但是我不确定这是允许的。


您是否在计算器中输入了此字?因为那是出乎意料的,而且令人印象深刻。
遮阳伞

是的 TI-BASIC的棘手部分是只有全局变量,因此我不得不有效地使用列表本身作为递归堆栈。
calc84maniac

2

Mathematica 86 77字节

Select[Subsets@Divisors@#~Cases~{1,___,#},And@@BlockMap[#∣#2&@@#&,#,2,1]&]&

通过定义蛮力。

希望有一种较短的方法可以对列表进行成对的顺序元素比较。

感谢@Jenny_mathy和@JungHwanMin为节省9个字节的建议


1
您可以使用FreeQ[#∣#2&@@@Partition[#,2,1],1>2]&](作为第二个参数)转到82个字节
J42161217 '17

@Jenny_mathy或更好,And@@BlockMap[#∣#2&@@#&,#,2,1]
JungHwan Min


0

PHP 147 141

编辑以删除多余的测试

function g($i){$r=[[1]];for($j=2;$j<=$i;$j++)foreach($r as$c)if($j%end($c)<1&&$c[]=$j)$r[]=$c;foreach($r as$c)end($c)<$i?0:$R[]=$c;return$R;}

解释:

function g($i) {

15个字符的模板:(

    $r = [[1]];

将结果集初始化[[1]]为每条链从1开始。这也导致支持1作为输入。

    for ($j = 2; $j <= $i; $j++) {
        foreach ($r as $c) {
            if ($j % end($c) < 1) {
                $c[] = $j;
                $r[] = $c;
            }
        }
    }

对于从2到的$i每个数字,如果gozinta,我们将以当前数字扩展集合中的每个链,然后将扩展的链添加到我们的结果集中。

    foreach ($r as $c) {
        end($c) < $i ? 0 : $R[] = $c;
    }

过滤掉我们没有做到的中间链 $i

    return $R;
}

10个字符的模板:(


-1

Mathematica

f[1] = {{1}};
f[n_] := f[n] = Append[n] /@ Apply[Join, Map[f, Most@Divisors@n]]

应答被缓存以用于其他呼叫。


1
欢迎光临本站!这是一个代码高尔夫球,因此您应该包括字节数,并尝试删除所有多余的空白,我怀疑您有一些空白。
小麦巫师
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.