Xác định nếu một mối quan hệ là bắc cầu


15

Mô tả thử thách

Hãy bắt đầu với một số định nghĩa:

  • một mối quan hệ là một tập hợp các cặp phần tử được đặt hàng (trong thử thách này, chúng tôi sẽ sử dụng các số nguyên)

Ví dụ, [(1, 2), (5, 1), (-9, 12), (0, 0), (3, 2)]là một mối quan hệ.

  • một mối quan hệ được gọi là bắc cầu nếu với bất kỳ hai cặp phần tử nào (a, b)(b, c)trong mối quan hệ này, một cặp (a, c)cũng có mặt,

  • [(1, 2), (2, 4), (6, 5), (1, 4)]mang tính bắc cầu, bởi vì nó chứa (1, 2)(2, 4), nhưng (1, 4)cũng vậy,

  • [(7, 8), (9, 10), (15, -5)]là bắc cầu, bởi vì không có bất kỳ hai cặp nào (a, b), (c, d)hiện tại sao cho b= c.

  • [(5, 9), (9, 54), (0, 0)]không phải là bắc cầu, bởi vì nó chứa (5, 9)(9, 54), nhưng không(5, 54)

Đưa ra một danh sách các cặp số nguyên, xác định xem một mối quan hệ có phải là bắc cầu hay không.

Đầu ra đầu vào

Bạn sẽ được cung cấp một danh sách các cặp số nguyên ở bất kỳ định dạng hợp lý nào. Xem xét một mối quan hệ

[(1, 6), (9, 1), (6, 5), (0, 0)]

Các định dạng sau là tương đương:

[(1, 6), (9, 1), (6, 5), (0, 0)] # list of pairs (2-tuples)
[1, 9, 6, 0], [6, 1, 5, 0] # two lists [x1, x2, ..., xn] [y1, y2, ..., yn]
[[1, 6], [9, 1], [6, 5], [0, 0] # two-dimentional int array
[4, 1, 6, 9, 1, 6, 5, 0, 0] # (n, x1, y1, ..., xn, yn)
[1+6i, 9+i, 6+5i, 0+0i] # list of complex numbers

... many others, whatever best suits golfing purposes

Đầu ra: một giá trị trung thực cho một mối quan hệ bắc cầu, giả mạo khác. Bạn có thể cho rằng đầu vào sẽ bao gồm ít nhất một cặp và các cặp là duy nhất.


Là đầu vào phải là một định dạng giống như danh sách, hoặc nó có thể là một định dạng kề - định dạng giống như ma trận?
xnor

Bạn nên có một trường hợp thử nghiệm chỉ mang tính bắc cầu vì các cặp được đặt hàng. Ví dụ (1,3) (2,1) (3,4) (1,4) (2,4). Nếu các cặp không được đặt hàng, điều này sẽ không có tính bắc cầu vì (2,3)bị thiếu.
Martin Ender

1
@MartinEnder Tôi nghĩ bạn hiểu sai "các cặp theo thứ tự". Tôi không nghĩ nó có nghĩa là các cặp theo thứ tự - Tôi nghĩ nó có nghĩa là mỗi cặp có một thứ tự, trước tiên là thứ hai.
isaacg

@isaacg đó là những gì tôi muốn nói. Nói cách khác, trường hợp thử nghiệm của tôi chỉ là sự thật vì mối quan hệ không hoàn toàn đối xứng.
Martin Ender

Trường hợp thử nghiệm thứ ba ( [(7, 8), (9, 10), (15, -5)]) không nên bắc cầu?
wnnmaw

Câu trả lời:


8

Haskell, 42 byte

f x=and[elem(a,d)x|(a,b)<-x,(c,d)<-x,b==c]

Ví dụ sử dụng: f [(1,2), (2,4), (6,5), (1,4)]-> True.

(Bên ngoài) vòng lặp trên tất cả các cặp (a,b)và vòng lặp (bên trong) trên cùng một cặp, bây giờ được gọi (c,d)và mỗi khi b==ckiểm tra xem đó có phải (a,d)là một cặp tồn tại không. Kết hợp các kết quả với logic and.


Câu trả lời dễ đọc nhất cho đến nay!
Lynn

@Lynn Kiểm tra câu trả lời của Prolog, sau đó ;-)
coredump

