计算{1,2,…,n}上的拓扑数


9

任务

编写一个函数/程序,该函数/程序将其n作为参数/输入并打印/返回集合上的拓扑数(如下所示){1,2,...,n}

拓扑定义

令X为任意有限集,并假设T是X 的幂集的子集(即,包含X的子集的集合)满足以下条件

  1. X和空集在T中。

  2. 如果两个组U和V是在T,则联合这两组都在T.

  3. 如果两组U和V在T中,则这两组的交点在T中。

...然后T称为X上的拓扑。

技术指标

  1. 您的程序是:

    • 一个函数,它接受n作为参数
    • 或输入 n

    并打印或返回set上(不同)拓扑的数量{1,2,...,n}

  2. n 是小于11的任何非负整数(当然,如果您的程序处理的n大于11也没有问题),并且输出是一个正整数。

  3. 您的程序不应使用任何类型的库函数或本机函数来直接计算拓扑数。

输入示例(n的值): 7

输出/返回示例: 9535241

您可以在此处此处检查返回值。

当然,最短的代码胜出。


获胜者已确定,但是,如果出现较短的代码,我可能会更改获胜者。


它是否必须在本世纪给出结果,还是正确性证明足够好?
彼得·泰勒

@Peter实际上,我不知道需要多长时间。因此,程序的正确性证明足够好,但是如果n较小,如4〜5,程序仍应在合理的时间内给出结果。
JiminP 2011年

@JiminP,似乎在n = 12时进行计算在今天值得一纸,而且没有已知的公式。我怀疑用强力在几分钟内就能实现4或5。
彼得·泰勒

2 ^ X的不正确子集是否也是拓扑?
FUZxxl 2011年

@FUZxxl:是的。我认为这就是离散拓扑
JiminP 2011年

Answers:


4

Haskell,144个字符

import List
import Monad
p=filterM$const[True,False]
f n=sum[1|t<-p$p[1..n],let e=(`elem`t).sort,e[],e[1..n],all e$[union,intersect]`ap`t`ap`t]

该规范几乎直接实现,对一些monad魔术进行了模运算。

极慢n > 4


5

Python,147个字符

N=input()
S=lambda i,K:1+sum(0if len(set(j&k for k in K)-K)-1 else S(j+1,K|set(j|k for k in K))for j in range(i,2**N))
print S(1,set([0,2**N-1]))

N <= 6快,N = 7慢,N> = 8不可能完成。

各个集用整数位掩码表示,拓扑用位掩码集表示。 S(i,K)通过K以位掩码> = 开始并添加集来计算可以形成的不同拓扑的数量i


0

Zsh,83个字符

该解决方案符合您的要求(当然不是精神)。毫无疑问,有一种进一步压缩数字的方法。

a=(0 3 S 9U 5CT 4HO6 5ODFS AMOZQ1 T27JJPQ 36K023FKI HW0NJPW01R);echo $[1+36#$a[$1]]

-1

Python,131个字符

lambda n:sum(x&(x>>2**n-1)&all((~(x>>i&x>>j)|x>>(i|j)&x>>(i&j))&1 for i in range(2**n)for j in range(2**n))for x in range(2**2**n))

扩展版本:

def f(n):
    count = 0
    for x in range(2**2**n): # for every set x of subsets of [n] = {1,...,n}
        try:
            assert x & 1 # {} is in x
            assert (x >> 2 ** n - 1) & 1 # [n] is in x
            for i in range(2**n): # for every subset i of [n]...
                if x >> i & 1: # ...in x
                    for j in range(2**n): # for every subset j of [n]...
                        if x >> j & 1: # ...in x
                            assert (x >> (i | j)) & 1 # their union is in x
                            assert (x >> (i & j)) & 1 # their intersection is in x
            count += 1
        except AssertionError:
            pass
    return count

例如,假设n =3。[n]的可能子集为

0b000
0b001
0b010
0b011
0b100
0b101
0b110
0b111

第ith位指示i是否在子集中。为了对子进行编码,我们注意到这些子集中的每个子集都属于或不属于所讨论的集合。因此,例如

x = 0b10100001
0b000 # 1
0b001 # 0
0b010 # 1
0b011 # 0
0b100 # 0
0b101 # 0
0b110 # 0
0b111 # 1

表示x包含{},{2}和{1,2,3}。


您能解释一下这是如何工作的吗?
Ad Hoc Garf Hunter

@AdHocGarfHunter添加了扩展版本。
user76284
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.