构造图


15

在此挑战中,您的任务是根据一系列指令构造一个无向图。每个非负整数都有一个指令,并且每个指令都会将给定的图转换为新的图。

  • 指令0:添加一个新的断开连接的节点。
  • 指令1:添加一个新节点,并将其连接到每个现有节点。
  • 伪指令m > 1:删除度(邻居数)可被整除的所有节点m。请注意,0所有m节点都可以将其整除,因此始终会删除断开连接的节点。

从空图开始,指令从左到右一一应用。例如,[0,1,0,1,0,1,3]使用令人敬畏的ASCII技术对序列进行如下处理。我们从空图开始,并按照的指示添加一个顶点0

a

然后,按照的指示添加另一个顶点并将其连接到第一个顶点1

a--b

我们按照0和的指示添加另一个断开连接的顶点,然后添加一个连接的顶点1

a--b   c
 \  \ /
  `--d

我们重复这一次,作为导演01

  ,--f--e
 /  /|\
a--b | c
 \  \|/
  `--d

最后,按照以下指示删除3级顶点a和:b3

f--e
|\
| c
|/
d

这是由序列定义的图[0,1,0,1,0,1,3]

输入值

非负整数列表,代表指令序列。

输出量

序列定义的图中的节点数。

测试用例

[] -> 0
[5] -> 0
[0,0,0,11] -> 0
[0,1,0,1,0,1,3] -> 4
[0,0,0,1,1,1] -> 6
[0,0,1,1,0,0,1,1,2,5,7,0,1] -> 6
[0,0,1,1,1,1,5,1,4,3,1,0,0,0,1,2] -> 6
[0,0,1,1,0,0,1,1,5,2,3,0,0,1,1,0,0,1,1,3,4,0,0,1,1,2,1,1] -> 8
[0,0,1,1,0,0,1,1,2,5,7,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,8] -> 14

详细规则

您可以编写函数或完整程序。最短的字节数获胜。不允许出现标准漏洞。请在回答中说明您的算法。


已经过了一周,所以我接受了最短的答案。如果以后出现的更短,我将更新选择。值得一提的是Peter Taylor的答案,包括获奖者在内的其他人也基于此。


5
因为我读的问题,想着你有实际绘制图形- 这是超韧,向下滚动-
优化

@Optimizer是的,我想提出一个问题,以便图的实际表示形式不重要,而主要的困难在于实现指令。节点数只是检查正确性的一种简便方法。
Zgarb 2014年

1
我真的很喜欢这个挑战!就像设计数据结构一样。您必须弄清楚如何表示图形,因为输入和输出格式不受其约束。
xnor 2014年

Answers:


4

柏斯37 31

lu?+GH<H2m@Gdf%+*@GTtTs>GTHUGQY

该解决方案使用reduce函数(u)来构建列表,其中每个条目对应于列表中剩余的节点,条目的值对应于该节点最初是根据伪指令0还是1添加的。

G是reduce函数中的累加器变量,并保存上述列表。初始化为空列表Y

H接受Q输入中每个成员的值,一个接一个。G每次将表达式的结果分配,并将的下一个条目Q分配给H,然后重新运行表达式。

为了G正确更新,有两种可能性,一种用于指令0或1,一种用于其他指令。这些情况以三元区分? ... <H2 ...

如果H为0或1,那么我们要做的只是追加HG+GH完成此任务。

否则,首先需要确定图形中的每个节点有多少个邻居。这分两个步骤完成:

首先,s>GT计算输入节点处或输入节点之后的节点数为1s。这些都连接到输入节点,但是如果输入节点为1,我们将加1。

其次,我们需要比输入节点早的节点数量。如果输入节点为0,则为0;如果输入节点为1,则为输入节点的索引T。此值将由给出*@GTT。但是,仍存在来自第一部分的超计数,需要纠正。因此,我们*@GTtT改为计算,如果输入节点为1,则少1。将这些值相加,得出连接到输入节点的节点数。

% ... H将给0表示该数字可被整除H,因此应将其删除,否则将不给0。

f ... UG因此将给出不应删除的输入索引,因为它f是一个过滤器,且0为假。

m@Gd 将这些索引转换为相应节点的0和1。

最后,一旦找到了标记为0和1的节点的结果列表,就对其长度进行计算(l)并进行打印(隐式)。

感谢@PeterTaylor。


12

GolfScript(53字节)

])~{:^1>{.-1:H)-,:T;{..H):H*T@-:T+^%!{;}*}%}{^+}if}/,

