Check if a matrix is a Toeplitz matrix

11

1

You will be given a two-dimensional array and a number and you are asked to find whether the given matrix is Toeplitz or not.

Input Format:

You will be given a function which will take two-dimensional matrix as argument.

Output Format:

Return 1 from the function if the matrix is Toeplitz, else return -1.

Constraints:

3 < n,m < 10,000,000

where n is the number of rows while m will be the number of columns.

Sample Test Case:

Sample Input :
4 
5
6 7 8 9 2
4 6 7 8 9
1 4 6 7 8
0 1 4 6 7 

Sample Output : 
1 

Scoring

This is , so the shortest answer in bytes wins.

user67947

Posted 2017-05-18T05:45:09.720

Reputation:

8

This is a good challenge, but we prefer laxer I/O requirements here. I'd suggest allowing both programs and functions as is the default. And to allow True/False or 1/0 as outputs, or perhaps just any two consistent distinct outputs as seems to be preferred for decision problems.

– xnor – 2017-05-18T05:59:07.583

15Also, a definition of Toeplitz would be good, as would be more test cases including non-Toeplitz ones. Not sure what you mean about adding code. – xnor – 2017-05-18T06:00:51.197

5I think you must reduce the maximum value of n,m. Otherwise the main part of this challenge is to find a way to process a 1 terabyte matrix. – Stewie Griffin – 2017-05-18T07:25:19.850

1Will the matrix elements always be non-negative integers? – Martin Ender – 2017-05-18T13:52:13.150

Answers

7

Mathematica, 42 bytes

