长度为n的魔术序列


11

魔术序列的非负整数序列x[0..n-1],从而有确切x[i]的情况下,i

例如,6,2,1,0,0,0,1,0,0,0是一个魔术序列,因为有6个0、2个1等。

编写一个函数,当给定n时,输出长度为n的所有魔术序列


可以在10秒内获得n最大值的正确输出的程序。(尽管欢迎所有程序)

例如,爱丽丝的程序可以在10秒内处理多达n = 15,而鲍勃的程序可以在同一时间内处理多达n = 20。鲍勃赢了。

平台:Linux 2.7GHz @ 4 CPU


5
欢迎来到PPCG!这是一个巨大的挑战,但是您需要一个成功的标准。例如,您可以说获胜者是最短的程序。
Ypnypn

1
相关信息:自描述数字
Sp3000,2015年

2
发布答案后,请勿更改获奖标准。而且,至少在我看来,这比打高尔夫球比打最快的代码要好得多。
Alex A.

2
@xnor您可以首先生成n的整数分区,然后检查它们是否可以自我描述。
马丁·恩德

2
n>5没有形式的解决方案最小 的是[n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]什么?我一直在寻找n=20,但没有找到,并且想知道我是否在犯错误。
xnor

Answers:


19

Python中,n≈10 8

def magic_sequences(n):
    if n==4:
        return (1, 2, 1, 0),(2, 0, 2, 0) 
    elif n==5:
        return (2, 1, 2, 0, 0),
    elif n>=7:
        return (n-4,2,1)+(0,)*(n-7)+(1,0,0,0),
    else:
        return ()

这使用了一个事实,我将证明,唯一的Magic长度序列n是:

  • [1, 2, 1, 0][2, 0, 2, 0]n=4
  • [2, 1, 2, 0, 0] 对于 n=5
  • [n-4, 2, 1, 0, 0, ..., 0, 0, 1, 0, 0, 0] 对于 n>=7

因此,对于n>=7,只需返回一个巨大的元组。我最多可以n=10^8在笔记本电脑上进行此操作,这可能受内存限制。再也没有了。(感谢trichoplax使用元组而不是列表的想法。)或者,如果可以打印一个非零条目的字典{0:n-4, 1:2, 2:1, (n-4):1},则可以对ginormous执行此操作n

我证明的独特性n>=7; 其他的可以通过蛮力或案例检查。

的总和l是列表中所有数字的总数,即其长度n。该列表具有l[0]零,因此n-l[0]非零项。但是根据定义,它l[0]必须为非零,否则我们将产生一个矛盾,并且其他每个非零条目至少为1。这已经占的总和l[0] + (n-l[0]-1)*1 = n-1之和n。因此,不算在内l[0],最多只能有1 2,且条目数不得大于2。

但这意味着唯一的非零项是l[0], l[1], l[2], and l[l[0]],其值最多为l[0]一个排列,的排列为1,1,2最大值l[0]+4。由于该和n至少为7,l[0]>=3所以我们有,依此类推l[l[0]]=1。现在,有至少一个1装置,该装置l[1]>=1,但如果l[1]==1这是另一个1,所以l[1]>=2,这意味着l[1]是孤独的2。这给出了l[2]=1,而所有剩余的条目都是0,所以l[0]=n-4,完成了解决方案。


语言是...?
edc65

@ edc65看起来像python。但我不确定。
伊斯梅尔·米格尔

4

Python 3,n≈40

def plausible_suffix(l,N):
    if sum(l)>N:
        return False

    pairs = [(N-1-i,l[i]) for i in range(len(l))]

    if sum(i*x for i,x in pairs)>N:
        return False

    num_remaining = N - len(l)

    for index, desired_count in pairs:
        count = l.count(index)
        more_needed = desired_count - count
        if more_needed<0: 
            return False
        num_remaining -= more_needed
        if num_remaining<0:
            return False
    return True

plausible_func = plausible_suffix

def generate_magic(N):
    l=[0]
    while l:
        extend = False
        if plausible_func(l,N):
            if len(l)==N:
                yield l[::-1]
            else:
                extend = True
        if extend:
            l.append(0)
        else:
            while l[-1]>=N-2:
                l.pop(-1)
                if not l:raise StopIteration
            l[-1]+=1

n=40 #test parameter

if n>0:
    for x in generate_magic(n):
        print(n,x)

对可能的列表进行广度优先搜索,从右到左填充条目,如果不合理,则在后缀处停止搜索,如果出现以下情况,则可能发生:

  • 后缀中条目n的总和超过(整个列表的总和必须为n
  • i*l[i]后缀中的加权总和超过n(整个列表的总和必须为n
  • 后缀中出现的任何数字均比后缀表示应出现的次数多
  • 剩余的未填充斑点的数量太少,无法解决需要出现更多次的所有数字。

我从左到右有经过测试的原始前缀,但是速度变慢了。

最多输出n=30为:

4 [1, 2, 1, 0]
4 [2, 0, 2, 0]
5 [2, 1, 2, 0, 0]
7 [3, 2, 1, 1, 0, 0, 0]
8 [4, 2, 1, 0, 1, 0, 0, 0]
9 [5, 2, 1, 0, 0, 1, 0, 0, 0]
10 [6, 2, 1, 0, 0, 0, 1, 0, 0, 0]
11 [7, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0]
12 [8, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0]
13 [9, 2, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
14 [10, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
15 [11, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
16 [12, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
17 [13, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
18 [14, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
19 [15, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
20 [16, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
21 [17, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
22 [18, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
23 [19, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
24 [20, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
25 [21, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
26 [22, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
27 [23, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
28 [24, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
29 [25, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
30 [26, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

除了前三个清单外[1, 2, 1, 0], [2, 0, 2, 0], [2, 1, 2, 0, 0],每个长度n>6都有一个清单,形式为[n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]。此模式至少持续到n=50。我怀疑它永远存在,在这种情况下,输出大量的这些是微不足道的。即使不是这样,对可能的解决方案进行数学理解也会大大加快搜索速度。


@Ypnypn我有特殊情况n=0。我错过了我们只返回一个结果n,而不是累加的结果n。这使我起床n=40
xnor

0

Pyth-15个字节

对所有可能的len序列使用蛮力n,然后进行过滤。

f.A.eq/TkYT^UQQ

完整的解释即将推出。

在线尝试一下


2
仅供参考,OP将获胜标准更改为最快的代码。
Alex A.

2
无论获胜的标准是什么,这都是3字节的高尔夫:`fqm / TdQT ^ UQQ`
雅库贝(Jakube)

0

K,26个字节

{f@&{x~(+/x=)'!#x}'f:!x#x}

就像Maltysen的方法一样,蛮力。该程序的核心是谓词,用于测试给定向量是否为“魔术”:

{x~(+/x=)'!#x}

只要输入向量(!#x)建立一个iota向量,计算每个数字((+/x=)')的出现次数,然后将结果与输入向量(x~)比较。如果有比赛,那么您就有一个神奇的序列。

不幸的是,第一次刺刺似乎很慢。在我的笔记本电脑上使用Kona进行测试需要大约12秒才能处理n = 7。我需要多考虑一下。

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.