在线演示

我实际上还没有打过高尔夫球,但是我发现消除HT变量并不是很容易,因此这可能是局部最小值。

以格式输入标准输入[0 1 2 3]。将输出保留在stdout上。

取消高尔夫:

])~{
  :^1>{
    # array of 0s and 1s
    # Each 0 has degree equal to the number of 1s after it
    # Each 1 has degree equal to the number of values before it plus the number of 1s after it
    .-1:H)-,:T;
    {
      # Stack: x
      # T' = T - x is the number of 1s after it
      # H' = H + 1 is the number of values before it
      # Degree is therefore H' * x + T' = H * x + T - x = (H-1)*x + T
      # Keep x unless degree % ^ == 0
      ..H):H*T@-:T+^%!{;}*
    }%
  }{^+}if
}/,

4

果酱 129 75 73 68 61 46 42字节

基于彼得算法的解决方案:

Lq~{I+I1>{0:U(<:L{LU<,*LU):U>1b+I%},}*}fI,

代码扩展随之而来。


先前的解决方案(61字节):

Lq~{:N2<{U):UaN{f+U1$0f=+}*a+}{{:X,(N%_!{X0=L+:L;}*},Lf-}?}/,

接收来自STDIN的输入,例如:

[0 0 1 1 0 0 1 1 5 2 3 0 0 1 1 0 0 1 1 3 4 0 0 1 1 2 1 1]

输出是STDOUT上的数字:

8

算法

  • 保持递增变量 U,该存储要添加的节点的ID。
  • 维护一个list列表,其中,每个list是一个具有唯一ID的节点,该ID由列表的第一个元素组成,其余元素为已连接节点的ID。
  • 在每次迭代中(在读取输入指令的同时),
    • 如果指令是0,请添加[U]到列表列表
    • 如果伪指令为1,则将其添加U到列表列表中的每个列表,并添加另一个列表,该列表由每个列表列表的第一个元素组成,并且U
    • 对于要删除的指令,我过滤掉了所有length - 1可被整除的列表,m并始终注意这些列表的第一个元素。过滤后,我从剩余的ID列表中删除了所有已删除的ID。

代码扩展

Lq~{:N2<{U):UaN{f+U1$0f=+}*a+}{{:X,(N%_!{X0=L+:L;}*},Lf-}?}/,
L                                            "Put an empty array on stack";
 q~                                          "Evaluate the input";
   {                                }/       "For each directive";
    :N                                       "Store the directive in N";
      2<{     ...    }{    ...    }?         "If directive is 0 or 1, run the first";
                                             "block, else second";
{U):UaN{f+U1$0f=+}*a+}
 U):U                                        "Increment and update U (initially 0)";
     a                                       "Wrap it in an array";
      N{         }*                          "Run this block if directive is 1";
        f+                                   "Add U to each list in list of list";
          U1$                                "Put U and list of lists on stack";
             0f=                             "Get first element of each list";
                +                            "Prepend U to the above array";
                   a+                        "Wrap in array and append to list of list";
{{:X,(N%_!{X0=L+:L;}*},Lf-}
 {                   },                      "Filter the list of list on this block";
  :X,(                                       "Get number of connections of this node";
      N%_                                    "mod with directive and copy the result";
         !{        }*                        "If the mod is 0, run this block";
           X0=                               "Get the id of this node";
              L+:L;                          "Add to variable L and update L";
                       Lf-                   "Remove all the filtered out ids from the";
                                             "remaining nodes";
,                                            "After the whole process is completed for"
                                             "all directives, take length of remaining ";
                                             "nodes in the list of list";

在这里尝试


3

Pyth,88 80 75个字符

JYFHQI!H~Y]]lY)IqH1=Y+m+dlYY]UhlY)VYI&Hq%l@YNH1~J]N))=Ymf!}TJ@YkUlYY;-lYl{J

我受够了。也许其他人有一些打高尔夫球的技巧。

Y是图的邻接表。出于打高尔夫的原因,即使删除了节点,我也将节点保留在此列表中(否则,我将必须更新所有索引)。每个节点都有自己作为邻居。该列表J跟踪已删除的节点。

我在示例输入中显示邻接表的更改[0,1,0,1,0,1,3]

输入0:Y = [[0]] J = []
输入1:Y = [[0,1],[0,1]] 0 J = []
输入0:Y = [[0,1],[0,1],[2]] J = []
输入1:Y = [[0,1,3],[0,1,3],[2,3],[0,1,2,3]] J = []
输入0:Y = [[0,1,3],[0,1,3],[2,3],[0,1,2,3],[4]] J = []
输入1:Y = [[0,1,3,5],[0,1,3,5],[2,3,5],[0,1,2,3,5],[4,5 ],[0,1,2,3,4,5]] J = []
输入3:Y = [[3,5],[3,5],[2,3,5],[2,3,5],[4,5],[2,3,4,5]] J = [0,1]

然后,该算法非常简单:迭代所有输入,如果input == 0:添加一个自己为邻居的新节点,如果input == 1:添加一个所有节点为邻居的新节点(也包括删除的节点),然后添加如果输入> 1,则将此节点添加到所有节点的邻接列表中:确定具有#neighbor-1%input == 0的节点,并将它们添加到J,在每种情况下,使用来更新每个节点的邻居J。在末尾打印长度Y减去(长度)的长度J

JYFHQI!H~Y]]lY)IqH1=Y+m+dlYY]UhlY)VYI&Hq%l@YNH1~J]N))=Ymf!}TJ@YkUlYY;-lYl{J
JY                      set J=[]
  FHQ                   for H in: input()
I!H      )                if H==0:
   ~Y]]lY                   Y.append([len(Y)])