4

 Prolog, 66 byte

t(L):-not((member((A,B),L),member((B,C),L),not(member((A,C),L)))).

Mối quan hệ không mang tính bắc cầu nếu chúng ta có thể tìm thấy (A, B) và (B, C) sao cho (A, C) không giữ được.


4

MATL , 27 25 byte

7#u2e!l6MX>thl4$XQttY*g<~

Định dạng đầu vào là một ma trận (sử dụng ;như dấu phân cách hàng) trong đó mỗi cặp quan hệ là một cột. Ví dụ, trường hợp thử nghiệm

[(1, 2), (2, 4), (6, 5), (1, 4)]
[(7, 8), (9, 10), (15, -5)]
[(5, 9), (9, 54), (0, 0)]

lần lượt là đầu vào như

[1 2 6 1; 2 4 5 4]
[7 9 15; 8 10 -5]
[5 9 0; 9 54 0]

Đầu ra thật là một ma trận được hình thành bởi những cái. Falsy là một ma trận chứa ít nhất một số không.

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

Giải trình

Mã trước tiên giảm số nguyên đầu vào thành các giá trị nguyên duy nhất, dựa trên 1. Từ những giá trị đó, nó tạo ra ma trận kề; ma trận nhân nó bằng chính nó; và chuyển đổi các giá trị khác 0 trong ma trận kết quả thành các giá trị. Cuối cùng, nó kiểm tra rằng không có mục nào trong ma trận sau vượt quá ma trận kề.


3

JavaScript (ES6), 69 67 byte

a=>(g=f=>a.every(f))(([b,c])=>g(([d,e])=>c-d|!g(([d,c])=>b-d|c-e)))

Đã lưu 2 byte nhờ một ý tưởng của @Cyoce. Có bốn công thức 69 byte trước đó:

a=>a.every(([b,c])=>a.every(([d,e])=>c-d|a.some(([d,c])=>b==d&c==e)))
a=>!a.some(([b,c])=>!a.some(([d,e])=>c==d&a.every(([d,c])=>b-d|c-e)))
a=>a.every(([b,c])=>a.every(([d,e])=>c-d|!a.every(([d,c])=>b-d|c-e)))
(a,g=f=>a.every(f))=>g(([b,c])=>g(([d,e])=>c-d|!g(([d,c])=>b-d|c-e)))

1
Bạn có thể rút ngắn giải pháp thứ hai bằng cách viết tắt cho.every
Cyoce

@Cyoce Thật vậy, bạn tiết kiệm 3 byte mỗi lần bằng cách viết [e], do đó, mặc dù chi phí 8 byte để gán ebạn vẫn tiết kiệm được một byte. Tuy nhiên, tôi đã tiến thêm một bước bằng cách viết tắt cho a.every, nó đã lưu một byte thứ hai.
Neil

3

Brachylog , 24 byte

'{psc[A:B:B:C],?'e[A:C]}

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

Giải trình:

'{psc[A:B:B:C],?'e[A:C]}
'{                     } it is impossible to find
    c                    a flattened
   s                     subset of
  p                      a permutation of the input
     [A:B:B:C]           that has four elements, with the second and third equal
              ,?         and such that the input
                'e       does not contain
                  [A:C]  a list formed of the first and fourth element

Nói cách khác, nếu đầu vào chứa các cặp [A:B][B:C], chúng ta có thể hoán vị đầu vào để đặt [A:B][B:C]khi bắt đầu, xóa tất cả các thành phần khác và tạo danh sách [A:B:B:C]. Sau đó, chúng tôi trả lại sự thật từ vị ngữ bên trong (falsey từ toàn bộ chương trình) nếu [A:C]không có.


2

CJam (22 byte)

{__Wf%m*{z~~=*}%\-e_!}

Bộ kiểm tra trực tuyến . Đây là một khối ẩn danh (hàm) lấy các phần tử làm một mảng hai cấp, nhưng bộ kiểm tra thực hiện thao tác chuỗi để đưa đầu vào vào một định dạng phù hợp trước tiên.

