44
\$\begingroup\$

A string is considered to be square if the following conditions are met:

  • Each line has the same number of characters
  • The number of characters on each line is equal to the number of lines.

Your task is to write a program or function which determines whether or not a given input string is a square.

You may require input to be delimited by your choice of LF, CR, or CRLF.

The newline character(s) are not considered part of the line's length.

You may require there to be or to not be a trailing newline in input, which doesn't count as an additional line.

Input is a string or 1D char array; it is not a list of strings.

You may assume input is non-empty and only contains printable ASCII, including spaces.

You must output a truthy value for square strings and a falsy one for other strings.

Truthy test cases:

foo
bar
baz
.
.s.
.ss
.s.
(s represents space)
ss
ss
(s represents space)
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa

Falsy test cases:

..
.
.


.
....


....
4444
333
22
333
333
abc.def.ghi

Note extra blank lines in some of the falsy cases.

This is - fewest bytes wins!

\$\endgroup\$
  • \$\begingroup\$ Possible duplicate of Language Design: 2-D Pattern Matching. Problem #5 is the same as this question. \$\endgroup\$ – mbomb007 Jun 6 '17 at 21:40
  • 1
    \$\begingroup\$ @mbomb007 I feel like the different winning criteria make this not a duplicate? "Golfiness" was one of the voting criteria but I don't think answers to that question will largely reflect on the ones here. \$\endgroup\$ – FryAmTheEggman Jun 6 '17 at 22:12
  • 2
    \$\begingroup\$ @mbomb007 I'm voting to leave this question open because, while it is a subset of the other question, the other question is restricted to languages created specifically for that question. \$\endgroup\$ – ETHproductions Jun 6 '17 at 22:15
  • 2
    \$\begingroup\$ @mbomb007: That's not a duplicate, because that question asks you to design a language for the purpose of answering the question, rather than answering in an existing language. Very few of the answers here would be legal there. \$\endgroup\$ – user62131 Jun 6 '17 at 22:29
  • 1
    \$\begingroup\$ @mbomb007: That's no reason to close this challenge, and give people nowhere to post their answers in pre-existing languages, though. It might potentially be an argument for closing the other challenge (because it's just a more restrictive version of this one), although I'd consider it a poor argument and believe both should be left open. \$\endgroup\$ – user62131 Jun 7 '17 at 17:47

48 Answers 48

1
\$\begingroup\$

Dart - 54 chars

q(s)=>!(s=s.split('\n')).any((x)=>x.length!=s.length);

(Expects input separated by newlines and not terminated by one)

Try it online

\$\endgroup\$
1
\$\begingroup\$

C#, 73 bytes

using System.Linq;s=>s.Split('\n').All(l=>l.Length==s.Split('\n').Length)

Explanation:

using System.Linq;    //Import Linq
s=>                   //Take input
s.Split('\n')         //Split the input stirng by line feeds
.All(l=>              //Make sure All lines in the array return true for:
l.Length              //The length of the line
==                    //Equaling
s.Split('\n').Length) //The length of the array split again by line feeds
\$\endgroup\$
1
\$\begingroup\$

Perl 5, 31 bytes

29 bytes of code + -p0 flags.

/.*/;$_=/^(.{@{+}}
){@{+}}\z/

Try it online!

Explanations:
/.*/ matches the first line, and thus makes @+ contain the length of the first line. Then the regex checks whether the string contains @+ lines of length @+.

\$\endgroup\$
1
\$\begingroup\$

MacOS Bash, 34

rs -EH|awk '{print $1}'|uniq|wc -l

rs is part of the default MacOS image. This will also work on Linux if rs is installed; it is on TIO.

  • rs -EH lists the length of each line, along with the number of lines
  • awk strips out extraneous info
  • uniq outputs one line if the line lengths and number of lines are all the same, but more otherwise
  • wc -l outputs 1 if the input is square or a greater number otherwise.

Try it online: Truthy, Falsey.

\$\endgroup\$
1
\$\begingroup\$

AWK, 49 bytes

{s=length($0)}L{x+=L!=s}{L=s}END{print x?0:L==NR}

Try it online!