IqH1              )       if H==1:
    =Y+                     Y=                 +
       m+dlYY                 old nodes updated
             ]UhlY                              new node with all neighbors
VY                )       for N in range(len(Q)):
  I&Hq%l@YNH1    )          if H>0 and len(Y[N])%H==1:
             ~J]N             J.append(N) //this node gets deleted
=Ym           Y           Y=[           for k in Y]
   f!}TJ@YkUlY               k-filtered  //all items of J are removed
;                       end input for loop
-lYl{J                  print len(Y) - len(set(J))

用法

只需调用脚本并提供输入[0,1,0,1,0,1,3]或其他测试用例即可。



2

蟒蛇2,296

s=input();e=[];n=[];c=0
for t in s:
    if t<2:e=e+[[]]if t==0 else [x+[c]for x in e]+[n[:]];n+=[c];c+=1
    else:
        M=zip(*[(i,n[i])for i,x in enumerate(e)if not len(x)%t])
        if M:e=[list(set(z)-set(M[1]))for j,z in enumerate(e)if j not in M[0]];n=list(set(n)-set(M[1]))
print len(n)

每个节点都有一个唯一的ID,并记录每个节点的邻居ID。当指令为0时,将为新节点添加一个空的邻居列表。伪指令为1时,所有现有节点的ID都将成为新节点的邻居列表,所有其他邻居列表都将更新为包括新节点ID。对于m> 1,将从邻居列​​表和所有邻居列表中删除邻居列表是m的倍数的节点。感谢@Optimizer在早期版本中捕获错误。


2

NetLogo,160

to f[t]foreach t[if ? = 0[crt 1]if ? = 1[crt 1[create-links-with other turtles]]if ? > 1[ask turtles with[count my-links mod ? = 0][die]]]show count turtles
end

该实现非常简单,读取每个符号并执行适当的操作。

to f[t]
  foreach t [
    if ? = 0 [
      crt 1
    ]
    if ? = 1 [
      crt 1 [create-links-with other turtles]
    ]
    if ? > 1 [
      ask turtles with [count my-links mod ? = 0] [die]
    ]
  ]
  show count turtles
end

您可以从命令行以方式运行f[0 0 1 1 0 0 1 1 2 5 7 0 1]


2

Ruby 159157演示

N=Struct.new:l
G=->c{n=[]
c.map{|m|m<1?n<<N.new([]):m<2?(w=N.new([])
n.map{|x|x.l<<w;w.l<<x}
n<<w):(n-=r=n.select{|x|x.l.size%m<1}
n.map{|x|x.l-=r})}
n.size}

这定义了一个G使用stabby-lambda语法调用的函数。用于G[[0, 1]]通过命令0和调用它1

该实现非常简单:有一个Node结构(N上面称为),该结构通过l属性保存对所有链接节点的引用。G根据需要创建节点并操纵其链接。此处提供可读版本。


1

CJam,99 97字节

Lal~{I2<{_0={{If+z}2*));0+a+}{;Iaa}?}{_0=!!{{{_:+I%+}%z}2*));1+a+{{W=},z}2*);z_{);}{a}?}*}?}fI0=,

