# Is there a single straight line in the matrix?

Inspired by Wzl

Determine if a given square binary matrix has exactly one row or column consisting of entirely 1s, and the rest of the matrix is 0s.

For example, these are all true:

0 0 0 0 0 0 0 0 0    0 0 0 0 0    1 0 0 0    0 1
0 0 0 0 0 0 0 0 0    1 1 1 1 1    1 0 0 0    0 1
0 0 0 0 0 0 0 0 0    0 0 0 0 0    1 0 0 0
0 0 0 0 0 0 0 0 0    0 0 0 0 0    1 0 0 0
0 0 0 0 0 0 0 0 0    0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1


And these are all false:

0 0 0 0 0 0 0    0 1 0 0 0    0 1 0 0    0 0 0    0 0 0    0 0 1    0 1
1 1 1 1 1 1 1    1 1 1 1 1    1 1 0 1    1 0 1    0 0 0    1 0 0    0 0
0 0 0 0 0 0 0    0 1 0 0 0    0 1 0 0    0 0 0    0 0 0    0 1 0
1 1 1 1 1 1 1    0 1 0 0 0    0 1 0 0
0 0 0 0 0 0 0    0 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0


The reasons for the false ones:

• More than one row
• More than one row or column
• There are 1s outside the "all 1s column"
• There isn't a row or column of all 1s (describes the last 4)

You should take a square binary matrix of side length $$\n \ge 2\$$, in any reasonable format, and output 2 distinct, consistent values to indicate whether it has a single straight line. This is , so the shortest code in bytes wins.

Keep your golfing in your code, not your inputs/outputs. I'm very liberal with the I/O formats, including but not limited to:

• A multiline string
• A list of lines
• A 2D list (or matrix) consisting of two distinct consistent values (e.g. 0/1, space/'*', 5/'(')
• A flat array, and $$\n\$$, as separate arguments

• Two distinct consistent values (e.g. 1/0) to indicate the output
• Erroring/not erroring
• Two families of values, one of which consists of values that are truthy in your language and the other falsey (for example, natural numbers and zero)

• etc.

As a broad, general rule, so long as the input can be clearly understood and the outputs clearly distinguished, it's fair game.

## Test cases

Input Output
000000000000000000000000000000000000000000000000000000000000000000000000111111111
true
0000011111000000000000000
true
1000100010001000
true
0101
true
0000000111111100000001111111000000000000000000000
false
0100011111010000100001000
false
0100110101000100
false
1000010000100001
false
000101000
false
000000000
false
001100010
false
0100
false
• May we take $n$ along with a non-flat array? Jun 17 '21 at 2:12
• @chunes Yep, that's fine Jun 17 '21 at 2:16
• suggested test case: a matrix with the right amount of ones but not in a line Jun 17 '21 at 11:29
• I really like this kind of problem, where at face value it's very simple, but ends up generating many conceptually different solutions, some involving higher math (matrix algebra in this case). Jun 17 '21 at 12:41
• Nice use of markdown tables for test cases. I should do that
– qwr
Jun 17 '21 at 23:24

# Python 2, 49 bytes

Takes as input a 2D binary matrix $$\ a \$$, and its size $$\ n \$$.

lambda a,n:sorted(map(sum,a+zip(*a)))[-2:]==[1,n]


Try it online!

There may be shorter approaches, but this is what I could find for now. Please let me know if the algorithm is incorrect.

## Explanation

Since there is exactly one line, there should be exactly one row/column which contains $$\ n \$$ ones. Furthermore, since every $$\ 1 \$$ in the matrix exists on that line, there can be no other row/column containing more than one $$\ 1 \$$. Since if there were another $$\ 1 \$$ existing somwhere not on that line, it would create a row/column with at least two $$\ 1 \$$s.

Given this, it suffices to check that the two rows/columns with the largest number of $$\ 1 \$$s have counts of [1, n].

• @DLosc Brilliant idea! I had suspected my solution could be improved upon. Would you like to post a new answer? Jun 17 '21 at 23:24
• All right, done! It's mostly your idea, so I wanted to give you the option of integrating it first. It is exciting to get to post a Python golf--normally my answer is both longer and later than other people's. ;^) Jun 18 '21 at 17:27

# Brachylog, 8 bytes

{z|}≡ᵛ+1


Try it online!

{z|}        Either the rows or the columns
≡ᵛ      are all the same list
+1    which sums to 1.

• An alternate, ASCII-only version (same number of bytes): replace ≡ᵛ with =h. Jun 17 '21 at 22:22

# Ruby, 47 bytes

->m,n{m.uniq[1]?m-[[0]*n]==[[1]*n]:m[0].sum==1}


Try it online!

Split the two cases:

• If m has at least 2 different rows, remove all zeros and check if we are left with a single row consisting of ones.

• If not (all the rows are the same), check that the sum of the first row is one.

# Factor + math.unicode, 59 bytes

[ [ concat Σ = ] keep dup flip [ all-equal? ] bi@ or and ]


Try it online!

Takes $$\n\$$ and a matrix of $$\1\$$s and $$\0\$$s, in that order.

• [ concat Σ = ] keep Is the sum of the matrix equal to $$\n\$$?
• dup flip [ all-equal? ] bi@ or and And are all the rows in either the original matrix or its transposition equal?

# JavaScript (ES6), 46 bytes

Thanks to @PertinentDetail for a bug fix

Expects a multiline string with a trailing line feed. Returns a Boolean value.

s=>/^(0*10*\n)\1*$|^(0+\n)*1+\n[^1]*$/.test(s)


Try it online!

• Unfortunately, this doesn't work if the ones are the first row of the matrix (not one of the test cases). To fix this, replace \2* with [^1]* at the cost of two characters. However, you don't need the grouping in (\1+\n) so you can save two characters to get back to 46. Jun 17 '21 at 21:35
• @PertinentDetail Good catch and nice fix. Thanks! Jun 17 '21 at 21:57

# Jelly, 9 bytes

S;§ṢIṪ‘=L


Try it online!

Slightly modified port of dingledooper's algorithm.

### How it works

S;§ṢIṪ‘=L    Monadic link; input = matrix M
S;§          Column sums of M ++ Row sums of M
Ṣ         Sort
I        Increments; (next - previous) for each adjacent pair
Ṫ       Last item
‘      +1
=L    Equals the length of M?


# Jelly, 9 bytes

ZEȯE×SS=L


Try it online!

Slightly modified port of chunes's algorithm.

### How it works

ZEȯE×SS=L    Monadic link; input = matrix M
ZE           1 if transpose(M) has all rows equal
ȯE           or M has all rows equal, 0 otherwise
×SS      times column sum, and sum again
(= times the sum of the entire matrix)
=L    equals the length of M?


# Wolfram Language (Mathematica), 2113 35 bytes

Norm@#==#2&&Norm@Eigenvectors@#>#2&


Try It Online! (Thanks to @ZaMoC for configuring this.)

Takes # as the matrix, and #2 as the square root of the side length, n. Returns True if the conditions are met, and False otherwise

Explanation

In Mathematica, the Norm function, when applied to a matrix, will perform a singular value decomposition and then identify and return, from among the resulting matrices, the element with the largest value. For most square binary matrices with n ≥ 2, the conditions will be met IFF the Norm of the matrix equals sqrt(n), i.e., if the following returns True:

Norm@#==#2&


However @Nitroden found an exception, which can be generalized as follows: If sqrt(n) is an integer, and the matrix contains a sqrt(n) x sqrt(n) submatrix that is all 1's, and has 0's everywhere else, its Norm will also equal sqrt(n).

Thus, to eliminate those, I added an additional test: that the Norm of the Eignevectors of the matrix is greater than sqrt(n).

My Try It Online! link contains all the OP's test matrices and, at the end, Norden's case plus three additional matrices of that form. These now all return False.

Alas, Mathematica's Eigenvectors function is 12 bytes.

Thanks to @Bubbler for the tip that my If wrapper was unnecessary.

