负空间图


13

任务

您将得到一个正整数,并且必须输出具有这么多节点的“ 自补图 ”。如果您不知道什么是自助图,那么维基百科的文章将无济于事,因此以下是两种解释,一种是技术性的解释,另一种是非技术性的解释。

非技术

图是一组由线连接的节点。每对点可以通过一条线连接或不连接。图的“补码”是获取图并连接所有未连接的节点并断开所有已连接的节点的结果。

自补图是可以将补码重新排列为原始形状的图。下面是一个自补图的示例以及如何进行演示。

这是一个有5个节点的图形:

5节点图

我们将用红色虚线突出显示可以进行连接的所有地方:

突出显示图

现在,我们将通过交换红色和黑色边缘来找到图形的补码:

补充

这看起来不像原始图,但是如果我们像这样移动节点(每个步骤交换两个节点):

同构

我们得到原始图!该图及其补图是同一图

技术

自补图是与其补图同构的图。

技术指标

通过最适合您的方法,您将收到一个正整数。然后,您将以您认为合适的任何方法输出图形,包括但不限于邻接矩阵表单邻接列表表单,当然还有图片!输出的图必须是其自己的补码,并且具有与整数输入一样多的节点。如果不存在这样的图形,则必须输出一个伪造的值。

这是,您应努力减少字节数。

测试用例

以下是几个n的可能输出的图片

4

5

9


自补图只能存在于完整图具有偶数个边的情况下。我们可以保证吗?
xnor

@xnor我忘了包括在内。立即修复。
Ad Hoc Garf Hunter

我们必须处理负输入吗?
xnor

@xnor否。我将解决这个问题,使其完全一致
Ad Hoc Garf Hunter,2015年

