34
\$\begingroup\$

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
000000000
000000000
000000000
000000000
000000000
000000000
000000000
000000000
111111111
true
00000
11111
00000
00000
00000
true
1000
1000
1000
1000
true
01
01
true
0000000
1111111
0000000
1111111
0000000
0000000
0000000
false
01000
11111
01000
01000
01000
false
0100
1101
0100
0100
false
1000
0100
0010
0001
false
000
101
000
false
000
000
000
false
001
100
010
false
01
00
false
asked Jun 17, 2021 at 1:38
\$\endgroup\$
6
  • 1
    \$\begingroup\$ May we take \$n\$ along with a non-flat array? \$\endgroup\$ Commented Jun 17, 2021 at 2:12
  • 2
    \$\begingroup\$ @chunes Yep, that's fine \$\endgroup\$ Commented Jun 17, 2021 at 2:16
  • 1
    \$\begingroup\$ suggested test case: a matrix with the right amount of ones but not in a line \$\endgroup\$ Commented Jun 17, 2021 at 11:29
  • 3
    \$\begingroup\$ 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). \$\endgroup\$ Commented Jun 17, 2021 at 12:41
  • 2
    \$\begingroup\$ Nice use of markdown tables for test cases. I should do that \$\endgroup\$ Commented Jun 17, 2021 at 23:24

26 Answers 26

29
\$\begingroup\$

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].

answered Jun 17, 2021 at 2:14
\$\endgroup\$
2
  • \$\begingroup\$ @DLosc Brilliant idea! I had suspected my solution could be improved upon. Would you like to post a new answer? \$\endgroup\$ Commented Jun 17, 2021 at 23:24
  • \$\begingroup\$ 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. ;^) \$\endgroup\$ Commented Jun 18, 2021 at 17:27
15
\$\begingroup\$

Brachylog, 8 bytes

{z|}≡v+1

Try it online!

{z|} Either the rows or the columns
 ≡v are all the same list
 +1 which sums to 1.
answered Jun 17, 2021 at 5:31
\$\endgroup\$
1
  • 2
    \$\begingroup\$ An alternate, ASCII-only version (same number of bytes): replace ≡v with =h. \$\endgroup\$ Commented Jun 17, 2021 at 22:22
11
\$\begingroup\$

Ruby, 47 bytes

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

Try it online!

Explain please:

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.

answered Jun 17, 2021 at 6:16
\$\endgroup\$
10
\$\begingroup\$

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?
answered Jun 17, 2021 at 3:39
\$\endgroup\$
10
\$\begingroup\$

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!

answered Jun 17, 2021 at 7:11
\$\endgroup\$
2
  • 3
    \$\begingroup\$ 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. \$\endgroup\$ Commented Jun 17, 2021 at 21:35
  • \$\begingroup\$ @PertinentDetail Good catch and nice fix. Thanks! \$\endgroup\$ Commented Jun 17, 2021 at 21:57
8
\$\begingroup\$

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

×ばつSS=L

Try it online!

Slightly modified port of chunes's algorithm.

How it works

×ばつ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?
answered Jun 17, 2021 at 3:45
\$\endgroup\$
8
\$\begingroup\$

Wolfram Language (Mathematica), (削除) 21 (削除ここまで) (削除) 13 (削除ここまで) 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.