Mổ xẻ

{         e# Begin a block
  _       e#   Duplicate the argument
  _Wf%    e#   Duplicate again and reverse each pair in this copy
  m*      e#   Cartesian product
  {       e#   Map over arrays of the form [[a b][d c]] where [a b] and [c d]
          e#   are in the relation
    z~~=* e#     b==c ? [a d] : []
  }%
  \-      e#   Remove those transitive pairs which were in the original relation
  e_!     e#   Test that we're only left with empty arrays
}

2

Bình thường, 14 byte

!-eMfqFhTCM*_M

Bộ kiểm tra

Định dạng đầu vào dự kiến ​​là [[0, 0], [0, 1], ... ]

!-eMfqFhTCM*_M
!-eMfqFhTCM*_MQQQ    Variable introduction
            _MQ      Reverse all of the pairs
           *   Q     Cartesian product with all of the pairs
         CM          Transpose. We now have [[A2, B1], [A1, B2]] for each pair
                     [A1, A2], [B1, B2] in the input.
    f                Filter on
       hT            The first element (the middle two values)
     qF              Being equal
  eM                 Take the end of all remaining elements (other two values)
 -              Q    Remove the pairs that are in the input
!                    Negate. True if no transitive pairs were not in the input

2

Toán học, 49 byte

#/.{x=___,{a_,b_},x,{b_,c_},x}/;#~FreeQ~{a,c}:>0&

Hàm thuần túy có một danh sách các cặp. Nếu danh sách đầu vào chứa {a,b}{b,c}không {a,c}dành cho một số a, b, c, hãy thay thế nó bằng 0. Truthy là danh sách đầu vào, giả là 0.


1

C ++ 14, 140 byte

Như lambda chưa được đặt tên trở lại thông qua tham số tham chiếu. Yêu cầu đầu vào của nó là một container của pair<int,int>. Lấy cách tiếp cận O (n ^ 3) nhàm chán.

[](auto m,int&r){r=1;for(auto a:m)for(auto b:m)if (a.second==b.first){int i=0;for(auto c:m)i+=a.first==c.first&&b.second==c.second;r*=i>0;}}

Ungolfed và cách sử dụng:

#include<vector>
#include<iostream>

auto f=
[](auto m,int&r){
  r=1;                         //set return flag to true
  for(auto a:m)                //for each element
    for(auto b:m)              //check with second element
      if (a.second==b.first){  //do they chain?
        int i=0;               //flag for local transitivity
        for(auto c:m)          //search for a third element
          i+=a.first==c.first&&b.second==c.second;
        r*=i>0;                //multiply with flag>0, resulting in 0 forever if one was not found
      }
}
;

int main(){
 std::vector<std::pair<int,int>> m={
  {1, 2}, {2, 4}, {6, 5}, {1, 4}
 };

 int r;
 f(m,r);
 std::cout << r << std::endl;

 m.emplace_back(3,6);
 f(m,r);
 std::cout << r << std::endl;

 m.emplace_back(3,5);
 f(m,r);
 std::cout << r << std::endl;

}


0

Tiên đề 103 byte

c(x)==(for i in x repeat for j in x repeat if i.2=j.1 and ~member?([i.1, j.2],x)then return false;true)

vô dụng:

c(x)==
  for i in x repeat
    for j in x repeat
       if i.2=j.1 and ~member?([i.1, j.2],x) then return false
  true

                                                                   Type: Void

bài tập

(2) -> c([[1,2],[2,4],[6,5],[1,4]])
   Compiling function c with type List List PositiveInteger -> Boolean
   (2)  true
                                                                Type: Boolean
(3) -> c([[7,8],[9,10],[15,-5]])
   Compiling function c with type List List Integer -> Boolean
   (3)  true
                                                            Type: Boolean
(4) -> c([[5,9],[9,54],[0,0]])
   Compiling function c with type List List NonNegativeInteger ->
      Boolean
   (4)  false


0

Clojure, 56 53 byte

