Определить, является ли отношение транзитивным

15

Описание задачи

Давайте начнем с некоторых определений:

  • отношение есть множество упорядоченных пар элементов (в этой проблеме, мы будем использовать целые числа)

Например, [(1, 2), (5, 1), (-9, 12), (0, 0), (3, 2)]это отношение.

  • отношение называется транзитивным, если для любых двух пар элементов (a, b)и (b, c)в этом отношении (a, c)также присутствует пара ,

  • [(1, 2), (2, 4), (6, 5), (1, 4)]является переходным, потому что он содержит (1, 2)и (2, 4), но (1, 4)также,

  • [(7, 8), (9, 10), (15, -5)]является транзитивным, потому что нет двух пар (a, b), (c, d)представленных так, что b= c.

  • [(5, 9), (9, 54), (0, 0)]не является переходным, потому что он содержит (5, 9)и (9, 54), но не(5, 54)

Учитывая список пар целых чисел, определите, является ли отношение транзитивным или нет.

Ввод, вывод

Вам будет предоставлен список пар целых чисел в любом разумном формате. Рассмотрим отношение

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

Следующие форматы эквивалентны:

[(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

Вывод: истинное значение для транзитивного отношения, иначе ложь. Вы можете предположить, что вход будет состоять как минимум из одной пары, и что пары будут уникальными.

shooqie
источник
Должен ли ввод быть форматом, подобным списку, или это может быть формат смежности, подобный матрице?
xnor
У вас должен быть тестовый случай, который является только транзитивным, потому что пары упорядочены. Например (1,3) (2,1) (3,4) (1,4) (2,4). Если бы пары не были заказаны, это не было бы транзитивно, потому что (2,3)отсутствует.
Мартин Эндер
1
@MartinEnder Я думаю, что вы неправильно истолковали "упорядоченные пары". Я не думаю, что это означает, что пары в порядке - я думаю, что это означает, что у каждой пары есть порядок, сначала, а затем второй.
Исаак
@isaacg вот что я имел ввиду. Другими словами, мой тестовый пример является только правдивым, потому что отношение не является неявно симметричным.
Мартин Эндер
Должен ли третий контрольный пример ( [(7, 8), (9, 10), (15, -5)]) не быть транзитивным?
wnnmaw

Ответы:

8

Haskell, 42 байта

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

Пример использования: f [(1,2), (2,4), (6,5), (1,4)]-> True.

(Внешний) цикл по всем парам (a,b)и (внутренний) цикл по одним и тем же парам, теперь вызываемым (c,d)и каждый раз, когда b==cпроверяется, существует ли (a,d)также существующая пара. Объедините результаты с логическим and.

Ними
источник
Самый читаемый ответ на данный момент!
Линн
@Lynn Зацените ответ на Пролог, тогда ;-)
coredump
4

 Пролог, 66 байт

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

Отношение не транзитивно, если мы можем найти (A, B) и (B, C) такие, что (A, C) не выполняется.

CoreDump
источник
4

MATL , 27 25 байт

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

Формат ввода - это матрица (используется в ;качестве разделителя строк), где каждая пара отношения является столбцом. Например, тесты

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

соответственно вводятся как

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

Истинный вывод - это матрица, образованная единицами. Ложь - это матрица, которая содержит хотя бы один ноль.

Попробуйте онлайн!

объяснение

Сначала код сокращает входные целые до уникальных целочисленных значений, основанных на 1. Из этих значений он генерирует матрицу смежности; матрица умножает это сама; и преобразует ненулевые значения в матрице результатов в единицы. Наконец, он проверяет, что ни одна запись в последней матрице не превышает записи в матрице смежности.

Луис Мендо
источник
3

JavaScript (ES6), 69 67 байт

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

Сохранено 2 байта благодаря идее @Cyoce. Было четыре предыдущих 69-байтовых формулировки:

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
Возможно, вы сможете сократить второе решение, сделав аббревиатуру для.every
Cyoce
@Cyoce Действительно, вы каждый раз сохраняете 3 байта, записывая [e], поэтому, даже если для назначения eвам потребуется 8 байтов, вы все равно сохраняете байт. Однако я пошел дальше, сделав аббревиатуру для a.every, которая сохранила второй байт.
Нил
3

Брахилог , 24 байта

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

Попробуйте онлайн!

Объяснение:

'{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

Другими словами, если вход содержит пары [A:B]и [B:C], мы можем переставить вход для ввода [A:B]и [B:C]в начале, удалить все остальные элементы и создать список [A:B:B:C]. Затем мы возвращаем истину из внутреннего предиката (фальси из всей программы), если [A:C]его там нет.


источник
2

CJam (22 байта)

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

Набор онлайн-тестов . Это анонимный блок (функция), который принимает элементы как двухуровневый массив, но набор тестов выполняет строковые манипуляции, чтобы сначала поместить ввод в подходящий формат.

рассечение

{         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

Pyth, 14 байт

!-eMfqFhTCM*_M

Тестирование

Ожидается, что формат ввода [[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
isaacg
источник
2

Mathematica, 49 байтов

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

Чистая функция, которая принимает список пар. Если список содержит входной {a,b}и , {b,c}но не {a,c}для некоторых a, b, c, заменяет его 0. Истина это входной список, ложь есть 0.

ngenisis
источник
1

C ++ 14, 140 байт

В качестве неназванного лямбда возвращается через ссылочный параметр. Требует, чтобы его вход был контейнером pair<int,int>. Принимая скучный подход O (n ^ 3).

[](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 и использование:

#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;

}
Карл Напф
источник
1

Python 2 , 91 67 55 байт

lambda s:all(b-c or(a,d)in s for a,b in s for c,d in s)

Попробуйте онлайн!

-24 байта благодаря Leaky Nun
-12 байтов благодаря Bubbler

HyperNeutrino
источник
67 байт (и исправили свой код, изменив lambda xна lambda s.
Leaky Nun
@ LeakyNun Ой, это было глупо с моей стороны. Благодарность!
HyperNeutrino
55 байтов при распаковке в fors.
Bubbler
@Bubbler о, круто, спасибо
HyperNeutrino
0

Аксиома 103 байта

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)

ungolfed:

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

упражнения

(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
RosLuP
источник
0

Clojure, 56 53 байта

Обновление: Вместо того , чтобы использовать :whenя просто проверить , что для всех пар [a b] [c d]либо b != cили [a d]находится из входного набора.

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

Оригинал:

Ничего себе, Clojure для циклов это круто: D Это проверяет, что forцикл не генерирует ложное значение, которое происходит, если [a d]не найдено из входного набора.

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

Этот вход должен быть набором двухэлементных векторов:

(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]]))

Если входные данные должны быть похожими на список, то (%[a d])должны быть заменены ((set %)[a d])на дополнительные 6 байтов.

NikoNyrh
источник
0

Оба эти решения являются неназванными функциями, принимающими список упорядоченных пар в качестве входных данных и возвращающих True или False.

Mathematica, 65 байт

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

#~Permutations~{2}]создает список всех упорядоченных пар упорядоченных пар из входных данных и Join@@@преобразует их в упорядоченные четверки. Затем они обрабатываются функцией If[#2==#3,{#,#4},Nothing]&@@@, которая имеет классное свойство: если два средних элемента равны, она возвращает упорядоченную пару, состоящую из первого и последнего чисел; в противном случае возвращается Nothingспециальный токен Mathematica, который автоматически исчезает из списков. Таким образом, результатом является набор упорядоченных пар, которые должны быть на входе, чтобы он был транзитивным;SubsetQ[#,...]обнаруживает это свойство.

Mathematica, 70 байт

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

Table[...,{i,#},{j,#}]создает двумерный массив с индексами iи j, которые берутся непосредственно из входных данных (отсюда обе упорядоченные пары). Функция этих двух индексов есть Last@i!=#&@@j||#~MemberQ~{#&@@i,Last@j}, что переводится как «либо второй элемент iи первый элемент jне совпадают, либо вход содержит упорядоченную пару, состоящую из первого элемента iи последнего элемента j». Это создает двумерный массив логических значений, который And@@And@@@превращается в единый логический тип.

Грег Мартин
источник
0

APL (NARS), 39 символов, 78 байтов

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

тестовое задание:

  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

одну секунду «решение» следуйте по пути:

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
RosLuP
источник