answered Jun 17, 2021 at 5:40
\$\endgroup\$
10
  • 3
    \$\begingroup\$ I think it should be fine to strip the if statement entirely (giving true or false). \$\endgroup\$ Commented Jun 17, 2021 at 6:29
  • \$\begingroup\$ 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! \$\endgroup\$ Commented Jun 17, 2021 at 11:28
  • \$\begingroup\$ @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] \$\endgroup\$ Commented Jun 17, 2021 at 11:56
  • 1
    \$\begingroup\$ here are all test cases: Try it online! \$\endgroup\$ Commented Jun 17, 2021 at 12:04
  • 5
    \$\begingroup\$ Fails on {{1, 1, 0, 0}, {1, 1, 0 ,0}, {0, 0, 0, 0}, {0, 0, 0, 0}, which has operator norm 2. \$\endgroup\$ Commented Jun 17, 2021 at 13:55
7
\$\begingroup\$

Vyxal, 12 bytes

:∑$v∑Js ̄Nt›=

Try it Online!

Yay! Beating Lyxal by 1 byte with a different approach!!!

-1 byte from @Lyxal himself thanks

answered Jun 17, 2021 at 4:11
\$\endgroup\$
2
  • 2
    \$\begingroup\$ You can remove 0 for -1 (because the input hasn't cycled back to the input list) \$\endgroup\$ Commented Jun 17, 2021 at 4:17
  • 2
    \$\begingroup\$ Good job! You beat the creator of the language. \$\endgroup\$ Commented Jun 17, 2021 at 5:15
7
\$\begingroup\$

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{\θα

Try it online! or Try all cases!

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
answered Jun 17, 2021 at 11:41
\$\endgroup\$
0
6
\$\begingroup\$

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] ?
answered Jun 17, 2021 at 2:19
\$\endgroup\$
0
6
\$\begingroup\$

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
answered Jun 17, 2021 at 6:18
\$\endgroup\$
6
\$\begingroup\$

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?
answered Jun 17, 2021 at 2:52
\$\endgroup\$
7
  • \$\begingroup\$ Fails with inputs like 1101 0010 0000 0000. \$\endgroup\$ Commented Jun 17, 2021 at 4:35
  • \$\begingroup\$ Ugh, nice catch. \$\endgroup\$ Commented Jun 17, 2021 at 4:35
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Jun 17, 2021 at 5:00
  • \$\begingroup\$ 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 \$\endgroup\$ Commented Jun 17, 2021 at 13:56
  • 2
    \$\begingroup\$ Fails with 1100 1100 0000 0000 – which suggests that it is the same algorithm as theorist's answer, that also fails with this case. :-) \$\endgroup\$ Commented Jun 17, 2021 at 15:16
5
\$\begingroup\$

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?
answered Jun 17, 2021 at 4:04
\$\endgroup\$
5
\$\begingroup\$

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.

answered Jun 17, 2021 at 4:36
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Can you add an explanation? I'm starting to learn Wolfram. \$\endgroup\$ Commented Jun 17, 2021 at 5:38
4
\$\begingroup\$

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
answered Jun 18, 2021 at 17:23
\$\endgroup\$
3
\$\begingroup\$

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.

answered Jun 17, 2021 at 10:30
\$\endgroup\$
3
\$\begingroup\$

Julia, 37 bytes

x$n=(l=sum([x x'],dims=1))[l.>1]==[n]

Try it online!

uses Razetime's approach

answered Jun 17, 2021 at 11:51
\$\endgroup\$
2
\$\begingroup\$

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] 
answered Jun 17, 2021 at 3:31
\$\endgroup\$
2
\$\begingroup\$

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

answered Jun 17, 2021 at 14:47
\$\endgroup\$
2
\$\begingroup\$

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
answered Jun 18, 2021 at 19:13
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 27 bytes

WS⊞υι∨∧=⌊υ⌈υ=1Σ⌈υ=ΦυΣι⟦⭆⌈υ1

Try it online! Link is to verbose version of code. Takes input as a newline-terminated list of strings. Explanation:

WS⊞υι

Input the matrix.

 =⌊υ⌈υ All rows are identical
 ∧ Logical And
 Σ⌈υ The sum of a row
 =1 Equals literal `1`
∨ Logical Or
 υ Input array
 Φ Filtered where
 ι Current row
 Σ Is non-zero
 = Equals
 ⭆⌈υ1 Row of 1s
 ⟦ As a 1-row 2D array
answered Jun 17, 2021 at 12:41
\$\endgroup\$
1
\$\begingroup\$

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?
answered Jun 18, 2021 at 10:09
\$\endgroup\$
1
\$\begingroup\$

PowerShell, (削除) 49 (削除ここまで) (削除) 45 (削除ここまで) 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
answered Jun 19, 2021 at 13:37
\$\endgroup\$
1
\$\begingroup\$

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 
answered Jun 19, 2021 at 14:58
\$\endgroup\$
1
\$\begingroup\$

C (gcc), (削除) 121 (削除ここまで) 119 bytes

-2 bytes thanks to ceilingcat

l;e;r;o;a;f(m,n)int*m;{r=l=o=0;for(e=a=~0;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!

answered Jun 21, 2021 at 20:06
\$\endgroup\$
0
1
\$\begingroup\$

jq, 38 bytes

Reads a 2D array, outputs a boolean.

(.+transpose|map(add)-[0,1])==[length]

Try it online!

answered Oct 25, 2022 at 6:01
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.