3
在有人得到基于答案的想法之前GraphData@{"SelfComplementary",{#,1}}&,我相信只是n从Wolfram的数据库中加载一些低级的示例,因此这不适用于任意大的输入。
Martin Ender

Answers:


9

Haskell,77个字节

f n=[(a,b)|b<-[1..n],a<-[1..b-1],mod n 4<2,mod(a+(last$b:[a|odd n,n==b]))4<2]

在线尝试!

这使用易于计算的显式标准来确定边是否(a,b)属于图形。实例化此算法,并在模4值之间进行置换循环

4*m -> 4*m+1 -> 4*m+2 -> 4*m+3 -> 4*m

我们包括两个端点顶点加到0或1模4的边。请注意,按此置换循环的顶点每个顶点的总和加2模4,因此交换边和非边。这给出了与边缘互补的顶点排列。

如果图形的额外节点超出4的倍数,则将其单独放入一个循环中。当其他顶点是偶数时,我们将其包括在内。对顶点进行置换会翻转奇偶校验,因此图保持自补。

如果顶点的数目不是0或1模4,则不可能有自补图,因为完整图中的边数是奇数

总的来说,这是条件:

  • 如果输入n不是0或1模4,则输出一个空列表
  • 否则,如果n是偶数,包括所有边缘(a,b)a<ba+b等于0或1模4。
  • 否则,如果n为奇数,则执行相同的操作,(a,n)但当a为偶数时,则包括表单的边缘。

该代码通过更换条件结合了第二和第三种情况mod(a+b)4<2mod(a+a)4<2当两个odd nb==n


5

Brachylog 2,24字节

{⟦₁⊇Ċ}ᶠpḍ.(\\ᵐcdl?∨?<2)∧

在线尝试!

函数返回一对包含两个邻接表的函数:一个用于图,一个用于补图。(在TIO上的Brachylog解释器中,您可以要求它通过提供Z命令行参数来评估函数而不是完整程序。)例如,输入的输出为5

[[[1,2],[1,3],[1,5],[3,5],[4,5]],[[2,5],[2,3],[2,4],[3,4],[1,4]]]

这是一张图片(显示两个图):

一个图及其在5个元素上的相同补码

与基于Prolog的语言一样,该函数支持多个调用模式。值得注意的是,如果您尝试将其用作生成器,它将输出具有给定顶点数量的所有可能的自互补图(尽管我没有做出任何努力使这种情况可用,并且值得注意的是,它将输出每个每个图形很多次)。

说明

基本上,这只是对问题的描述,而Prolog实现则可以找到解决问题的最佳方法。(但是,我怀疑在这种特殊情况下,它使用的算法是否比蛮力更好,因此它的效率可能很低,并且测试似乎证实了这一点,显示图越大,性能会越差。)

{⟦₁⊇Ċ}ᶠpḍ.(\\ᵐcdl?∨?<2)∧
 ⟦₁                       The range [1, 2, …, ?], where ? is the input
   ⊇                      A subset of that range…
    Ċ                     …which has exactly two elements
{    }ᶠ                   A list of everything that fits the above description
{⟦₁⊇Ċ}ᶠ                   All edges that could exist in a ?-element graph
       p                  Find a permutation of these…
        ḍ                 …so that splitting it into two equal parts…
          (       ∨   )   …either:
               dl?          produces ? distinct elements
           \                after transposing it
            \ᵐ              and transposing its elements
              c             and flattening one level;
                          or:
                   ?<2      ? was less than 2
         .             ∧  Once you've found it, . specifies what to output

顺便说一句,我最终不得不花整个6个字节(程序的¼,是字符(∨?<2))来处理0和1的特殊情况。令人沮丧,但这就是特殊情况的本质。

\\ᵐcdl?部分有点难以理解,因此这是一个可行的示例。其目的是检查某物是否为图及其补码,其中图和补码中的对应边在列表中的顺序相同。图形/补码对成为程序的最终输出。这是一个示例案例:

[[[1,2],[1,3],[1,5],[3,5],[4,5]],[[2,5],[2,3],[2,4],[3,4],[1,4]]]

换位后,我们得到了图形和补数之间的一对对应边的列表:

[[[1,2],[2,5]],[[1,3],[2,3]],[[1,5],[2,4]],[[3,5],[3,4]],[[4,5],[1,4]]

接下来,我们在列表元素内转置并展平一个级别。这给了我们图表和补数之间成对的对应元素的列表:

[[1,2],[2,5],[1,2],[3,3],[1,2],[5,4],[3,3],[5,4],[4,1],[5,4]]

显然,我们在这里想要的是从每个元素开始不超过1对(因此证明了图的元素和补码是一对一的对应关系)。我们仅通过声明列表具有完全?不同的元素(即,等于顶点数量的不同元素)就可以验证这一点。在这种情况下,测试成功;不同的元素是:

[[1,2],[2,5],[3,3],[5,4],[4,1]]

但是,这为潜在的问题留有余地。如果顶点在原始图中完全断开,则不会提及其对应关系,从而为与其他某个顶点的重复对应关系留有空间。如果是这样的情况下,补图必须有一个顶点之间的边缘(不失一般性,我们说这是1),和所有其他顶点,因此对应的列表将包含[1,2][1,3],... [1, ?]。当?它很大时,这将导致总的通信量比否则多,因此没有问题。唯一的问题发生在?3或更低的时间,在这种情况下,我们最终只会添加一个额外的对应关系(从中删除一个对应关系)1没有出现在输入中); 但是,实际上这不是问题,因为3元素图上有3个可能的边,这是一个奇数(同样,2元素图上的1个可能的边也是一个奇数),因此测试将在该\步骤失败(您不能转置参差不齐的列表,即元素长度不同的列表)。


之间的区别z,并\z是循环的压缩,这意味着[[1,2,3],["a"]]最终会被[[1,"a"],[2,"a"],[3,"a"]]z,而它会为失败\\目前仅适用于正方形矩阵;将来的实现将使其像一样工作z,除非不是周期性的。
Fatalize

我实际上已经自己找出了区别,但是只有在写完解释之后。这个特定的解决方案取决于``仅在矩形上工作(尽管如果您不能利用该步骤,则仅占用2个字节)。

2

BBC BASIC,161字节

标记化文件大小140字节

http://www.bbcbasic.co.uk/bbcwin/bbcwin.html下载口译员

I.m:IF2ANDm ORm<4P.0:END
r=400n=-2A.m:t=2*PI/n:F.i=1TOn*n:a=i DIVn:b=i MODn:c=b:IFa+b A.2a*=t:b*=t:L.r+r*SINa,r+r*COSa,r+r*SINb,r+r*COSb:IF 1A.m A.c DRAWr*3,0
N.

非高尔夫代码

  INPUTm                           :REM get input
  IF2ANDm ORm<4PRINT0:END          :REM if m=4x+2 or 4x+3 or less than 4, print 0 and exit
  r=400                            :REM radius of diagram
  n=-2ANDm                         :REM n = m truncated to an even number
  t=2*PI/n                         :REM t = 1/n turns
  FORi=1TOn*n                      :REM for each combination of vertices
    a=i DIVn                       :REM extract a and b
    b=i MODn                       :REM make a copy of c
    c=b                            :REM if a+b MOD 4 = 2 or 3, convert a and b to angles and draw edge.
    IFa+b AND2 a*=t:b*=t:LINEr+r*SINa,r+r*COSa,r+r*SINb,r+r*COSb:IF 1ANDm ANDc DRAWr*3,0
  NEXT                             :REM if m is odd and c is odd, draw a line to the additional vertex for m=4x+1 input.

说明

它使用与Xnor相同的算法,但会生成图表输出。

其中n的形式的4x+24x+3不存在溶液作为边缘的数量为奇数。

哪里n是4x形式,我们将所有顶点(a+b) mod 4排列成一个圆形,并画出2或3的那些边(出于打高尔夫球的原因,而不是像Xnor那样为0或1。因此,这是Xnor提供的解决方案的补充。)

为了更直观地理解这一点,我们每隔一个顶点并沿逆时针方向将边线绘制到顶点1和2处。这定义了n平行方向,占总数的一半。然后,我们添加与这些平行的所有其他边缘。

可以通过在每个边缘规格中的a和b上都加1来找到补码,或者通过旋转图表1/n将其象形图所示。

n形式为4x + 1的位置,我们添加了另一个顶点,该顶点链接到4x图的每个第二顶点。如果将其放置在中心,则将保持图的对称性,但是为了清楚起见,我选择将其放置在点的主圆之外。

输出量

以下是4x + 1的前几种情况。通过删除右下角的顶点及其相关边缘,可以看到4x情况。

在此处输入图片说明


1

JavaScript(ES6),191个字节

f=(n,a=[],v=n*~-n/4)=>v%1?0:eval(n>5?f(n-=4,a)&&'for(i=0;i<n;)a.push([i,n+1],[i++,n+2]);a.push([n,++n],[n,++n],[n,++n])-v':'for(l=x=0;x<n;x++)for(y=x;y<n;y++)l<v&y>>x&1?l=a.push([x,y]):a')||a

该函数返回一个邻接表。它使用两种算法,并通过返回0而不是[]不存在的情况来区分空的互补图和非输出。第一种算法基于使用BIT谓词构造的Rado图,并创建有效的0、1、4、4阶和5阶互补图。我们的数学朋友发现了另一种算法,通过有效的V顶点互补图应用4路径加法来构造有效的V + 4 顶点互补图。

首先,通过验证输入以确认是否存在有效的互补图(使用n*~-n/4%1),如果失败,则返回0。然后,它检查是否n>5递归,n-4以构造有效的低阶解决方案,然后在递归链备份的方式上将4加法应用于返回的邻接表。最后,如果n>5不为true,则从迭代0n-1for xy,并检查as是否(y>>x)&1为true。如果是这样,则将这些节点配对。

这是一种更易读的函数格式,其中三元运算符扩展为if-else语句并eval()内联了s:

// precalculate amount of required vertices in v
f = (n, a = [], v = n*~-n / 4) => {
  // if amount is non-integer
  if (v % 1) {
    // no valid complementary graph
    return 0;
  } else {
    if (n > 5) {
      // generate valid (n-4)-order complementary graph
      f(n -= 4, a);
      // apply 4-path addition
      for (i = 0; i < n;)
        a.push([i, n+1],[i++, n+2]);
      a.push([n, ++n], [n, ++n], [n, ++n]);
    } else {
      // construct Rado graph using BIT predicate
      for(l = x = 0; x < n; x++)
        for(y = x; y < n; y++)
          // if amount of pairs is less than required and xth bit of y is high
          if (l < v && (y>>x & 1))
            // vertices x and y should be paired
            a.push([x,y]);
    }
    return a;
  }
};

演示版

f=(n,a=[],v=n*~-n/4)=>v%1?0:eval(n>5?f(n-=4,a)&&'for(i=0;i<n;)a.push([i,n+1],[i++,n+2]);a.push([n,++n],[n,++n],[n,++n])-v':'for(l=x=0;x<n;x++)for(y=x;y<n;y++)l<v&y>>x&1?l=a.push([x,y]):a')||a
<input type="number" onchange="o.textContent=JSON.stringify(f(this.value))"><pre id="o"></pre>

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.