Determina se una relazione è transitiva


15

Descrizione della sfida

Cominciamo con alcune definizioni:

  • una relazione è un insieme di coppie ordinate di elementi (in questa sfida, useremo numeri interi)

Ad esempio, [(1, 2), (5, 1), (-9, 12), (0, 0), (3, 2)]è una relazione.

  • una relazione è chiamata transitiva se per due coppie di elementi (a, b)e (b, c)in questa relazione (a, c)è presente anche una coppia ,

  • [(1, 2), (2, 4), (6, 5), (1, 4)]è transitivo, perché contiene (1, 2)e (2, 4), ma (1, 4)anche

  • [(7, 8), (9, 10), (15, -5)]è transitivo, perché non ci sono due coppie (a, b), (c, d)presenti in modo tale che b= c.

  • [(5, 9), (9, 54), (0, 0)]non è transitivo, perché contiene (5, 9)e (9, 54), ma non(5, 54)

Dato un elenco di coppie di numeri interi, determinare se una relazione è transitiva o meno.

Input Output

Ti verrà dato un elenco di coppie di numeri interi in qualsiasi formato ragionevole. Prendi in considerazione una relazione

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

I seguenti formati sono equivalenti:

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

Output: un valore veritiero per una relazione transitiva, falsa altrimenti. Si può presumere che l'input consisterà in almeno una coppia e che le coppie siano uniche.


L'input deve essere un formato simile a un elenco o può essere un adiacenza - formato simile a una matrice?
xnor

Dovresti avere un caso di prova che è solo transitivo perché le coppie sono ordinate. Es (1,3) (2,1) (3,4) (1,4) (2,4). Se le coppie non fossero ordinate, questo non sarebbe transitivo perché (2,3)mancante.
Martin Ender,

1
@MartinEnder Penso che tu abbia interpretato male le "coppie ordinate". Non penso che significhi le coppie in un ordine - penso che significhi che ogni coppia ha un ordine, prima poi secondo.
isaacg,

@isaacg è quello che volevo dire. In altre parole, il mio caso di test è solo vero perché la relazione non è implicitamente simmetrica.
Martin Ender,

Il terzo caso di test ( [(7, 8), (9, 10), (15, -5)]) non dovrebbe essere transitivo?
wnnmaw,

Risposte:


8

Haskell, 42 byte

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

Esempio di utilizzo: f [(1,2), (2,4), (6,5), (1,4)]-> True.

Ciclo (esterno) su tutte le coppie (a,b)e ciclo (interno) sulle stesse coppie, ora chiamato (c,d)e ogni volta che b==ccontrolla se (a,d)esiste anche una coppia esistente. Combina i risultati con logico and.


La risposta più leggibile finora!
Lynn,

@Lynn Dai un'occhiata alla risposta di Prolog, quindi ;-)
coredump

4

 Prolog, 66 byte

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

La relazione è non transitiva se possiamo trovare (A, B) e (B, C) tale che (A, C) non regge.


4

MATL , 27 25 byte

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

Il formato di input è una matrice (che utilizza ;come separatore di riga) in cui ogni coppia della relazione è una colonna. Ad esempio, casi di test

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

sono rispettivamente inseriti come

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

L' output vero è una matrice formata da quelli. Falsy è una matrice che contiene almeno uno zero.

Provalo online!

Spiegazione

Il codice prima riduce gli interi di input a valori interi univoci basati su 1. Da questi valori genera la matrice di adiacenza; matrice lo moltiplica da solo; e converte i valori diversi da zero nella matrice dei risultati in uno. Infine, verifica che nessuna voce in quest'ultima matrice superi quella nella matrice di adiacenza.


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

Salvato 2 byte grazie a un'idea di @Cyoce. C'erano quattro precedenti formulazioni a 69 byte:

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
Potresti essere in grado di abbreviare la seconda soluzione facendo un'abbreviazione per.every
Cyoce,

@Cyoce In effetti, si risparmiano 3 byte ogni volta scrivendo [e], quindi anche se costa 8 byte assegnare esi salva comunque un byte. Tuttavia, ho fatto un ulteriore passo facendo un'abbreviazione per a.every, che ha salvato un secondo byte.
Neil,

3

Brachylog , 24 byte

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

Provalo online!

Spiegazione:

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

In altre parole, se l'input contiene coppie [A:B]e [B:C], possiamo consentire all'input di inserire [A:B]e [B:C], all'inizio, eliminare tutti gli altri elementi e produrre un elenco [A:B:B:C]. Quindi restituiamo la verità dal predicato interno (la falsità dell'intero programma) se [A:C]non c'è.


2

CJam (22 byte)

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

Suite di test online . Questo è un blocco (funzione) anonimo che accetta gli elementi come un array a due livelli, ma la suite di test esegue la manipolazione delle stringhe per inserire prima l'input in un formato adatto.

Dissezione

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

!-eMfqFhTCM*_M

Suite di test

Il formato di input dovrebbe essere [[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

Mathematica, 49 byte

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

Funzione pura che prende un elenco di coppie. Se l'elenco di input contiene {a,b}e {b,c}non {a,c}per alcuni a, b, c, lo sostituisce con 0. La verità è la lista di input, la falsità lo è 0.


1

C ++ 14, 140 byte

Come lambda senza nome che ritorna tramite parametro di riferimento. Richiede che il suo input sia un contenitore di pair<int,int>. Adottando l'approccio noioso 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 e utilizzo:

#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

Axiom 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)

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

gli esercizi

(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

Aggiornamento: Invece di utilizzare :whenmi limiterò a verificare che per tutte le coppie di [a b] [c d]uno b != co[a d] si trova dal set di input.

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

Originale:

Wow, Clojure per i loop è interessante: D Questo verifica che il forloop non generi un valore errato, che si verifica se [a d]non viene trovato dal set di input.

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

Questo input deve essere un insieme di vettori a due elementi:

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

Se l'input deve essere simile a un elenco, (%[a d])è necessario sostituirlo con ((set %)[a d])altri 6 byte.


0

Entrambe queste soluzioni sono funzioni senza nome che prendono un elenco di coppie ordinate come input e return Trueo False.

Mathematica, 65 byte

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

#~Permutations~{2}]crea l'elenco di tutte le coppie ordinate di coppie ordinate dall'input e Join@@@converte quelle in quadruple ordinate. Questi vengono quindi gestiti dalla funzione If[#2==#3,{#,#4},Nothing]&@@@, che ha una proprietà interessante: se i due elementi centrali sono uguali, restituisce la coppia ordinata costituita dal primo e dall'ultimo numero; altrimenti ritorna Nothing, uno speciale token Mathematica che scompare automaticamente dagli elenchi. Quindi il risultato è l'insieme di coppie ordinate che deve essere nell'input per essere transitivo; SubsetQ[#,...]rileva quella proprietà.

Mathematica, 70 byte

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

Table[...,{i,#},{j,#}]crea un array 2D indicizzato da ie j, che sono presi direttamente dall'input (quindi sono entrambe le coppie ordinate). La funzione di questi due indici è Last@i!=#&@@j||#~MemberQ~{#&@@i,Last@j}, che si traduce in "o il secondo elemento di ie il primo elemento di jnon corrispondono, oppure l'input contiene la coppia ordinata costituita dal primo elemento ie dall'ultimo elemento di j". Questo crea una matrice 2D di booleani, che And@@And@@@si appiattisce in un singolo booleano.


0

APL (NARS), 39 caratteri, 78 byte

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

test:

  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

un secondo 'soluzione' segue goto modi:

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 comune, 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))))))))

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.