Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Challenge description

Let's start with some definitions:

  • a relation is a set of ordered pairs of elements (in this challenge, we'll be using integers)

For instance, [(1, 2), (5, 1), (-9, 12), (0, 0), (3, 2)] is a relation.

  • a relation is called transitive if for any two pairs of elements (a, b) and (b, c) in this relation, a pair (a, c) is also present,

  • [(1, 2), (2, 4), (6, 5), (1, 4)] is transitive, because it contains (1, 2) and (2, 4), but (1, 4) as well,

  • [(7, 8), (9, 10), (15, -5)] is transitive, because there aren't any two pairs (a, b), (c, d) present such that b = c.

  • [(5, 9), (9, 54), (0, 0)] is not transitive, because it contains (5, 9) and (9, 54), but not (5, 54)

Given a list of pairs of integers, determine if a relation is transitive or not.

Input / output

You will be given a list of pairs of integers in any reasonable format. Consider a relation

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

The following formats are equivalent:

[(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: a truthy value for a transitive relation, falsy otherwise. You may assume that the input will consist of at least one pair, and that the pairs are unique.

share|improve this question
    
Does the input have to be a list-like format, or can it be an adjacency--matrix-like format? – xnor 21 hours ago
    
You should have a test case that is only transitive because the pairs are ordered. E.g. (1,3) (2,1) (3,4) (1,4) (2,4). If the pairs weren't ordered, this wouldn't be transitive because (2,3) is missing. – Martin Ender 21 hours ago
    
@MartinEnder I think you misinterpreted "ordered pairs". I don't think it means the pairs in an order - I think it means each pair has an order, first then second. – isaacg 17 hours ago
    
@isaacg that's what I meant. In other words, my test case is only truthy because the relation isn't implicitly symmetric. – Martin Ender 13 hours ago
    
Should the third test case ([(7, 8), (9, 10), (15, -5)]) be not transitive? – wnnmaw 4 hours ago

Haskell, 42 bytes

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

Usage example: f [(1,2), (2,4), (6,5), (1,4)]-> True.

(Outer)loop over all pairs (a,b) and (inner)loop over the same pairs, now called (c,d) and every time when b==c check if (a,d)is also an existent pair. Combine the results with logical and.

share|improve this answer
    
Most readable answer so far! – Lynn 16 hours ago
    
@Lynn Check out the Prolog answer, then ;-) – coredump 3 hours ago

JavaScript (ES6), 69 67 bytes

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

Saved 2 bytes thanks to an idea by @Cyoce. There were four previous 69-byte formulations:

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)))
share|improve this answer
1  
You might be able to shorten the second solution by making an abbreviation for .every – Cyoce 19 hours ago
    
@Cyoce Indeed, you save 3 bytes each time by writing [e], so even though it costs 8 bytes to assign e you still save a byte. However, I went a step further by making an abbreviation for a.every, which saved a second byte. – Neil 19 hours ago

MATL, 27 25 bytes

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

Input format is a matrix (using ; as row separator) where each pair of the relation is a column. For example, test cases

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

are respectively input as

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

Truthy output is a matrix formed by ones. Falsy is a matrix that contains at least one zero.

Try it online!

Explanation

The code first reduces the input integers to unique, 1-based integer values. From those values it generates the adjacency matrix; matrix-multiplies it by itself; and converts nonzero values in the result matrix to ones. Finally, it checks that no entry in the latter matrix exceeds that in the adjacency matrix.

share|improve this answer

CJam (22 bytes)

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

Online test suite. This is an anonymous block (function) which takes the elements as a two-level array, but the test suite does string manipulation to put the input into a suitable format first.

Dissection

{         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
}
share|improve this answer

Pyth, 14 bytes

!-eMfqFhTCM*_M

Test suite

Input format is expected to be [[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
share|improve this answer

 Prolog, 66 bytes

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

The relation is not transitive if we can find (A,B) and (B,C) such that (A,C) doesn't hold.

share|improve this answer

Axiom 103 bytes

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

the exercises

(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
share|improve this answer

Pyth - 22 21 bytes

.Am},hdedQfqFtPTsM^Q2

Test Suite.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.