Đồ thị không gian âm


13

Bài tập

Bạn sẽ được cấp một số nguyên dương và bạn phải xuất ra một " biểu đồ tự bổ sung " với nhiều nút đó. Nếu bạn không biết biểu đồ tự bổ sung là gì thì bài viết trên wikipedia sẽ không giúp bạn nhiều vì vậy dưới đây là hai cách giải thích, một kỹ thuật và phi kỹ thuật.

Phi kỹ thuật

Biểu đồ là một tập hợp các nút được kết nối bằng các đường. Mỗi cặp điểm có thể được kết nối bởi một dòng hoặc không. "Bổ sung" của biểu đồ là kết quả của việc lấy biểu đồ và kết nối tất cả các nút không được kết nối và ngắt kết nối tất cả các nút.

Biểu đồ tự bổ sung là một biểu đồ có phần bổ sung có thể được sắp xếp lại thành hình dạng của bản gốc. Dưới đây là một ví dụ về biểu đồ tự bổ sung và trình diễn cách làm.

Dưới đây là biểu đồ có 5 nút:

Đồ thị 5 nút

Chúng tôi sẽ làm nổi bật tất cả những nơi mà các kết nối có thể đi với các đường chấm màu đỏ:

Đồ thị nổi bật

Bây giờ chúng ta sẽ tìm thấy phần bù của biểu đồ bằng cách hoán đổi các cạnh màu đỏ và đen:

Bổ sung

Điều này không giống như biểu đồ ban đầu nhưng nếu chúng ta di chuyển các nút xung quanh như vậy (mỗi bước hoán đổi hai nút):

Đồng phân

Chúng ta có được đồ thị ban đầu! Biểu đồ và phần bù của nó là cùng một biểu đồ

Kỹ thuật

Một đồ thị tự bổ sung là một đồ thị đẳng hình với bổ sung của nó.

Thông số kỹ thuật

Bạn sẽ nhận được một số nguyên dương thông qua bất kỳ phương pháp nào phù hợp với bạn nhất. Và bạn sẽ xuất một biểu đồ theo bất kỳ phương pháp nào bạn cho là phù hợp, điều này bao gồm nhưng không giới hạn ở Biểu mẫu ma trận điều chỉnh , Biểu mẫu danh sách điều chỉnh và tất nhiên là cả hình ảnh! Biểu đồ xuất ra phải là phần bù riêng của nó và có nhiều nút như đầu vào số nguyên. Nếu không có đồ thị như vậy tồn tại, bạn phải xuất ra một giá trị giả.

Đây là và bạn nên cố gắng giảm thiểu số lượng byte của mình.

Các trường hợp thử nghiệm

Dưới đây là hình ảnh của đầu ra có thể cho một số n

4

5

9


Một đồ thị tự bổ sung chỉ có thể tồn tại khi đồ thị hoàn chỉnh có số cạnh chẵn. Chúng tôi có đảm bảo điều này?
xnor

@xnor Tôi quên bao gồm điều đó. Đã sửa bây giờ.
Đăng Rock Garf Hunter

Chúng ta có phải xử lý đầu vào tiêu cực?
xnor

@xnor Không. Tôi sẽ sửa câu hỏi để phù hợp
Post Rock Garf Hunter