• I think it should be fine to strip the if statement entirely (giving true or false). Jun 17 '21 at 6:29
• I don't have mathematica but it seems like this only counts if there is the right amount of 1s Try it online with Julia! Jun 17 '21 at 11:28
• @MarcMush I tried your test matrix, and it correctly returned False. "norm" seems to means something different in Julia—according to discourse.julialang.org/t/performance-of-norm-function/14709/9, it instead computes the Frobenius norm. In Mathematica, when Norm is applied to a matrix, it does a singular value decomposition, and then selects the element with the maximum value. So, for your matrix m= {{1, 0, 0}, {1, 0, 0}, {0, 1, 0}}, [continued] Jun 17 '21 at 11:56
• here are all test cases: Try it online! Jun 17 '21 at 12:04
• Fails on {{1, 1, 0, 0}, {1, 1, 0 ,0}, {0, 0, 0, 0}, {0, 0, 0, 0}, which has operator norm 2. Jun 17 '21 at 13:55

:∑$v∑Js¯Nt›=  Try it Online! Yay! Beating Lyxal by 1 byte with a different approach!!! -1 byte from @Lyxal himself thanks • You can remove ⁰ for -1 (because the input hasn't cycled back to the input list) Jun 17 '21 at 4:17 • Good job! You beat the creator of the language. – user100690 Jun 17 '21 at 5:15 # 05AB1E, 8 bytes Based on the first part of Bubblers Jelly answer, which uses dingledooper's algorithm. Input is a 2d matrix and the side length, output is 1 for truthy inputs and any other integer for falsy ones. This is the definition of truthiness in 05AB1E. Dø«O{¥θα  D # push two copies of the input matrix ø # transpose one copy to get a list of columns « # concatenate to the list of rows O # sum each sublist { # sort the row and column sums ¥ # take consecutive differences θ # get the last one (largest value - second largest value) α # absolute difference with the second input  # Jelly, 10 bytes S;§>Ƈ1⁼LW$


Try it online!

Uses Unrelated string's test suite.

Fixed with some help from Unrelated string.

## Explanation

S;§>Ƈ1⁼LW$S sums of columns ; concat with § sums of rows Ƈ keep the sums which are: > 1 greater than 1 ⁼LW$  = [length] ?


# Jelly, 9 bytes

ŒṪZEƇȧiɗJ


Try it online!

The fourth totally different Jelly 9 byter. Returns either 1 or 2 for truthy and either an empty list or the number 0 for falsy. Also the program structure is more convoluted.

### How it works

ŒṪZEƇȧiɗJ    Monadic link. Input: the matrix M of size n
ŒṪZ          Take the transpose of multi-dimensional indices of 1
the result is a 2-row matrix X;
in order to satisfy the condition, one of the rows must be
all-equal, and the other must be identical to 1..n
....ɗJ    A dyad with ^ as left arg and 1..n as right:
EƇ          Collect every row that is all-equal from X
ȧ         Chain onto Python's and...
i        Get 1-based index of 1..n in X, 0 if not found


# J, 25 bytes

(1:0}0"0)e.],&(#\|."{])|:


Try it online!

Not the shortest (my previous translation of dingledooper's was a couple bytes shorter), but I wanted to come up with a different approach:

• (1:0}0"0) Is the matrix with all ones in the first row and zeros elsewhere...
• e. an elment of...
• ],&(#\|."{])|: All possible rotations of the input, and all possible rotations of its transpose, catted together?
• Fails with inputs like 1101 0010 0000 0000. Jun 17 '21 at 4:35
• Ugh, nice catch. Jun 17 '21 at 4:35
• @Bubbler Fixed. I really wanted to find a solution with using diagonal /. sums, which produce a string of # ones and zero elsewhere iff valid input. But golfing that condition was cumbersome. Maybe you can make it work. Jun 17 '21 at 5:00
• Why do you need to square element wise? The matrix always has 0 or 1 in it, and squaring either of those (or any product involving those) does nothing Jun 17 '21 at 13:56
• Fails with 1100 1100 0000 0000 – which suggests that it is the same algorithm as theorist's answer, that also fails with this case. :-)
– xash
Jun 17 '21 at 15:16

# Jelly, 9 bytes

,ZfJṁ=ⱮJƲ


Try it online!

Idea stolen from Razetime in TNB

,            Pair the input with
Z           its transpose.
f          Filter the pair to elements contained in
Jṁ=ⱮJƲ    every matrix of the same dimensions with a single column of 1s.

Jṁ        Mold [1 .. len(input)] to the shape of the input.
ⱮJ     For each 1 .. len(input),
=       is each element equal to it?


# Wolfram Language (Mathematica), 25 bytes

#||#/.{a_..}:>Tr@a==1&


Try it online!

Returns True if the matrix has a single line, and nonTrue otherwise.

#||#                   input OR its tranpose
/.{a_..}:>         replace lists of repeated elements with
Tr@a==1      (is the sum of that element equal to 1?)


Then, any Or expression with True as an argument gets reduced to True.

• Can you add an explanation? I'm starting to learn Wolfram. Jun 17 '21 at 5:38

# Python 2, 43 bytes

Heavily based on dingledooper's answer, which you should upvote.

lambda a,n:set(map(sum,a+zip(*a)))=={0,1,n}


Try it online!

Or:

### Python 3, 44 bytes:

lambda a,n:{*map(sum,a+[*zip(*a)])}=={0,1,n}


Saves bytes with set unpacking, but loses bytes because zip doesn't return a list. Try it online!

### Explanation

In a truthy input, the sum of a row or column must be one of these three numbers:

• $$\0\$$, if it is parallel to the line of $$\1\$$s
• $$\1\$$, if it is perpendicular to the line of $$\1\$$s
• $$\n\$$, if it is the line of $$\1\$$s

Any number other than these three indicates the existence of multiple lines or a partial line.

Furthermore, all three of these numbers must be represented among the list of sums:

• If $$\n\$$ is missing, there is no row or column that contains all $$\1\$$s.
• If $$\1\$$ is missing, there are multiple rows and columns containing $$\1\$$s.
• If $$\0\$$ is missing, the input has two perpendicular lines of $$\1\$$s (as in the second falsey test case). Conveniently, we don't have to worry about the case of a $$\1 \times 1\$$ matrix, because we're given that $$\n \geq 2\$$.

Therefore:

set(                  )           # The set of
map(sum,         )            # the sums of each
a+                    # row and
zip(*a)             # column
==         # must be exactly
{0,1,n}  # that set


# Retina 0.8.2, 32 bytes

^(0*10*)(¶\1)*$|^(0+¶)*1+(¶0+)*$


Try it online! Turns out to be much like @Arnauld's answer, except I wanted to solve it for no trailing newline instead.

# Julia, 37 bytes

x$n=(l=sum([x x'],dims=1))[l.>1]==[n]  Try it online! # Vyxal, 14 bytes :ÞTJv∑s2Nȯ1?"⁼  Try it Online! Another stealing of the python answer. ## Explained :ÞTJv∑s2Nȯ1?"⁼ :ÞTJ # merge the input list with itself transposed. v∑s # sort the list that results from getting the sum of each item 2Nȯ # take the last two items of that list 1?"⁼ # and check for equality with the list [1, second_input]  # T-SQL, 152 bytes Input is a table variable Returns 1 for true, 0 for false To save bytes, this can only handle matrix up to length 10 SELECT top 1iif(x=replace(a,0,'')or sum(x)over()=x*2-1and a not like'%0%'and 0=min(a)over(),1,0)FROM(SELECT rank()over(order by a)x,*FROM @)c ORDER BY-x  Try it online # tinylisp, 88 bytes (load library (d _(q((M)(e 1(*(sum(map all M))(sum(map any M (q((M)(+(_ M)(_(transpose M  The solution is the anonymous function in the last line. Try it online! Here's an ungolfed version that verifies all test cases: Try it online! ### Explanation Define a helper function _ that takes a matrix (list of lists) M:  (sum(map all M)) Number of rows that are all 1s (sum(map any M)) Number of rows that have any 1s (* ) Multiply those two numbers (e 1 ) Is the product equal to 1?  In other words, is there exactly one row that has all 1s, which is also the only row that has any 1s? Then our main function needs only apply _ to the matrix and its transpose, and return truthy if either result is truthy:  (_ M) Test M (_(transpose M)) Test transpose(M) (+ ) Add the two results  # Charcoal, 27 bytes ＷＳ⊞υι∨∧⁼⌊υ⌈υ⁼¹Σ⌈υ⁼ΦυΣι⟦⭆⌈υ¹  Try it online! Link is to verbose version of code. Takes input as a newline-terminated list of strings. Explanation: ＷＳ⊞υι  Input the matrix.  ⁼⌊υ⌈υ All rows are identical ∧ Logical And Σ⌈υ The sum of a row ⁼¹ Equals literal 1 ∨ Logical Or υ Input array Φ Filtered where ι Current row Σ Is non-zero ⁼ Equals ⭆⌈υ¹ Row of 1s ⟦ As a 1-row 2D array  # APL (Dyalog Unicode), 63 55 bytes {(F⍉⍵)+(F←{(1↑⍴⍵)=(+/,⍵)×+/∧/⍵})⍵}  Try it online! • changed approach • F used on input + input transposed ×+/∧/⍵ ⍝ number of all 1s lines multiplied by (+/,⍵) ⍝ total 1s (1↑⍴⍵)= ⍝ equal to side length?  # PowerShell, 4945 46 bytes inspired by Arnauld's and Neil's answers. +1 bytes with additional Test cases. "$args "-match'^(0*10* )\1+$|^(0+ )*1+ [0 ]*$'


Try it online!

• convert the arguments to a string with space char as separator
• add the trail space char
• match with regexp

# GNU-APL, 34 bytes

{+/(⍺≡+/,⍵)∧(⍵∧.=⍺⍴1)∨((⍺⍴1)∧.=⍵)}


Input the size of the matrix, and the matrix itself.

⍵∧.=⍺⍴1    finds the row with all ones, a1=1∧a2=1∧a3=1 ...
(⍺⍴1)∧.=⍵  finds the column with all ones
The disjunction of the above two ensures atleast one of them happends
⍺≡+/,⍵     ensures that only required numbers of ones are present


# C (gcc), 121 bytes

l;e;r;o;a;f(m,n)int*m;{r=l=o=0;a=~0;for(e=1;r++<n;o|=*m,a&=*m++)~*m<<32-n?e&=!*m:++l;for(o-=a;a;a/=2)l+=a&1;r=l<2&&e^!o;}


This has entire rows stored in integer arrays, making the maximum matrix size 32.

Try it online!