Cập nhật: Thay vì sử dụng :whentôi sẽ chỉ kiểm tra cho tất cả các cặp của [a b] [c d]một trong hai b != choặc [a d]được tìm thấy từ tập đầu vào.

#(every? not(for[[a b]%[c d]%](=[b nil][c(%[a d])])))

Nguyên:

Wow, Clojure cho các vòng lặp rất tuyệt: D Điều này kiểm tra rằng forvòng lặp không tạo ra giá trị giả, xảy ra nếu [a d]không tìm thấy từ bộ đầu vào.

#(not(some not(for[[a b]%[c d]% :when(= b c)](%[a d]))))

Đầu vào này phải là một tập các vectơ hai phần tử:

(f (set [[1, 2], [2, 4], [6, 5], [1, 4]]))
(f (set [[7, 8], [9, 10], [15, -5]]))
(f (set [[5, 9], [9, 54], [0, 0]]))

Nếu đầu vào phải giống như danh sách thì (%[a d])phải thay thế ((set %)[a d])thêm 6 byte.


0

Cả hai giải pháp này đều là các hàm không tên, lấy danh sách các cặp theo thứ tự làm đầu vào và trả về Truehoặc False.

Toán học, 65 byte

SubsetQ[#,If[#2==#3,{#,#4},Nothing]&@@@Join@@@#~Permutations~{2}]&

#~Permutations~{2}]tạo danh sách tất cả các cặp được sắp xếp theo thứ tự từ đầu vào và Join@@@chuyển đổi chúng thành bốn lần theo thứ tự. Các hàm này sau đó được vận hành theo hàm If[#2==#3,{#,#4},Nothing]&@@@, có một thuộc tính tuyệt vời: nếu hai phần tử ở giữa bằng nhau, nó sẽ trả về cặp theo thứ tự bao gồm các số đầu tiên và số cuối; nếu không thì nó trở lạiNothing , một mã thông báo Mathicala đặc biệt tự động biến mất khỏi danh sách. Vì vậy, kết quả là tập hợp các cặp theo thứ tự cần có trong đầu vào để nó có tính bắc cầu;SubsetQ[#,...]phát hiện tài sản đó.

Toán học, 70 byte

And@@And@@@Table[Last@i!=#&@@j||#~MemberQ~{#&@@i,Last@j},{i,#},{j,#}]&

Table[...,{i,#},{j,#}]tạo một mảng 2D được lập chỉ mục bởi ij, được lấy trực tiếp từ đầu vào (do đó là cả hai cặp theo thứ tự). Chức năng của hai chỉ số là Last@i!=#&@@j||#~MemberQ~{#&@@i,Last@j}, nghĩa là "một trong hai yếu tố thứ hai của ivà các yếu tố đầu tiên của jkhông phù hợp, hoặc nếu không đầu vào chứa các cặp lệnh bao gồm các yếu tố đầu tiên của ivà yếu tố cuối cùng của j". Điều này tạo ra một mảng booleans 2D, And@@And@@@làm phẳng thành một boolean duy nhất.


0

APL (NARS), 39 ký tự, 78 byte

{∼∨/{(=/⍵[2 3])∧∼(⊂⍵[1 4])∊w}¨,⍵∘.,w←⍵}

kiểm tra:

  f←{∼∨/{(=/⍵[2 3])∧∼(⊂⍵[1 4])∊w}¨,⍵∘.,w←⍵}
  f (1 2) (2 4) (6 5) (1 4)
1
  f (7 8) (9 10) (15 ¯5)
1
  f (5 9) (9 54) (0 0)
0

một giây 'giải pháp' theo cách goto:

r←q w;i;j;t;v
r←1⋄i←0⋄k←↑⍴w⋄→3
r←0⋄→0
→0×⍳k<i+←1⋄t←i⊃w⋄j←0
→3×⍳k<j+←1⋄v←j⊃w⋄→4×⍳t[2]≠v[1]⋄→2×⍳∼(⊂t[1]v[2])∊w

0

Lisp thông thường, 121 byte

(lambda(x)(not(loop for(a b)in x thereis(loop for(c d)in x do(if(= b c)(return(not(member`(,a ,d) x :test #'equal))))))))

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

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.