在这方面还有很多事情要做。该算法基于跟踪邻接矩阵,但是表示空矩阵而不必对其进行特殊处理,这让我很头疼。

在这里测试。

输入是CJam样式的数组:

[0 0 1 1 0 0 1 1 2 5 7 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 8]

您可以使用此测试工具来运行所有测试:

"[]
[5]
[0,0,0,11]
[0,1,0,1,0,1,3]
[0,0,0,1,1,1]
[0,0,1,1,0,0,1,1,2,5,7,0,1]
[0,0,1,1,1,1,5,1,4,3,1,0,0,0,1,2]
[0,0,1,1,0,0,1,1,5,2,3,0,0,1,1,0,0,1,1,3,4,0,0,1,1,2,1,1]
[0,0,1,1,0,0,1,1,2,5,7,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,8]"

","SerN/{
La\~{I2<{_0={{If+z}2*));0+a+}{;Iaa}?}{_0=!!{{{_:+I%+}%z}2*));1+a+{{W=},z}2*);z_{);}{a}?}*}?}fI0=,
N}/

1

Python 2,174

l=input()
g={}
n=0
for x in l:
 n+=1;g[n]=set()
 if x>1:h={i for i in g if len(g[i])%x};g={i:g[i]&h for i in set(g)&h}
 if x==1:
  for i in g:g[i]^={n};g[n]^={i}
print len(g)

这可能仍然可以打很多。

我用字典 g来代表图形。节点用数字标记,它们映射到相邻节点的集合。这意味着边缘的每个更新都需要在其两个端点上执行。

通过向上计数创建新节点索引n。每次,我创建一个新的空节点n。对于command 0,它仍然存在。对于命令1,它通过g[i]^={n};g[n]^={i}; 相互连接。使用xor使其不连接该节点。对于> 1的命令,将立即将其删除。

程度为倍数的节点的过滤是通过首先查找剩余(h)的节点,然后将and其与节点列表和每个节点的邻居进行比较来完成的。

最后,图字典中的条目数就是答案。


0

Mathematica,223个字节

哇,结果比我预期的要长。

f=(g={};t=Append;l=Length;m=ListQ;h=Flatten;k=Position;o=If;(d=#;o[d==0,g=g~t~{},o[d==1,g=o[m@#,t[#,l@g+1],#]&/@g;g=t[g,h@k[g,_?m,1]],g=o[l@#~Mod~d==0,0,#]&/@g;p=h@k[g,0];(c=#;g=#~DeleteCases~c&/@g)&/@p]])&/@#;g~Count~_?m)&

用法:

f@{0, 1, 0, 1, 0, 1, 3}

这是测试用例的结果:

f /@ {
  {},
  {5},
  {0, 0, 0, 11},
  {0, 1, 0, 1, 0, 1, 3},
  {0, 0, 0, 1, 1, 1},
  {0, 0, 1, 1, 0, 0, 1, 1, 2, 5, 7, 0, 1},
  {0, 0, 1, 1, 1, 1, 5, 1, 4, 3, 1, 0, 0, 0, 1, 2},
  {0, 0, 1, 1, 0, 0, 1, 1, 5, 2, 3, 0, 0, 1, 1, 0, 0, 1, 1, 3, 4, 0, 0, 1, 1, 2, 1, 1},
  {0, 0, 1, 1, 0, 0, 1, 1, 2, 5, 7, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 8}
}

Out: {0, 0, 0, 4, 6, 6, 6, 8, 14}

少打高尔夫球:

f = (
   a = #;
   g = {};
   Table[
    If[a[[n]] == 0,
     AppendTo[g, {}],
     If[a[[n]] == 1,
      g = If[ListQ@#, Append[#, Length@g + 1], #] & /@ g; 
      g = Append[g, Flatten@Position[g, _?ListQ, 1]],
      If[a[[n]] > 1,
       g = If[Mod[Length@#, a[[n]]] == 0, 0, #] & /@ g;
       p = Flatten@Position[g, 0];
       (c = #; g = DeleteCases[#, c] & /@ g) & /@ p
       ]
      ]
     ],
    {n, Length@a}];
   Count[g, _?ListQ]
   ) &

它的工作方式是将图形表示为“邻居列表”列表。
对于0指令,我只是追加一个空列表。
对于1指令,我附加了所有先前节点的列表,并将新节点添加到所有先前节点。
对于> 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.