2Boole[#==ToeplitzMatrix[#&@@@#,#&@@#]]-1&

Mathematica doesn't have a built-in to check whether something is a Toeplitz matrix, but it does have a built-in to generate one. So we generate one from the first column (#&@@@#) and the first row (#&@@#) of the input and check whether it's equal to the input. To convert the True/False result to 1/-1 we use Boole (to give 1 or 0) and then simply transform the result with 2x-1.

Martin Ender

Posted 2017-05-18T05:45:09.720

Reputation: 184 808

6

Octave, 30 bytes

I'm assuming I don't have to handle 1,000,000x1,000,000 matrices as it says in the challenge. This works for matrices that don't exceed the available memory (less than 1 TB in my case).

@(x)x==toeplitz(x(:,1),x(1,:))

Try it online!

This takes a matrix x as input and creates a Toeplitz matrix based on the values on the first column, and the first row. It will then check each element of the matrices for equality. IF all elements are equal then the input is a Toeplitz matrix.

The output will be a matrix of the same dimensions as the input. If there are any zeros in the output then that's considered falsy be Octave.

Edit:

Just noticed the strict output format:

This works for 41 bytes. It might be possible to golf off a byte or two from this version, but I hope the output rules will be relaxed a bit.

@(x)2*(0||(x==toeplitz(x(:,1),x(1,:))))-1

Stewie Griffin

Posted 2017-05-18T05:45:09.720

Reputation: 43 471

5

Jelly, 5 bytes

ŒDE€Ạ

Try it online!

Following the definition here.

ŒDE€Ạ
ŒD     all diagonals
   €   for each diagonal ...
  E       all elements are equal
    Ạ  all diagonal return true

Leaky Nun

Posted 2017-05-18T05:45:09.720

Reputation: 45 011

5

05AB1E, 11 bytes

Œ2ùvy`¦s¨QP

Try it online!

Explanation

Π            # get all sublists of input
 2ù           # keep only those of length 2
   v          # for each such pair
    y`        # split to separate lists
      ¦       # remove the first element of the second list
       s¨     # remove the last element of the first list
         Q    # compare for equality
          P   # product of stack

Emigna

Posted 2017-05-18T05:45:09.720

Reputation: 50 798

4

Haskell, 43 bytes

f(a:b:t)|init a==tail b=f$b:t|1>0= -1
f _=1

Try it online!

xnor

Posted 2017-05-18T05:45:09.720

Reputation: 115 687

Dang, overcomplicating it again. Curiously, I get that down to 39 bytes with truthy/falsy output, so if Toeplitz = False were allowed I might have beaten it by one byte. – Ørjan Johansen – 2017-05-19T02:04:55.323

3

Mathematica, 94 bytes

l=Length;If[l@Flatten[Union/@Table[#~Diagonal~k,{k,-l@#+1,l@#[[1]]-1}]]==l@#+l@#[[1]]-1,1,-1]&

input

{{6, 7, 8, 9, 2}, {4, 6, 7, 8, 9}, {1, 4, 6, 7, 8}, {0, 1, 4, 6, 7}}

another one based on Stewie Griffin's algorithm

Mathematica, 44 bytes

If[#==#[[;;,1]]~ToeplitzMatrix~#[[1]],1,-1]&

J42161217

Posted 2017-05-18T05:45:09.720

Reputation: 15 931

2Do you need to define s? Can't you just use # instead? – Not a tree – 2017-05-18T07:51:08.413

yes! you are right! – J42161217 – 2017-05-18T08:04:32.290

3

Java 7, 239 233 220 113 bytes

int c(int[][]a){for(int i=a.length,j;i-->1;)for(j=a[0].length;j-->1;)if(a[i][j]!=a[i-1][j-1])return -1;return 1;}

-107 bytes after a tip of using a more efficient algorithm thanks to @Neil.

Explanation:

Try it here.

int c(int[][]a){                // Method with integer-matrix parameter and integer return-type
  for(int i=a.length,j;i-->1;)  //  Loop over the rows (excluding the first)
    for(j=a[0].length;j-->1;)   //   Loop over the columns (excluding the first)
      if(a[i][j]!=a[i-1][j-1])  //    If the current cell doesn't equal the one top-left of it:
        return -1;              //     Return -1
                                //   End of columns loop (implicit / single-line body)
                                //  End of rows loop (implicit / single-line body)
  return 1;                     //  Return 1
}                               // End of method

Kevin Cruijssen

Posted 2017-05-18T05:45:09.720

Reputation: 67 575

what is r & c in first function? – Mickey Jack – 2017-05-18T07:43:50.127

@MickeyJack Rows and columns (r = n and c = m if you compare it to the challenge). – Kevin Cruijssen – 2017-05-18T07:45:16.273

Shouldn't you pass the array as a parameter to the function? Also, there is a much more efficient algorithm for this, which would cut your byte count by about 50%. – Neil – 2017-05-18T09:14:35.200

@Neil Well, it saves 13 bytes to put it on class-level instead, and you'll still have to set the array before calling the method (which can be seen in the TIO). I believe this is an allowed rule regarding code-golf, but I'll see if I can find a meta-post as confirmation. As for the more efficient algorithm: I'm sure there is, but which one are you talking about? – Kevin Cruijssen – 2017-05-18T09:18:17.787

1@KevinCruijssen Simply check that all elements not in the first row or column equal the element diagonally up and left from it. – Neil – 2017-05-18T09:57:35.870

@Neil Ah of course. It's obvious now that you say it, but still brilliant. Thanks, it indeed halved the byte-count. – Kevin Cruijssen – 2017-05-18T12:24:45.370

1Ah, you even got to use the --> operator! – Neil – 2017-05-18T12:44:11.603

@Neil Always a useful operator to use. And I also like the +++ or --- operators in Java, which I unfortunately haven't used in this answer. ;p – Kevin Cruijssen – 2017-05-18T12:49:51.657

3

Haskell, 51 bytes

t takes a list of lists of integers and returns an integer.

t m=1-sum[2|or$zipWith((.init).(/=).tail)=<<tail$m]

Try it online!

This could have been 39 or 38 bytes with truthy/falsy output.

The idea to use init was inspired by Emigna's 05AB1E answer, which uses a very similar method; before that I used a nested zipping.

How it works

  • zipWith((.init).(/=).tail)=<<tail is a point-free form of \m->zipWith(\x y->tail x/=init y)(tail m)m.
  • This combines each consecutive pair of rows of m, checking if the first with first element removed is different from the second with second element removed.
  • The or then combines the checks for all pairs of rows.
  • 1-sum[2|...] converts the output format.

Ørjan Johansen

Posted 2017-05-18T05:45:09.720

Reputation: 6 914

2

JavaScript (ES6), 65 54 bytes

a=>a.some((b,i)=>i--&&b.some((c,j)=>c-a[i][j-1]))?-1:1

Neil

Posted 2017-05-18T05:45:09.720

Reputation: 95 035

Or using your own trick: a=>a.some(b=>b.some((v,i)=>d[i]-(d[i]=v),d=[,...d]),d=[])?-1:1 (62 bytes)

– Arnauld – 2017-05-18T08:45:41.570

1@Arnauld Thanks, but it turns out I was over-thinking the problem again... – Neil – 2017-05-18T09:02:09.460

2

Ruby, 54 bytes

->a,b,m{m.reduce{|x,y|x[0..-2]==y[1,b]?y:[]}.size<=>1}

Exactly as specified, can be golfed more if flexible input/output is accepted.

Explanation:

Iterate on the matrix, and compare each line with the line above, shifted by one to the right. If they are different, use an empty array for the next iteration. At the end, return -1 if the final array is empty, or 1 if it's at least 2 elements (since the smallest possible matrix is 3x3, this is true if all comparisons return true)

Try it online!

G B

Posted 2017-05-18T05:45:09.720

Reputation: 11 099

Nice use of <=> to compute the result! – Neil – 2017-05-18T09:09:52.323

How about |(*x,_),y| so you don't need to slice x? – Stefan Pochmann – 2018-01-22T12:09:45.247

1

PHP, 70 bytes

<?=!preg_match('/\[([\d,]+?),\d+\],\[\d+,(?!\1)/',json_encode($_GET));

user63956

Posted 2017-05-18T05:45:09.720

Reputation: 1 571

1

Python, 108

r=range
f=lambda x,n,m:all([len(set([x[i][j] for i in r(n) for j in r(m) if j-i==k]))==1 for k in r(1-n,m)])

Not efficient at all since it touches every element n+m times while filtering for diagonals. Then checks if there are more than one unique element per diagonal.

DenDenDo

Posted 2017-05-18T05:45:09.720

Reputation: 2 811

1

Axiom, 121 bytes

f(m)==(r:=nrows(m);c:=ncols(m);for i in 1..r-1 repeat for j in 1..c-1 repeat if m(i,j)~=m(i+1,j+1)then return false;true)

m has to be a Matrix of some element that allow ~=; ungolf it

f m ==
  r := nrows(m)
  c := ncols(m)
  for i in 1..(r - 1) repeat
    for j in 1..(c - 1) repeat
      if m(i,j)~=m(i + 1,j + 1)     then return(false)
  true

RosLuP

Posted 2017-05-18T05:45:09.720

Reputation: 3 036

1

Retina, 148 bytes

m(1`\d+
$*#
1`#\n\d+\n
@
+`(#*)#@([^#\n]*(#*)\n)(.*)$
$1# $2$1@$4 #$3
@

+`##
# #
+(+s`^(\d+)\b(.*)^\1\b
$1$2#
s`.*^\d.*^\d.*
-1
)%`^[^- ]+ ?

\s+
1

Try it online!

An N×M input matrix

6 7 8 9 2 0
4 6 7 8 9 2
1 4 6 7 8 9
0 1 4 6 7 8

is first converted to an N×(N+M-1) matrix by aligning the diagonals this way:

# # # 6 7 8 9 2 0
# # 4 6 7 8 9 2 #
# 1 4 6 7 8 9 # #
0 1 4 6 7 8 # # #

and then the first column is repeatedly checked to contain a single unique number, and removed if this is so. The matrix is Toeplitz iff the output is blank.

eush77

Posted 2017-05-18T05:45:09.720

Reputation: 1 280

Oh, it doesn't work with negative numbers, gotta fix this :) – eush77 – 2017-05-19T01:29:05.710

1

MATL, 11 bytes

T&Xd"@Xz&=v

Try it online!

The straightforward "construct a Toeplitz matrix and check against it" method, that the top few answers use, somehow felt boring to me (and it looks like that would be 1 byte longer anyway). So I went for the "check each diagonal only contains one unique value" method.

T&Xd - Extract the diagonals of the input and create a new matrix with them as columns (padding with zeros as needed)

" - iterate through the columns of that

@Xz - push the iteration variable (the current column), and remove (padding) zeros from it

&= - broadcast equality check - this creates a matrix with all 1s (truthy) if all the remaining values are equal to one another, otherwise the matrix contains some 0s which is falsy

v - concatenate result values together, to create one final result vector which is either truthy (all 1s) or falsey (some 0s)

sundar - Reinstate Monica

Posted 2017-05-18T05:45:09.720

Reputation: 5 296

0

R, 48 bytes

pryr::f(all(x[-1,-1]==x[-nrow(x),-ncol(x)])*2-1)

Try it online!

Nitrodon

Posted 2017-05-18T05:45:09.720

Reputation: 9 181

0

Clojure, 94 bytes

#(if(=(+ %2 %3 -1)(count(set(for[Z[zipmap][i r](Z(range)%)[j v](Z(range)r)][(- i j)v]))))1 -1)

NikoNyrh

Posted 2017-05-18T05:45:09.720

Reputation: 2 361