3
Trước khi bất cứ ai có ý tưởng dựa trên câu trả lời GraphData@{"SelfComplementary",{#,1}}&, tôi tin rằng chỉ cần tải một số ví dụ ntừ cơ sở dữ liệu của Wolfram, vì vậy điều này sẽ không hoạt động đối với các đầu vào lớn tùy ý.
Martin Ender

Câu trả lời:


9

Haskell , 77 byte

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]

Hãy thử trực tuyến!

Điều này sử dụng một tiêu chí rõ ràng dễ tính toán để quyết định xem một cạnh có (a,b)thuộc đồ thị hay không. Khởi tạo thuật toán này , với chu kỳ hoán vị giữa các giá trị modulo 4

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

Chúng tôi bao gồm các cạnh có hai đỉnh điểm cuối thêm vào 0 hoặc 1 modulo 4. Lưu ý rằng các đỉnh đi xe đạp theo hoán vị này sẽ thêm 2 modulo 4 vào tổng đỉnh trên mỗi đỉnh, và do đó hoán đổi các cạnh và không cạnh. Điều này cho phép hoán vị các đỉnh bổ sung cho các cạnh.

Nếu đồ thị có một nút phụ ngoài bội số của 4, nó sẽ được đặt trong một chu kỳ. Chúng tôi bao gồm các cạnh với nó khi đó đỉnh khác là chẵn. Cho phép các đỉnh lật ngang nhau, và do đó biểu đồ vẫn tự bổ sung.

Nếu số đỉnh không phải là 0 hoặc 1 modulo 4, thì không thể có đồ thị tự bổ sung vì có một số cạnh lẻ trong đồ thị hoàn chỉnh

Nhìn chung, đây là các điều kiện:

  • Nếu đầu vào n không phải là 0 hoặc 1 modulo 4, hãy đưa ra một danh sách trống
  • Mặt khác, nếu n chẵn, bao gồm tất cả các cạnh (a,b)a<ba+bbằng 0 hoặc 1 modulo 4.
  • Mặt khác, nếu n là số lẻ, hãy làm tương tự, nhưng thay vào đó bao gồm các cạnh của biểu mẫu (a,n)khi a chẵn.

Mã kết hợp trường hợp thứ hai và thứ ba bằng cách thay thế điều kiện mod(a+b)4<2bằng mod(a+a)4<2khi cả hai odd nb==n.


5

Brachylog 2 , 24 byte

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

Hãy thử trực tuyến!

Đây là một hàm trả về một cặp bao gồm hai danh sách kề: một cho biểu đồ, một cho biểu đồ bổ sung. (Trong trình thông dịch Brachylog trên TIO, bạn có thể yêu cầu nó đánh giá một hàm, thay vì một chương trình đầy đủ, thông qua việc đưa ra Zlàm đối số dòng lệnh.) Ví dụ: đầu ra cho đầu vào 5là:

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

Đây là những gì trông giống như một hình ảnh (hiển thị hai biểu đồ):

một đồ thị và bổ sung giống hệt nhau trên 5 yếu tố

Như thường thấy trong các ngôn ngữ dựa trên Prolog, chức năng này hỗ trợ nhiều hơn một mẫu cuộc gọi. Đáng chú ý, nếu bạn cố gắng sử dụng nó như một trình tạo, nó sẽ xuất ra tất cả các biểu đồ tự bổ sung có thể với số đỉnh đã cho (mặc dù tôi không mất công sức để làm cho trường hợp này có thể sử dụng được và đáng chú ý là nó sẽ xuất ra từng các đồ thị nhiều lần mỗi).

Giải trình

Đây về cơ bản chỉ là một mô tả về vấn đề, để lại việc triển khai Prolog để tìm ra phương pháp tốt nhất để giải quyết nó. (Tuy nhiên, tôi nghi ngờ rằng nó sẽ sử dụng thuật toán tốt hơn so với lực lượng vũ phu trong trường hợp cụ thể này, vì vậy nó có vẻ khá kém hiệu quả và thử nghiệm dường như xác nhận điều này, cho thấy hiệu suất ngày càng tệ hơn khi đồ thị lớn hơn nhiều.)

{⟦₁⊇Ċ}ᶠ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

Tình cờ, cuối cùng tôi đã phải tiêu tốn toàn bộ 6 byte (chương trình, các ký tự (∨?<2)) để xử lý các trường hợp đặc biệt là 0 và 1. Bực bội, nhưng đó là bản chất của các trường hợp đặc biệt.

Các \\ᵐcdl?phần là một chút khó hiểu, vì vậy đây là một ví dụ cách. Mục đích của nó là để kiểm tra xem một cái gì đó là một biểu đồ và phần bù của nó, với các cạnh tương ứng trong biểu đồ và phần bổ sung có cùng thứ tự trong danh sách hay không. Cặp đồ thị / bổ sung trở thành đầu ra cuối cùng của chương trình. Đây là một ví dụ:

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

Chuyển đổi điều này cho chúng ta một danh sách các cặp cạnh tương ứng giữa biểu đồ và phần bù:

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

Tiếp theo, chúng tôi hoán vị bên trong các phần tử danh sách và làm phẳng một cấp; cung cấp cho chúng tôi danh sách các cặp phần tử tương ứng giữa biểu đồ và phần bù:

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

Rõ ràng, điều chúng ta muốn ở đây là không có nhiều hơn 1 cặp bắt đầu từ mỗi phần tử (do đó chứng minh rằng các phần tử của biểu đồ và phần bù nằm trong sự tương ứng 1-1). Chúng ta gần như có thể xác minh rằng chỉ bằng cách nói rằng danh sách có ?các phần tử riêng biệt chính xác (nghĩa là một số phần tử riêng biệt bằng với số đỉnh). Trong trường hợp này, thử nghiệm thành công; các yếu tố riêng biệt là:

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

Tuy nhiên, điều này để lại chỗ cho một vấn đề tiềm ẩn; nếu một đỉnh hoàn toàn bị ngắt kết nối trong biểu đồ ban đầu, thì sự tương ứng của nó sẽ không được đề cập, để lại chỗ cho một sự tương ứng trùng lặp từ một số đỉnh khác. Nếu đây là trường hợp, đồ thị bổ sung phải có một cạnh giữa đỉnh đó (không mất tính tổng quát, giả sử là nó 1) và mọi đỉnh khác, và do đó, danh sách các tương ứng sẽ chứa [1,2],, [1,3], [1, ?]. Khi ?lớn, điều này sẽ dẫn đến tổng số thư tương ứng nhiều hơn chúng ta có, vì vậy không có vấn đề gì. Vấn đề duy nhất xảy ra khi? 3 hoặc thấp hơn, trong trường hợp đó chúng tôi chỉ kết thúc thêm một thư tương ứng (trong khi xóa một từ1không xuất hiện trong đầu vào); tuy nhiên, đây không phải là vấn đề trong thực tế, vì có 3 cạnh có thể có trên biểu đồ 3 phần tử, đó là một số lẻ (tương tự, 1 cạnh có thể có trên biểu đồ 2 phần tử cũng là một số lẻ), và do đó kiểm tra sẽ thất bại ở \bước này (bạn không thể chuyển đổi một danh sách rách rưới, tức là những danh sách có các phần tử có độ dài khác nhau).


Sự khác biệt giữa z\đó zlà zip tuần hoàn, có nghĩa là [[1,2,3],["a"]]cuối cùng sẽ tồn [[1,"a"],[2,"a"],[3,"a"]]tại z, trong khi nó sẽ thất bại \. \ngay bây giờ chỉ hoạt động trên ma trận vuông; thực hiện trong tương lai sẽ làm cho nó hoạt động như thế nào z, ngoại trừ không theo chu kỳ.
Gây tử vong vào

Tôi thực sự đã tìm ra sự khác biệt bản thân mình, nhưng chỉ sau khi tôi viết lời giải thích. Giải pháp cụ thể này phụ thuộc vào `` chỉ hoạt động trên hình chữ nhật (mặc dù chỉ mất thêm 2 byte nếu bạn không thể tận dụng bước đó).

2

BBC BASIC, 161 byte

Kích thước tệp tokenised 140 byte

Tải xuống thông dịch viên tại 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.

Mã mã

  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.

Giải trình

Điều này sử dụng thuật toán tương tự như Xnor, nhưng tạo ra một đầu ra sơ đồ.

Trường hợp ncó dạng 4x+2hoặc 4x+3không có giải pháp vì số cạnh là số lẻ.

Trường hợp ncó dạng 4x, chúng tôi sắp xếp tất cả các đỉnh trong một vòng tròn và vẽ các cạnh đó bằng (a+b) mod 42 hoặc 3 (không phải 0 hoặc 1 như trong trường hợp của Xnor, vì lý do chơi gôn. Đây là phần bổ sung của giải pháp do Xnor đưa ra.)

Để thấy điều này theo nghĩa hình ảnh hơn, chúng ta lấy mỗi đỉnh thứ hai và vẽ các cạnh đến các đỉnh 1 và 2 theo hướng ngược chiều kim đồng hồ. Điều này xác định nhướng song song, một nửa của tổng số. Sau đó, chúng tôi thêm vào tất cả các cạnh khác song song với chúng.

Phần bù có thể được tìm thấy bằng cách thêm 1 vào cả a và b trong mỗi thông số kỹ thuật cạnh hoặc bằng hình ảnh bằng cách xoay sơ đồ theo 1/nlượt.

Trường hợp ncó dạng 4x + 1, chúng ta thêm một đỉnh khác, được liên kết với mỗi đỉnh thứ hai của đồ thị 4x. Nếu nó được đặt ở trung tâm thì tính đối xứng của sơ đồ sẽ được giữ nguyên, nhưng tôi đã chọn đặt nó bên ngoài vòng tròn chính của các điểm cho rõ ràng.

Đầu ra

Sau đây là một vài trường hợp đầu tiên cho 4x + 1. các trường hợp 4x có thể được nhìn thấy bằng cách xóa đỉnh ở dưới cùng bên phải và các cạnh liên quan của nó.

nhập mô tả hình ảnh ở đây


1

JavaScript (ES6), 191 byte

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

Hàm này trả về một danh sách kề. Nó sử dụng hai thuật toán và phân biệt giữa các đồ thị bổ sung trống và các đầu ra không bằng cách trả về 0thay vì []khi không tồn tại. Thuật toán đầu tiên dựa trên Đồ thị Rado được xây dựng bằng cách sử dụng vị từ BIT và tạo các biểu đồ bổ sung 0-, 1-, 4- và 5 thứ tự hợp lệ. Thuật toán khác, được tìm thấy bởi bạn bè của chúng tôi trong toán học , xây dựng biểu đồ bổ sung đỉnh V + 4 hợp lệ bằng cách áp dụng bổ sung 4 đường dẫn cho biểu đồ bổ sung đỉnh V hợp lệ.

Nó bắt đầu bằng cách xác nhận đầu vào để xác nhận sự tồn tại của đồ thị bổ sung hợp lệ (sử dụng n*~-n/4%1) và nếu thất bại, sẽ trả về 0. Sau đó, nó kiểm tra xem n>5n-4đệ quy cho trường hợp để xây dựng một giải pháp bậc thấp hợp lệ, sau đó áp dụng bổ sung 4 vào danh sách kề kề được trả về trên đường sao lưu chuỗi đệ quy. Cuối cùng, nếu n>5không phải là sự thật, nó lặp từ 0để n-1cho xy, và kiểm tra nếu (y>>x)&1là sự thật. Nếu vậy, thì các nút đó được ghép nối.

Đây là một định dạng dễ đọc hơn của hàm, với các toán tử ternary được mở rộng thành các câu lệnh if-other và eval()s inline:

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

Bản giới thiệu

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.