递增集序列


11

背景

一个前增加的一组序列的顺序被定义为整数集的序列s ^ 1S ^ 2小号Ñ其满足以下的:NS1,S2,,Sn

  • 每个是一个非空的子集{ 1 2 Ñ }Si{1,2,,N}
  • 对于小号小号+ 1 = ,即任何两个连续集没有共同的元素。1i<nSiSi+1=
  • 对于,平均的(平均值)小号比的严格更少小号+ 11i<nSiSi+1

挑战

给定一个正整数N,输出order的最长递增集合序列的长度N

测试用例

这些是基于Project Euler用户thundre的结果

1 => 1 // {1}
2 => 2 // {1} {2}
3 => 3 // {1} {2} {3}
4 => 5 // {1} {2} {1,4} {3} {4}
5 => 7 // {1} {2} {1,4} {3} {2,5} {4} {5}
6 => 10 // {1} {2} {1,4} {3} {1,4,5} {2,3,6} {4} {3,6} {5} {6}
7 => 15 // {1} {2} {1,4} {3} {1,2,7} {3,4} {1,2,5,7} {4} {1,3,6,7} {4,5} {1,6,7} {5} {4,7} {6} {7}
8 => 21
9 => 29
10 => 39
11 => 49
12 => 63
13 => 79
14 => 99
15 => 121
16 => 145
17 => 171
18 => 203
19 => 237
20 => 277
21 => 321
22 => 369
23 => 419
24 => 477
25 => 537

规则

适用标准规则。有效提交的最短字节数为准。

赏金

大约4年前在Project Euler论坛上已经在此问题上进行了讨论,但是我们未能提出可证明的多项式时间算法(用表示N)。因此,我将向首次提交的+200赏金给予奖励,或者证明其不可能。


我花了一个多星期的时间来尝试提出多项式时间算法或使用归约法的NP硬度证明。这里有人在这方面取得任何进展吗?
恩里科·博尔巴

Answers:


4

Brachylog,28个字节

⟦₁⊇ᶠk⊇pSs₂ᶠ{c≠&⟨+/l⟩ᵐ<ᵈ}ᵐ∧Sl

在线尝试!

这真是太慢了。大约需要30秒N = 3,而12分钟后并没有完成N = 4

说明

⟦₁                             Take the range [1, …, Input]
  ⊇ᶠk                          Find all ordered subsets of that range, minus the empty set
     ⊇                         Take an ordered subset of these subsets
      pS                       Take a permutation of that subset and call it S
       Ss₂ᶠ                    Find all substrings of 2 consecutive elements in S
           {           }ᵐ      Map for each of these substrings:
            c≠                   All elements from both sets must be different
              &⟨+/l⟩ᵐ            And the average of both sets (⟨xyz⟩ is a fork like in APL)
                     <ᵈ          Must be in strictly increasing order
                         ∧Sl   If all of this succeeds, the output is the length of L.

更快的版本,39字节

⟦₁⊇ᶠk⊇{⟨+/l⟩/₁/₁}ᵒSs₂ᶠ{c≠&⟨+/l⟩ᵐ<₁}ᵐ∧Sl

在计算机上,此过程大约需要50秒N = 4

这是同一程序,除了我们通过平均对子集的子集进行排序,而不是进行随机排列。因此,我们使用{⟨+/l⟩/₁/₁}ᵒ代替p

{         }ᵒ     Order by:
 ⟨+/l⟩             Average (fork of sum-divide-length)
      /₁/₁         Invert the average twice; this is used to get a float average

我们需要得到一个浮点平均值,因为我刚刚发现了一个荒谬的错误,其中的浮点数和整数不按值进行比较,而是按类型与排序谓词进行比较(这也是为什么我使用<ᵈ而不是<₁比较两个平均值;后者会要求双重反转技巧即可工作)。


我打算慢慢解决这个问题(因为@JonathanAllan在另一条评论中提到了它),但是我可能要等上几个星期才能提出来!最后,我喜欢(就像大多数Brachylog答案一样)看起来像对问题本身的巧妙重述。
sundar-恢复莫妮卡

@sundar,您随时可以稍后再返回并尝试重新发现解决方案!
致命的

3

CJam(81字节)

{YY@#(#{{2bW%ee{)*~}%}:Z~{)Z__1b\,d/\a+}%$}%{_,1>{2ew{z~~&!\~=>}%0&!}{,}?},:,:e>}

在线演示。它应该4在合理的时间内为输入执行,但是我不会尝试使用更高的输入。

解剖

{                 e# Declare a block (anonymous function)
  YY@#(#          e# There are 2^N subsets of [0, N), but the empty subset is problematic
                  e# so we calculate 2^(2^N - 1) subsets of the non-empty subsets
  {               e# Map integer to subset of non-empty subsets:
    {             e#   Define a block to map an bitset to its set indices; e.g. 9 => [0 3]
      2bW%ee      e#     Convert to base 2, reverse, and index
      {)*~}%      e#     If the bit was set, keep the index
    }:Z           e#   Assign the block to variable Z
    ~             e#   Evaluate it
    {             e#   Map those indices to non-empty subsets of [0, N):
      )Z          e#     Increment (to skip the empty set) and apply Z
      __1b\,d/    e#     Sum one copy, take length of another, divide for average
      \a+         e#     Wrap the subset and prepend its average value
    }%
    $             e#   Sort (lexicographically, so by average value)
  }%
  {               e# Filter out subsets of subsets with conflicts:
    _,1>{         e#   If the length is greater than 1
      2ew         e#     Take each consecutive pair of subsets
      {           e#     Map:
        z~        e#       Zip and expand to get [score1 score2] [subset1 subset2]
        ~&!\      e#       No element in common => 1
        ~=        e#       Different scores => 0
        >         e#       1 iff both constraints are met
      }%
      0&!         e#     1 iff no consecutive pair failed the test
    }{
      ,           e#   Otherwise filter to those of length 1
    }?
  },
  :,:e>           e# Map to size of subset and take the greatest
}

1

JavaScript(ES6),175个字节

天真且缓慢的递归搜索。大约需要15秒来计算TIO的前7个项。

n=>(a=[...Array(n)].reduce(a=>[...a,...a.map(y=>[x,...y],x=n--)],[[]]),g=(p,b=a,n)=>a.map(a=>(m=a.map(n=>s+=++k*b.includes(n)?g:n,s=k=0)&&s/k)>p&&g(m,a,-~n),r=r>n?r:n))(r=0)|r

在线尝试!

测试此修改版本以输出最长的递增设置序列。

怎么样?

{1,2,,n}a

a = [...Array(n)].reduce(a =>
  [...a, ...a.map(y => [x, ...y], x = n--)],
  [[]]
)

递归部分:

g = (                         // g = recursive function taking:
  p,                          //   p = previous mean average
  b = a,                      //   b = previous set
  n                           //   n = sequence length
) =>                          //
  a.map(a =>                  // for each set a[] in a[]:
    (m = a.map(n =>           //   for each value n in a[]:
      s +=                    //     update s:
        ++k * b.includes(n) ? //       increment k; if n exists in b[]:
          g                   //         invalidate the result (string / integer --> NaN)
        :                     //       else:
          n,                  //         add n to s
      s = k = 0)              //     start with s = k = 0; end of inner map()
      && s / k                //   m = s / k = new mean average
    ) > p                     //   if it's greater than the previous one,
    && g(m, a, -~n),          //   do a recursive call with (m, a, n + 1)
    r = r > n ? r : n         //   keep track of the greatest length in r = max(r, n)
  )                           // end of outer map()

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.