Could also have used a BEGIN block to set FS="" but that would be the same byte-count. For some reason using the -F"" argument never seems to work.

\$\endgroup\$
1
\$\begingroup\$

Clojure, 42 chars

#(every?(fn[x](=(count %)x))(map count %))
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 20 bytes

A⁺№θ¶¹αF⪪θ¶A×α⁼αLιαα

Try it online! Prints - repeated by the side length as truthy, nothing as falsy.

\$\endgroup\$
1
\$\begingroup\$

><>, 76 bytes

This should work, next step is trying to golf it more!

0v      0   <
 >i:0)?!va=?^1+
:0)?v1n;\~l:   >
    >r:@=?!vr1-^
        ;n0<

Try it online! Or more more fun, try some examples using this animated interpreter.

printf "aaa\naas\naaa" | fish _square.fish --tick 0.1 --play

Explanation

The idea is roughly as follows.

  1. Fill the stack with the number of characters on each line.
  2. Push the length of the stack, corresponding to the number of lines (n).
  3. Do n times:
    • Check if bottom two elements are equal.
    • Remove deepest element.

Examples

For

aaa
aaa
aaa

we get [3, 3, 3, 3] after the first two steps and we can see that all three length 2 subsequences are equal. However, for

aaa
aa
a

we get [3, 2, 1, 3] and not all sequences are equal. For the last falsy case

`abc.def.ghi`

we get [11, 1] so there is only subpair we can check, but it is unequal so we return falsy.

\$\endgroup\$
1
\$\begingroup\$

Add++, 45 bytes

D,g,@,bU10C€=sVcG1+V10CAtbU€bLB]db=$bM*G=

Try it online!

How it works

Boy this was a long one (not even counting the footer)

D,g,@,		; Declare a monadic function 'g'
		; Example argument:    		 ['foo\nbar\nbaz']
	bU	; Unpack;		 STACK = ['f' 'o' 'o' '\n' 'b' 'a' 'r' '\n' 'b' 'a' 'z']
	10C€=s	; Count newlines;	 STACK = ['f' 'o' 'o' '\n' 'b' 'a' 'r' '\n' 'b' 'a' 'z' 2]
	VcG	; Keep last value;	 STACK = [2]
	1+V	; Increment and save;	 STACK = []			; STORE = 3
	10CAt	; Split arg on newlines; STACK = [['foo' 'bar' 'baz']]
	bU€bLB]	; Length of €ach;	 STACK = [[3 3 3]]
	db=	; Are they all equal?	 STACK = [[3 3 3] 1]
	$bM	; Max value;		 STACK = [1 3]
	*	; Logical AND;		 STACK = [3]
	G=	; Equals STORE?		 STACK = [1]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PHP, 65 bytes

while(~$c=$argv[1][$p++])$w+=":"^$c||$w=!$$w+=!!++$h;echo$$h==$h;

expects linux style line endings (\n) and a trailing newline; prints 1 for truthy, nothing for falsy.
Run with php -nr '<code>' '<input>' or try it online.


Btw: The naive approach takes 82 bytes:

<?=count($a=explode("
",$argv[1]))==min($m=array_map(strlen,$a))&min($m)==max($m);

expects linebreaks as on compile system and no trailing newline; prints 1 or 0.
Run with php -nR '<code>' '<input>'.

\$\endgroup\$
1
\$\begingroup\$

Python 3, 79 bytes

lambda a:len(set([len(list(i))for i in a.split('\n')]+[len(a.split('\n'))]))==1
\$\endgroup\$
1
\$\begingroup\$

Stax, 9 bytes

éΘ┌«■/ÉW(

Run and debug online!

Turns out that due to way pairwise difference is calculated, I don't need to worry about the equivalence of k and x-k here. Saving 5 bytes.

Uses the unpacked version to explain.

Lc{%mc%+:u
L             Collect rows in a list
 c{%m         List of length of each row
     c%+      Append number of rows to the list
        :u    All elements in the list are equal
\$\endgroup\$
1
\$\begingroup\$

Swift 3, 134 bytes

import Foundation;func r(s:String)->Bool{let i=s.components(separatedBy:"\n");return i.filter{$0.characters.count != i.count}.isEmpty}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 48 bytes

($a=$args-split'
'|%{$_.Length}).Count-eq($a|gu)

Test script:

$f = {

($a=$args-split'
'|%{$_.Length}).Count-eq($a|gu)

}

@(

,($true,@"
foo
bar
baz
"@)

,($true,@"
.
"@)

,($true,@"
. .
.  
. .
"@)

,($true,@"


"@)

,($true,@"
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
"@)

,($false,@"
..
.
"@)

,($false,@"
.

"@)

,($false,@"

.
"@)

,($false,@"
....


....
"@)

,($false,@"
4444
333
22
"@)

,($false,@"
333
333
"@)

,($false,@"
abc.def.ghi
"@)

) | % {
    $expected,$s = $_
    $result = &$f $s
    "$($result-eq$expected): $result"
}

Output:

True: True
True: True
True: True
True: True
True: True
True: False
True: False
True: False
True: False
True: False
True: False
True: False

Explanation:

  • $args-split"``n"|%{$_.Length} creates an array of length of each line.
  • $a.Count counts elements of the array
  • $a|gu apply Get-Unique to the array. The result is one integer element if all lines has same length.
  • $a.Count-eq($a|gu) compares Count of element with result of the Get-Unique. It's true if all lines has same length and this length equals to Count.
\$\endgroup\$
1
\$\begingroup\$

Wren, 76 61 bytes

Fn.new{|a|a.split("\n").all{|x|x.count==a.split("\n").count}}

Try it online!

Old answer

The algorithm is essentially just copied from a 05AB1E answer.

Fn.new{|a|
var b=a.split("\n").map{|i|i.count}
return b.all{|i|i==b.count}
}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Red, 73 bytes

func[s][all collect[foreach b a: split s lf[keep(length? b)= length? a]]]

Try it online!

{abcd efg} represents true multiline string and not a list of strings, hence I need split s lf

\$\endgroup\$
0
\$\begingroup\$

SnakeEx, 50 bytes

This is BMac's solution to the problem for the 2D regex language design challenge.

m:{v<R>1}{h<>1}
v:${c<L>A1}+$
h:${c<R>A1}+$
c:$.+$

Try it online

\$\endgroup\$
0
\$\begingroup\$

J, 12 bytes

(*./=#)#;._2

Input requires trailing LF or CR.

Explanation:

  • ;._2 split into intervals and discard trailing atom
  • # count each group
  • (*./=#) is a fork which returns 0 (false) or 1 (true) if the LCM of the count of each group is equal to the count-of-counts

Tests

(*./=#)#;._2 'abc', LF, 'def', LF, 'ghi', LF   NB. 1 for well-formed input
(*./=#)#;._2 'abc', LF, 'def', LF, 'ghi'       NB. 0 because no trailing LF
\$\endgroup\$
  • \$\begingroup\$ How does it determine what the delimiter is..? And by the way, abc.def.ghi. should be falsy, so while clever, the delimiter trick is actually invalid. \$\endgroup\$ – Pavel Jun 8 '17 at 16:15
  • \$\begingroup\$ @Phoenix A test case to reflect that would be beneficial \$\endgroup\$ – Conor O'Brien Jun 9 '17 at 4:53
  • \$\begingroup\$ @Phoenix My answer used to just say "requires trailing delimiter" but I edited it to specifically call out either LF or CR. abc.def.ghi. would be truthy but abc.def.ghi.LF (trailing LF) would be falsy. \$\endgroup\$ – hoosierEE Jun 9 '17 at 19:28
  • \$\begingroup\$ abc.def.ghi. Is not a square string and should not be accepted. \$\endgroup\$ – Pavel Jun 9 '17 at 21:37
  • 1
    \$\begingroup\$ 15 Bytes for */(=#)#@>@cutLF, which only accepts LF as a delimiter, and does not require a trailing LF: */(=#)#@>@cutLF 'abc', LF, 'def', LF, 'ghi' returns 1 \$\endgroup\$ – Bolce Bussiere Mar 22 '18 at 17:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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