从1到n计数而没有任何连续数字


19

目标

您会得到一个整数nn > 1)。你必须输出的整数的许多排列如何1n有它启动1,在年底n,不具有相差1两个连续的整数。

或者,如果您拍摄完整的图形K_n并删除路径的边缘,则1-2-3-...-n必须在其余图形中计算从1到的哈密顿路径n

这些示例将f(n)用于一个函数,该函数接受n并输出有效排列的数量,但是您提交的内容可以是一个函数或一个程序。


例子

对于n = 6,可能的解决方案是1-3-5-2-4-6

但是,1-3-5-2-6-4这不是有效的解决方案,因为它没有以结尾6

实际上,对于n = 6,只有2个解决方案(1-4-2-5-3-6另一个是)。

因此f(6) = 2


对于n = 4开始于1和结束于的唯一排列41-2-3-41-3-2-4。在这两个中,都与2相邻3,从而给出相差1的连续整数f(4) = 0


测试用例

f(6) = 2
f(4) = 0
f(8) = 68
f(13) = 4462848

获奖标准

这是代码高尔夫球,答案最短。


7
您看到的,孩子们,您不能只检查有多少个排列不[2..n-1]包含1或的增量-1,还必须检查它们是否没有2n-1... 开头或结尾...
ETHproductions

1
列表是否必须以1开头并以数字结尾?
Okx

3
也许OP的意思是“相邻”而不是“连续”?
Stilez

6
奇怪的是,序列在这里:algo.inria.fr/libraries/autocomb/graphs99.ps在第6页上写的地方,Q_ser:=z + 2 z^6 + 10 z^7 + 68 z^8 + 500 z^9 + 4174 z^10 + 38774 z^11 + 397584z^12 + 4462848 z^13 + 54455754 z^14我现在花一些时间尝试使用公式,但是我无法编写一个生成序列的公式。惊人地看到z的指数是公式的输入,而结果是乘法因子。如何从中推导公式的一种方法可能是答案最短的一种字节形式
Christiaan Westerbeek

1
@ChristiaanWesterbeek,称为序列的生成函数。存在许多具有生成函数的序列,这些序列具有比序列本身更好的封闭形式,这很酷!
Carmeister '17

Answers:


6

MATL,16字节

qtq:Y@0&Yc!d|qAs

在线尝试!

对于超出的输入,12它将耗尽内存。

说明

q      % Implicitly input n. Push n-1
tq     % Duplicate and subtract 1: pushes n-2
:      % Range [1 2 ... n-2]
Y@     % Matrix with all permutations, each in a row
0      % Push 0
&Yc    % Append n-1 and predend 0 to each row
!      % Tranpose
d      % Consecutive differences along each column
|      % Absolute value
q      % Subtract 1
A      % All: true if all values in each column are non-zero
s      % Sum. Implicitly display

1
工作正常,做得很好:)
Philippe

1
尽管在此问题上确实取得了一些不错的进步,但是您的解决方案仍然是最短的。它也比果冻快。恭喜!
菲利普

19

Mathematica,58个字节,多项式(n)时间

Abs[Sum[(k-1)Hypergeometric2F1[k,k-#,2,2](#-k)!,{k,#}]-1]&

怎么运行的

与其使用蛮力迭代排列,不如使用包含-排除原理对它们进行组合计数。

设S是该组的所有排列的[1,...,N]与σ 1 = 1,σ Ñ = Ñ,并令S 是集合置换σ∈S,从而使|σ - σ + 1 | =1。那么我们要寻找的数量是

| S | - | S 1 ∪⋯∪小号ñ - 1 | =Σ 2≤ ķÑ + 1; 1≤ 2 <⋯< ķ - 1 < Ñ(-1)的k - 2 | S 2 ∩⋯∩小号ķ - 1 |。

现在,| S 2 ∩⋯∩小号ķ - 1 | 仅取决于k和[ i 1i 2,…,i k -1i k ]中连续索引的游程数j,为方便起见,我们将i 1 = 0和i k = n固定。特别,

| S 2 ∩⋯∩小号ķ - 1 | = 2 Ĵ - 2Ñ - ķ)!2≤ ĴķÑ
| S 2 ∩⋯∩小号ķ - 1 | = 1,对于j = 1,k = n + 1。

带有j游程的此类索引集[ i 1i 2,…,i k − 1i k ]的数量为

k − 1摄氏度 Ĵ - 1)( ñ - ķ Ç Ĵ - 2),2≤ Ĵ ķ Ñ
如图1所示, Ĵ = 1, ķ = Ñ + 1。

结果是

(-1)ñ - 12≤ ķÑ Σ 2≤ Ĵķ (-1)ķ - 2 ķ - 1 c ^ Ĵ - 1)( ñ - ķ Ç Ĵ - 2)2 Ĵ - 2 n - k)!

