負の空間グラフ


13

仕事

正の整数が与えられ、その数のノードで「自己補完グラフ」を出力する必要があります。自己補完グラフが何であるかわからない場合、ウィキペディアの記事はあまり役に立ちませんので、以下に技術的説明と非技術的説明の2つの説明があります。

非技術的な

グラフは、線で接続されたノードのセットです。ポイントの各ペアは、1本の線で接続することも、まったく接続しないこともできます。グラフの「補数」は、グラフを取得し、接続されていないすべてのノードを接続し、接続されているすべてのノードを切断した結果です。

自己補完グラフは、その補完を元の形状に再配置できるグラフです。以下は、自己補完グラフの例とその方法のデモです。

以下は、5つのノードを持つグラフです。

5ノードグラフ

接続できるすべての場所を赤い点線で強調表示します。

ハイライトされたグラフ

ここで、赤と黒のエッジを交換して、グラフの補数を見つけます。

補体

これは元のグラフとは異なりますが、ノードをそのように移動すると(各ステップで2つのノードが入れ替わります):

同型

元のグラフを取得します!グラフとその補数は同じグラフです

テクニカル

自己補完グラフは、その補完と同型のグラフです。

仕様書

最適な方法で正の整数を受け取ります。そして、適切と思われる方法でグラフを出力します。これには、隣接行列フォーム隣接リストフォーム、そしてもちろん写真が含まれますが、これらに限定されません。出力されるグラフは、それ自身の補数であり、整数入力と同じ数のノードを持たなければなりません。そのようなグラフが存在しない場合は、偽の値を出力する必要があります。

これはあり、バイト数を最小限に抑えることを目指してください。

テストケース

以下は、いくつかのnの可能な出力の写真です

4

5

9


自己補完グラフは、完全なグラフに偶数のエッジがある場合にのみ存在できます。これは保証されていますか?
-xnor

@xnorそれを含めるのを忘れました。修正されました。
ポストロックガーフハンター

負の入力を処理する必要がありますか?
-xnor

@xnorいいえ私は一致する質問を修正します
ポストロックGARFハンター

3
誰かがに基づいて答えを出すという考えを得る前にGraphData@{"SelfComplementary",{#,1}}&nWolframのデータベースからlowの例をロードするだけなので、これは任意の大きな入力に対しては機能しません。
マーティンエンダー

回答:


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

2つの端点頂点が4を法として0または1に追加されるエッジを含めます。この順列による頂点の循環は、それぞれの頂点の合計に4を法とする2を追加し、エッジと非エッジを交換します。これにより、エッジを補完する頂点の順列が得られます。

グラフに4の倍数を超える余分なノードがある場合、サイクルのみになります。他の頂点が偶数の場合、エッジを含めます。頂点を並べ替えるとパリティが反転するため、グラフは自己補完のままになります。

頂点の数が4または4を法とする0または1でない場合、完全なグラフには奇数のエッジがあるため、自己補完グラフは使用できません。

全体として、条件は次のとおりです。

  • 入力nが0または1モジュロ4でない場合、空のリストを出力します
  • そうでなければ、nが偶数である場合、すべてのエッジを含む(a,b)a<bし、a+b0又は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)∧

オンラインでお試しください!

これは 2つの隣接リストで構成されるペアを返す関数です。1つはグラフ用、もう1つは補グラフ用です。(TIOのBrachylogインタープリターでZは、コマンドライン引数として指定することで、完全なプログラムではなく関数を評価するように要求できます。)たとえば、入力の出力5は次のとおりです。

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

これは、イメージ(2つのグラフを表示)のように見えます:

グラフと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バイト(プログラムの1/4、キャラクター (∨?<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レベルをフラット化します。グラフと補数の間の対応する要素のペアのリストが得られます。

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

明らかに、ここで必要なのは、各要素から始まるペアが1つだけであることです(したがって、グラフの要素と補数が1対1に対応していることが証明されます)。リストが正確に?異なる要素(つまり、頂点の数に等しい異なる要素の数)を持っていることを述べるだけで、ほぼ確認できます。この場合、テストは成功します。明確な要素は次のとおりです。

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

ただし、これには潜在的な問題の余地があります。元のグラフで頂点が完全に切断されている場合、その対応は言及されず、他の頂点からの対応が重複する余地が残されます。この場合、補完グラフはその頂点間のエッジ持っている必要があります(一般性を失うことなくが、のはそれだとしましょう1)、および他のすべての頂点、および対応のリストが含まれますので[1,2][1,3]、...、 [1, ?]。ときに?大きく、これは、より多くの対応につながる私たちはそうでない場合があるだろうよりも、合計ので、全く問題はありません。唯一の問題?は、3以下の場合に発生します。この場合、追加の通信を1つ追加するだけです(ただし、1入力に表示されない); ただし、これは実際には問題ではありません。3要素グラフには3つの可能なエッジがあり、これは奇数です(同様に、2要素グラフの1つの可能なエッジも奇数です)。テストは\ステップで失敗します(不規則なリスト、つまり要素の長さが異なるリストを転置することはできません)。


違いzとは、\つまりzそれはつまり、巡回ジップである[[1,2,3],["a"]]ということになります[[1,"a"],[2,"a"],[3,"a"]]z、それは失敗します一方、\\現在、正方行列でのみ機能します。将来の実装ではz、周期的でない限り、のように動作します。
1

私は実際に自分で違いを理解していましたが、説明を書いてからです。この特定のソリューションは、「長方形でのみ動作します(ただし、そのステップを利用できない場合はさらに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+2か、4x+3エッジの数が奇数であるように解決策は存在しません。

nが4xの形式の場合、すべての頂点を円形に配置し、(a+b) mod 42または3のエッジを描画します(Xnorの場合のように、ゴルフの理由で0または1ではありません。したがって、これはXnorが提供するソリューションを補完します)。

これをより絵画的な感覚で見るために、頂点を1つおきに取り、頂点を1箇所と2箇所に反時計回りに引きます。これnにより、合計の半分の平行方向が定義されます。次に、これらに平行な他のすべてのエッジを追加します。

補数は、各エッジ仕様のaとbの両方に1を追加するか、図をa 1/n

どこにn我々は4倍グラフの秒ごとの頂点にリンクされている別の頂点を追加、フォームの4x + 1です。中央に配置した場合、ダイアグラムの対称性は保持されますが、明確にするために、メインの円の外側に配置することにしました。

出力

以下は、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

この関数は、隣接リストを返します。2つのアルゴリズムを使用し、空の補完グラフと非出力を区別するため0[]、何も存在しない場合ではなく戻ります。最初のアルゴリズムは、BIT述語を使用して構築されたRado Graphsに基づいており、有効な0次、1次、4次、および5次の相補グラフを作成します。数学の友人が見つけたもう1つのアルゴリズムは、有効なV頂点相補グラフに4パスの追加を適用することにより、有効なV + 4頂点相補グラフを構築します。

入力を検証して有効な補完グラフの存在を確認し(を使用n*~-n/4%1)、それが失敗した場合にを返します0。次にn>5n-4ケースを確認してケースに再帰し、有効な低次のソリューションを構築してから、再帰チェーンをバックアップする途中で返された隣接リストに4加算を適用します。最後に、n>5がtrueでない場合、0toからn-1for xおよびまで反復しy(y>>x)&1がtrue かどうかを確認します。その場合、それらのノードはペアになります。

次に、より読みやすい形式の関数を示します。三項演算子をif-elseステートメントにeval()展開し、インライン展開します。

// 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>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.