j的内部和可以使用超几何2 F 1函数来写:

(-1)ñ - 12≤ ķ Ñ(-1) ķ ķ - 1) 2 ˚F 1(2 - ķ ķ - Ñ ; 2; 2)( ñ - ķ)!

我们对其应用了Pfaff变换,使我们可以使用绝对值消除-1的幂:

(-1)ñ - 12≤ ķÑ(-1)Ñķ - 1)2 ˚F 1ķķ - Ñ ; 2; 2)(ñ - ķ)!
= | -1 +Σ 1≤ ķÑķ - 1)2 ˚F 1ķķ - Ñ ; 2; 2)(ñ - ķ!)|。

演示版

In[1]:= Table[Abs[Sum[(k-1)Hypergeometric2F1[k,k-#,2,2](#-k)!,{k,#}]-1]&[n],{n,50}]

Out[1]= {1, 0, 0, 0, 0, 2, 10, 68, 500, 4174, 38774, 397584, 4462848, 

>    54455754, 717909202, 10171232060, 154142811052, 2488421201446, 

>    42636471916622, 772807552752712, 14774586965277816, 297138592463202402, 

>    6271277634164008170, 138596853553771517492, 3200958202120445923684, 

>    77114612783976599209598, 1934583996316791634828454, 

>    50460687385591722097602304, 1366482059862153751146376304, 

>    38366771565392871446940748410, 1115482364570332601576605376898, 

>    33544252621178275692411892779180, 1042188051349139920383738392594332, 

>    33419576037745472521641814354312790, 

>    1105004411146009553865786545464526206, 

>    37639281863619947475378460886135133496, 

>    1319658179153254337635342434408766065896, 

>    47585390139805782930448514259179162696722, 

>    1763380871412273296449902785237054760438426, 

>    67106516021125545469475040472412706780911268, 

>    2620784212531087457316728120883870079549134420, 

>    104969402113244439880057492782663678669089779118, 

>    4309132147486627708154774750891684285077633835734, 

>    181199144276064794296827392186304334716629346180848, 

>    7800407552443042507640613928796820288452902805286368, 

>    343589595090843265591418718266306051705639884996218154, 

>    15477521503994968035062094274002250590013877419466108978, 

>    712669883315580566495978374316773450341097231239406211100, 

>    33527174671849317156037438120623503416356879769273672584588, 

>    1610762789255012501855846297689494046193178343355755998487686}

3
我很激动,干得好
菲利普

6

果冻17 16 字节

ṖḊŒ!ð1;;⁹IỊṀðÐḟL

单子链接。

在线尝试!

怎么样?

ṖḊŒ!ð1;;⁹IỊṀðÐḟL - Link: number n
Ṗ                - pop (implicit range build) -> [1,n-1]
 Ḋ               - dequeue -> [2,n-1]
  Œ!             - all permutations of [2,n-1]
    ð       ðÐḟ  - filter discard those entries for which this is truthy:
     1;          -   1 concatenated with the entry
       ;⁹        -   ...concatenated with right (n)
         I       -   incremental differences
          Ị      -   is insignificant (absolute value <=1)
           Ṁ     -   maximum
               L - length (the number of valid arrangements)

抱歉,它不符合测试用例
Philippe

1
是的,您也犯了同样的错误,Okx和我起初犯了错。您必须考虑以下事实:第二个数字不能为2,倒数第二个数字不能为n-1
ETHproductions'July

@Philippe修复了它。
乔纳森·艾伦,

我认为使用IỊṀ无效。具体来说,-2例如那里的一个三角洲怎么办?您可以用IAỊṀ+1 解决。
暴民埃里克(Erik the Outgolfer)'17年

1
@JonathanAllan Ooh我以为它回来了x <= 1
暴民埃里克(Erik the Outgolfer)'17年

5

Japt19 18字节

o2 á è_pU äÉ m²e>1

在线测试!我不建议在大于的任何值上进行测试10

说明

o2 á è_  pU äÉ  m²  e>1
o2 á èZ{ZpU ä-1 mp2 e>1}
                          : Implicit: U = input integer
o2                        : Create the range [2..U-1].
   á                      : Generate all permutations of this range.
     èZ{               }  : Check how many permutations Z return a truthy value:
        ZpU               :   Push U to the end of Z.
            ä-1           :   Push 1 to the beginning of Z, then take the difference
                          :   of each pair of items.
                m         :   Map each item X to
                 p2       :     X ** 2. This gives a number greater than 1 unless the
                          :     item is 1 or -1.
                    e>1   :   Return whether every item in this list is greater than 1.
                          :   This returns `true` iff the permutation contains no
                          :   consecutive pairs of numbers.
                          : Implicit: output result of last expression

做得好!滑稽我的蛮力代码怎么不能克服N = 13既不AHAH
菲利普

@Philippe我不建议接受这么快,我敢肯定,在05AB1E或Jelly中它会更短;-)
ETHproductions'Jul

在测试用例上失败1
Okx

2
@Okx OP已指定我们可以假设n > 1
ETHproductions


5

哈斯克尔(76) 65字节

@xnor节省了11个字节。

使用Q_rec@ChristiaanWesterbeek的发现的第7页的结果,我们得到

f 1=1
f n|n<6=0
f n=sum$zipWith((*).f)[n-5..][n-4,1,10-2*n,4,n-2]

我不明白他们的下一个结果 ha与此相关,但是在加快速度之后(首先通过记忆,请参见早期版本,然后如下所示),我得到了他们的电话号码。

尽管上面的方法还可以n=20,但本质上是一个示例,说明如何不进行递归。这是一个更快的版本(仅适用于n>=6),它也只需要恒定的内存-如果只是数字没有持续增加...

f n=last$foldl(#)[1,0,0,0,0][6..n]
l#n=tail l++[sum$zipWith(*)l[n-4,1,10-2*n,4,n-2]]

那给

Prelude> f 50
1610762789255012501855846297689494046193178343355755998487686
Prelude> f 500
659178618863924802757920269977240274180092211041657762693634630044383805576666007245903670780603497370173231423527767109899936008034229541700392144282505597945561328426013937966521561345817045884498867592832897938083071843810602104434376305964577943025310184523643816782047883794585616331928324460394146825636085453532404319881264974005968087265587062691285454120911586459406436421191277596121471930913837355151842093002557978076653884610826296845041929616496533544124347765641367732716560025553179112645454078955409181466212732427071306363820080109636358537270466838558068527692374178581063316309789026101221004745226182671038004326069705775312654329754698423385241664984156235692539255677944294995403233446243315371404887473868003155621849544566385172835597260848972758443874423271017007843907015007416644383573987606586308556317833384896267539628278571497402655322562624217658332870157802254043614726316296058329670971054977099155788604175817828380564156329839201579006169173002756295957371639199917376529472990059986681882194726437566769717959443857298155265292535858523609764515938314672724480762724541633037484152303637096

也没有问题,f 5000但我不想粘贴结果...


顺便说一句,有可能不使用花哨的数学并且仍然不使用(超)蛮力。首先,而不是查看所有排列,而是查看部分排列,仅在它们尚未无效时才对其进行扩展。查看以开头的所有排列是没有用的1 6 5。其次,一些部分置换喜欢1 3 5 71 5 3 7具有完全相同的有效延续,因此将它们一起处理。使用这些想法,我最多可以计算n=16 0.3s 的值。


您可以通过提取系数来使递归表达式写得像点一样短f n=sum$zipWith((*).f)[n-5..][n-4,1,10-2*n,4,n-2]
xnor

@xnor对,谢谢!
Christian Sievers

这是一项很好的工作,这个社区的成果令我感到惊讶!太糟糕了,它是高尔夫^^
Philippe

4

Python,125个字节

from itertools import*
lambda n:sum(p[-1]-p[0]==n-1and all(~-abs(x-y)for x,y in zip(p,p[1:]))for p in permutations(range(n)))

看起来很快,干得好!
菲利普


3

Mathematica,66个字节

Count[Permutations@Range@#,x:{1,__,#}/;FreeQ[Differences@x,1|-1]]&

说明

Function第一个论点#

Count[                                                             (* Count the number of *)
      Permutations@                                                (* permutations of *)
                   Range@#,                                        (* the list {1, ..., #} *)
                           x:{1,__,#}                              (* of the form {1, __, #} *)
                                     /;                            (* such that *)
                                             Differences@x,        (* the list of differences of consecutive elements *)
                                       FreeQ[                      (* is free of elements of the form *)
                                                           1|-1    (* 1 or -1 *)
                                                               ]]&

3

Javascript(ES6),100 74 72 60字节

f=n=>n--<6?!n|0:f(n)*--n+4*f(n--)-2*f(n--)*--n+f(n)*++n+f(n)

以下是@PeterTaylor掌握高尔夫之前的版本

f=n=>n<6?n==1|0:(n-4)*f(n-5)+f(n-4)-2*(n-5)*f(n-3)+4*f(n-2)+(n-2)*f(n-1)

感谢@ChristianSievers的答复,该答复设法从论文中起草了Haskell解决方案我在谷歌搜索“ 0、2、10、68、500、4174、38774、397584”后发现中,这是一个Javascript版本,它也不会置换。

用法

for (i=1; i<=20; i++) {
  console.log(i, f(i))
}

1 1 
2 0 
3 0 
4 0 
5 0 
6 2 
7 10 
8 68 
9 500 
10 4174 
11 38774 
12 397584 
13 4462848 
14 54455754 
15 717909202 
16 10171232060 
17 154142811052 
18 2488421201446 
19 42636471916622 
20 772807552752712

1
任务描述只问f(n)什么时候n>1,所以返回什么都没有关系n=1。我也认为f(1)=1是正确的。
Christian Sievers

您可以结合特殊情况n<6?n==1|0:,以进一步节省两个字符。
彼得·泰勒

大。我调整了这2条评论。
克里斯蒂安·韦斯特贝克

1
通过对术语进行重新排序并依靠评估的顺序,有可能降至60:f=n=>n--<6?!n|0:f(n)*--n+4*f(n--)-2*f(n--)*--n+f(n)*++n+f(n)
Peter Taylor

1

Brachylog,26个字节

{⟦₁pLh1&~tLs₂ᶠ{-ȧ>1}ᵐ}ᶜ|∧0

在线尝试!

说明

{                    }ᶜ       Output = count the number of outputs of:
 ⟦₁pL                           L is a permutation of [1, …, Input]
    Lh1                         The head of L is 1
       &~tL                     The tail of L is the Input
          Ls₂ᶠ                  Find all sublists of length 2 of L
              {    }ᵐ           Map on each sublist:
               -ȧ>1               The elements are separated by strictly more than 1
                       |      Else (no outputs to the count)
                        ∧0    Output = 0

1

Python 3中109个 107 102字节

q=lambda s,x,n:sum(q(s-{v},v,n)for v in s if(v-x)**2>1)if s else x<n;f=lambda n:q({*range(2,n)},1,n-1)

在线尝试!

通过不尝试使函数单行(如@shooqie所建议的那样)删除了四个字节,并通过替换abs为正方形删除了另一个字节。(需要Python 3.5+)




0

Mathematica,134个字节

(s=Permutations@Range[2,#-1];g=Table[Join[Prepend[s[[i]],1],{#}],{i,Length@s}];Length@Select[Union@*Abs@*Differences/@g,FreeQ[#,1]&])&


测试用例n:2到12

{0,0,0,0,2,10,68,500,4174,38774,397584}


0

Python 2,105个字节

lambda n:reduce(lambda a,i:a+[i*a[-5]+a[-4]+2*(1-i)*a[-3]+4*a[-2]+(i+2)*a[-1]],range(2,n),[0,1]+4*[0])[n]

在线尝试!

这是基于@Christiaan Westerbeek发现的Philippe Flajolet 的论文;它比我列举了可能排列的Python 3解决方案要快得多,而且短了两个字节。(在Python 3中,reduce已经烦人地移至functools。)

使用numpy的点积的版本要短得多,但是溢出非常快,需要导入numpy。但是对于它的价值:

lambda n:reduce(lambda a,i:a+[dot([i,1,2-2*i,4,i+2],a[-5:])],range(2,n),[0,1]+4*[0])[n]
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.