# Shape Identifying Program

Your task is to build a program that identifies the shape of the input. The shapes to be identified can be any of the following:

### Square

To be identified as a square, the source must have lines of all equal length, and the same number of lines as characters per line (newline characters excluded). An optional trailing newline is acceptable.

$_='$_="
"no
t a
squ
are
";#

_=
"So
this
"."".
shape;

$_="or even, this way !! "  ### Mess Anything that doesn't follow a consistent format as per the above, must be identified as a mess. ## Rules • You may return any four consistent printable values to identify each shape. • Your source code must also adhere to one of the above shapes (no, not a mess). • A single trailing newline in your source is acceptable. • You can assume input does not contain any blank lines (including trailing newlines), is not empty, and does not consist only of newlines. • All shapes must have a height and width of >= 2, otherwise this is defined as a mess. • Standard loopholes are forbidden. • The shortest solution in bytes, in each language, wins. • "Your source code must also adhere to one of the above shapes" does it mean one liner is just fine? – tsh Mar 23 '18 at 8:44 • @ tsh All shapes must have a height and width of >= 2. – TFeld Mar 23 '18 at 8:45 • The input can be an array? for example, a square ['abc','cfd','fgh']? – Luis felipe De jesus Munoz Mar 23 '18 at 12:23 • @recursive updated, thank you! – Dom Hastings Mar 23 '18 at 17:02 • You are telling me my source code can't be a mess? why not?!?! – NH. Mar 23 '18 at 23:31 ## 20 Answers # Jelly, 35 bytes L€ṀR,Ṛ$ċƲȧ3
L€,;¥LE€S+Ç
ỴµZL«L>1ȧÇ


Try it online!

0 = Mess
1 = Rectangle
2 = Square
3 = Triangle

• Is the space on your last line used by your code? Or is that just padding to meet the "rectangle" criteria? – BradC Mar 23 '18 at 18:00
• @BradC The latter. I should probably add an explanation. – Erik the Outgolfer Mar 23 '18 at 19:05

# Brachylog, 45 bytes

lᵐ{≥₁|≤₁}o{l>1&t>1&}↰₃
lg,?=∧1w|=∧2w|t⟦₁≡?∧3w


Try it online!

Code is a rectangle (despite the way it renders on my screen). Outputs: 1 for square, 2 for rectangle, 3 for triangle, and nothing for mess

### Explanation:

lᵐ{≥₁|≤₁}o{l>1&t>1&}↰₃
lg,?=∧1w|=∧2w|t⟦₁≡?∧3w

lᵐ                        Get the length of each string
{     }                 Verify
≥₁                     The list is non-increasing
|                    or...
≤₁                  The list is non-decreasing
o                Sort it to be non-decreasing
{        }      Verify
l>1            The number of lines is greater than 1
&           and...
t>1&       The longest line is longer than 1 character
↰₃    Call the following

lg,?                      Join the number of lines with the line lengths
=∧1w                  If they are all equal, print 1 (Square)
|=∧2w            Or if just the line lengths are equal, print 2 (Rectangle)
|t⟦₁         Or if the range [1, 2, ... <longest line length>]
≡?       Is the list of lengths
∧3w    Print 3 (triangle)
Otherwise print nothing (mess)


# Java 10, 231221219217213211 207 bytes

s->{var a=s.split("\n");int r=a.length,l=a[0].length(),R=0,i=1,L,D;if(r>1){for(L=a[1].length(),D=L-l;++
i<r;R=L-a[i-1].length()!=D?1:R)L=a[i].length();R=R<1?D==0?r==l?1:2:D>-2&D<2&(l<2|L<2)?3:0:0;}return R;}


Function is a rectangle itself.
1 = Squares; 2 = Rectangles; 3 = Triangles; 0 = Mess.

-14 bytes thanks to @OlivierGrégoire.

Explanation:

Try it online.

s->{                        // Method with String parameter and integer return-type
var a=s.split("\n");      //  Input split by new-lines
int r=a.length,           //  Amount of lines
l=a[0].length(),      //  Length of the first line
R=0,                  //  Result-integer, initially 0
i=1,                  //  Index integer, starting at 1
L,D;                  //  Temp integers
if(r>1){                  //  If there are at least two lines:
for(L=a[1].length(),    //   Set L to the length of the second line
D=L-l;              //   And set D to the difference between the first two lines
++i<r;              //   Loop over the array
;                   //     After every iteration:
R=L-a[i-1].length()//     If the difference between this and the previous line
!=D?              //     is not equal to the difference of the first two lines:
1                //      Set R to 1
:                 //     Else:
R)               //      Leave R the same
L=a[i].length();      //    Set L to the length of the current line
R=R<1?                    //   If R is still 0:
D==0?                  //    And if D is also 0:
r==l?                 //     And the amount of lines and length of each line is equal
1                    //      It's a square, so set R to 1
:                     //     Else:
2                    //      It's a rectangle, so set R to 2
:D>-2&D<2&             //    Else-if D is either 1 or -1,
(l<2|L<2)?            //    and either l or L is 1:
3                    //     It's a triangle, so set R to 3
:0:0;}                  //   In all other cases it's a mess, so set R to 0
return R;}                //  Return the result R

• Fixed for 221 bytes: s->{var a=s.split("\n");int S=a.length,l=a[0].length(),L,D,b=0,i=1;if(S<2)return 0;for(L=a[1].length(),D=L-l; b<1&++i<S;)if((L=a[i].length())-a[i-1].length()!=D)b=1;return b<1?D==0?S==l?1:2:D==-1|D==1?l==1|L==1?3:0:0:0;} (double space after var, line break after D=L-l;. – Olivier Grégoire Mar 23 '18 at 11:25
• @OlivierGrégoire Thanks. And I golfed two more bytes by changing D==-1|D==1 to D>-2|D<2. That one and the l==1|L==1 might be more golfable with some bitwise operations, but that's not really my expertise. – Kevin Cruijssen Mar 23 '18 at 12:43
• 207 bytes: s->{var a=s.split("\n");int r=a.length,l=a[0].length(),L,D,b=0,i=1;if(r>1){for(L=a[1].length(),D=L-l;++ i<r;b=L-a[i-1].length()!=D?1:b)L=a[i].length();b=b<1?D==0?r==l?1:2:D>-2&D<2&(l<2|L<2)?3:0:0;}return b;} (break after D=L-l;++). Still golfable by merging the loop and the statement afterwards in one, but I don't see how right now. – Olivier Grégoire Mar 23 '18 at 13:02

# Python 2, 129114109107 113 bytes

l=map(len,input().split('\n'));m=len(
l);r=range(1,m+1);print[[1],0,r,r[::-
1],[m]*m,0,[max(l)]*m,l].index(l)%7/2


Try it online!

Prints

• 0 = Mess
• 1 = Triangle
• 2 = Square
• 3 = Rectangle
• @KevinCruijssen Thanks, should be fixed now – TFeld Mar 23 '18 at 12:11

# Jelly, 32 27 bytes

,U⁼€JẸ,E;SÆ²$ZL«L’aL€Ç$æAƝ


Try it online!

Now taking input at a list of lines and switched >1× with ’a and using SÆ² after L€ instead of FLÆ²Ɗ. These allowed me to condense into two lines and I saved 5 bytes in total. The following values are the same as before.

[0.0, 0.0]=Mess
[0.0, 1.5707963267948966]=Rectangle
[0.0, 0.7853981633974483]=Square
[1.5707963267948966, 0.0]=Triangle

ZL«L gets the minimum of height and width and ’ subtracts 1 from it. Ç calls the second link and at the end if the input is a single line the result of Ç gets logical ANDed with the previous number if there is only a single line the output will be [0.0, 0.0].

In the second link: ,U yields a list of line lengths paired with it's reverse. J is range(number of lines) and ⁼€ checks whether each of them are equal to the result of J. Ẹ (Any) yields 1 if the input is a triangle.

E checks if all line lengths are equal (rectangle/square).

SÆ² with a $ to group them into a single monad checks whether the total number of characters is a square number. So at the end of the second link we have [[a,b],c] where each number is 0 or 1 indicating whether the input is a triangle, rectangular, and has square number of characters respectively. However a square number of elements doesn't imply the input is a square since an messy input like a3. 4  has a square number of elements but isn't a square. This is where æA (arctan2) comes in. 0æA0 == 0æA1 == 0. In other words, if the input has square number of elements but is not a rectangle, then it is not a square. There are certainly more clear ways to do this but what does that matter when we have bytes to think about and we are allowed consistent arbitrary output. Note I was previously using æA/ instead of æAƝ (and a , instead of a ; in the second link) but the former method distinguishes between triangles that have square number of elements and those that don't but they should obviously be counted as the same thing. • I was looking at the numbers thinking, they seem vaguely familiar... – Dom Hastings Mar 23 '18 at 21:21 • @DomHastings Haha. I was having trouble distinguishing squares from square-number-of-element messes and arctan2 was exactly what I needed. – dylnan Mar 23 '18 at 22:29 • Funny that I don't think this would be any shorter if there was no source restriction – dylnan Mar 27 '18 at 17:33 • ... Are you sure this is valid? As newline in Jelly is 0x7F, not 0x0A. – user202729 Apr 2 '18 at 2:16 • @DomHastings Is this valid? (see reason above) – user202729 Apr 2 '18 at 2:16 # Java 10, 274323298 229 bytes First triangle submission. s -> { var a=s. split ("\n"); int i,l= a.length, c,f=a[0]. length(),r= l<2||f<2&a[1 ].length()<2? 0:f==l?7:5;var b=f==1;for(i=1; i<l;){c=a[i++]. length();r&=c!=f? 4:7;r&=(b&c!=f+1)| (!b&c!=f-1)?3:7;f=c ;}return r;}  0 Mess 1 Rectangle 3 Square 4 Triangle Try it online here. Edited multiple times to golf it a bit more. Of course I could save a lot of bytes by turning this into a rectangle as well (281 267 259 200 bytes, see here). The result of the identification is manipulated using bitwise AND, yielding a bitmask as follows: 1 1 1 triangle square rectangle  Ungolfed version: s -> { var lines = s.split("\n"); // split input into individual lines int i, // counter for the for loop numLines = lines.length, // number of lines current, // length of the current line previous = lines[0].length(), // length of the previous line result = numLines < 2 // result of the identification process; if there are less than two lines || previous < 2 & lines[1].length() < 2 // or the first two lines are both shorter than 2 ? 0 : previous == numLines ? 7 : 5; // it's a mess, otherwise it might be a square if the length of the first line matches the number of lines var ascending = previous == 1; // determines whether a triangle is in ascending or descending order for(i = 1; i < numLines; ) { // iterate over all lines current = lines[i++].length(); // store the current line's length result &= current != previous ? 4 : 7; // check if it's not a rectangle or a square result &= (ascending & current != previous+1)|(!ascending & current != previous-1) ? 3 : 7; // if the current line is not one longer (ascending) or shorter (descending) than the previous line, it's not a triangle previous = current; // move to the next line } return result; // return the result }  • Welcome to PPCG! – Steadybox Mar 25 '18 at 0:50 • Hooray for triangles! Thanks! – Dom Hastings Mar 25 '18 at 4:55 • Hi, welcome to PPCG! Great first answer. I tried making my answer a triangle before as well, but it would cost too many bytes in comparison to rectangle, and some key-words were a bit too long in my initial answer as well. :) Great answer though, +1 from me. And I took the liberty to edit your post to add highlighting to the entire post, so the comments in your ungolfed version are easier to read. Enjoy your stay! – Kevin Cruijssen Mar 25 '18 at 10:39 • @KevinCruijssen Thanks for the upvote and edit, it looks much better now. My answer could be shortened by turning it into a rectangle as well, 281 bytes. But where's the fun in that? – O.O.Balance Mar 25 '18 at 12:43 ## Javascript 125 bytes _=>(g=(l=_.split('\n').map(a=>a.length)). length)<3?0:(r=l.reduce((a,b)=>a==b?a:0)) ?r==g?2:1:l.reduce((a,b)=>++a==b?a:0)?3:0 0 = Mess 1 = Rectangle 2 = Square 3 = Triangle  fa=_=>(g=(l=_.split('\n').map(a=>a.length)).length)<3?0:(r=l.reduce((a,b)=>a==b?a:0))?r==g?2:1:l.reduce((a,b)=>++a==b?a:0)?3:0 var square = asd asd asd var rectangle = asd asd asd asd asd asd var triangle = asd asdf asdfg asdfgh var mess = asd dasdasd sd dasasd console.log(fa(square), fa(rectangle), fa(triangle), fa(mess)) • The byte count is 125 (including the newlines) – Herman L Mar 23 '18 at 13:40 • Triangle should go to a 1? not a 3456 – l4m2 Mar 23 '18 at 13:47 • @l4m2 what do you mean? – Luis felipe De jesus Munoz Mar 23 '18 at 13:48 • triangle should always start at 1? – Luis felipe De jesus Munoz Mar 23 '18 at 13:49 • I think what @l4m2 is pointing out is that a triangle must have only one character on its first or last line, otherwise it's a "mess". – Shaggy Mar 23 '18 at 13:58 # Perl 5-p, 83 bytes • Mess: nothing • Square: 0 • Triangle: 1 • Rectangle: 2 ($z)=grep++$$_{"@+"-_*~-.}==.,0,//,-1 }{.<2or_=$$z{$z>0||$.}?$z%2:@F>1&&2x!$z


Try it online!

# PHP, 195 205 bytes

<?$a=$argv[1];$r=substr($a,-2,1)=="\n"?strrev($a):$a;foreach(explode("\n",$r)as$l){$s=strlen($l);$x[$s
]=++$i;$m=$i==$s?T:M;}$z=count($x);echo$i*$z>2?$z==1&&key($x)==$i?S:($z==1&&$i>2?R:($i==$z?$m:M)):M;?>


The upside down triangle adds an expensive 56 bytes to this!

Outputs are S,R,T,M

Saved a few bytes thanks to Dom Hastings.

Try it online!

Fixed a few issues now... Test runs produce this.

$_="$_="
$_"" ;say RESULT:S =============$_=
"no
t a
squ
are
";#

RESULT:R
=============
$_= "So this "."". shape; RESULT:T =============$_="or
even,
this
way
!!
"

RESULT:T
=============
as
smiley
asd
A

RESULT:M
=============
X

RESULT:M
=============
XX

RESULT:M
=============
cccc
a
aa
cccc

RESULT:M
=============

• Omit ?> should just be fine – tsh Mar 23 '18 at 10:02
• This seems to return T for cccc\na\naa\ncccc Try it online! – Dom Hastings Mar 23 '18 at 12:44

# Perl 6, 81 bytes

{.lines>>.chars.&{($_==.[0],3)[2*(2>.max )+($_ Z- .skip).&{.[0].abs+.Set*2+^2}]}}


Try it online!

Returns True for square, False for rectangle, 3 for triangle, Nil for mess.

• Very good, would you mind unpacking it a bit, in particular $_ Z- .skip? – Phil H Mar 24 '18 at 19:03 # Stax, 39 bytes L{%m~;:-c:u{hJchC; |mb1=-C;%a\sI^^P}M0  Run and debug online! Shortest ASCII-only answer so far. 0 - Mess 1 - Rectangle 2 - Square 3 - Triangle ## Explanation The solution makes use of the following fact: If something is explicitly printed in the execution of the program, no implicit output is generated. Otherwise, the top of stack at the end of the execution is implicitly output. L{%m~;:-c:u{hJchC;|mb1=-C;%a\sI^^P}M0 L Collect all lines in an array {%m Convert each line to its length ~; Make a copy of the length array, put it on the input stack for later use :- Difference between consecutive elements. If the original array has only one line, this will be an empty array c:u Are all elements in the array the same? Empty array returns false { }M0 If last test result is true, execute block If the block is not executed, or is cancelled in the middle, implicitly output 0 hJ The first element of the difference array squared (*) chC Cancel if it is not 0 or 1 ;|m1= Shortest line length (**) is 1 - Test whether this is the same as (*) Includes two cases: a. (*) is 1, and (**) is 1, in which case it is a triangle b. (*) is 0, and (**) is not 1, in which case it is a square or a rectangle C Cancel if last test fails ;% Number of lines a\ [Nr. of lines, (*)] I Get the 0-based index of (**) in the array 0-> Square, 1->Triangle -1(not found) -> Rectangle ^^P Add 2 and print  # Haskell, 113107103 101 bytes ((#)=<<k).map k.lines;k=length;1#x=0;l#x|x==[1..l] ||x==[l,l-1..1]=3;l#x=k[1|z<-[l,x!!0],all(==z)x]  Try it online! Returns 0, 1, 2 and 3 for mess, rectangle, square and triangle, respectively. Edit: -2 bytes thanks to Lynn! # 05AB1E, 3529 27 bytes Saved 8 bytes thanks to Magic Octopus Urn DgV€g©ZU¥ÄP®Y QP®ËJCXY‚1›P*  Try it online! 0 = Mess 4 = Triangle 1 = Rectangle 3 = Square • This looks to fail on some messy code: Try it online! – Dom Hastings Mar 23 '18 at 17:33 • @DomHastings: Thanks for catching that. I thought that golf was a bit iffy. Should be okay now. – Emigna Mar 23 '18 at 18:17 • Try it online! - 19 bytes - 1 (Rectangle), 2 (Triangle), 5 (Square) and 0 (Mess) [Using binary numbers]. Possibly not acceptable lol. gs€g©QP®¥ ÄP®1å&®ËJC can add a space char and a C for 21 though. – Magic Octopus Urn Mar 26 '18 at 14:56 • @MagicOctopusUrn: It still needs to check for length/height>=2, but it should still save bytes. Clever trick building the output numbers from binary! – Emigna Mar 26 '18 at 15:33 • @MagicOctopusUrn: I used your delta and binary tricks to save some bytes on my original version. Could probably save a few more rewriting it a bit more. – Emigna Mar 26 '18 at 15:49 # R, 101 bytes "if"(var(z<-nchar(y<-scan(,"",,," ","")))==0,"if"(length(y)==z,1,2 ),"if"(all(abs(diff(z))==1),3,4))  1=Square 2=Rectangle 3=Triangle 4=Random Code cannot deal with 'NEGATIVE ACKNOWLEDGE' (U+0015) or the square in the code above. This byte can be switched to something different if the input requires contains this byte. Try it online! • maybe you could use readLines() instead of scan()? – Giuseppe Mar 25 '18 at 16:54 • @Giuseppe Can't/too noob to get readLines to work – Vlo Mar 26 '18 at 5:50 • Hmm, looks like you have to specify file("stdin") to get it to read from console (rather than the next lines of code). That means it'll probably be less golfy. ah well. – Giuseppe Mar 26 '18 at 10:48 # Snails, 29 bytes ada7A .2,lr ?!(t. rw~)z .+~o~  Output key: • 0 - Mess • 3 - Triangle • 6 - Rectangle • 7 - Square It would be 23 bytes without source layout: zA .2,dun!(t.rf~)z.+~o~  • I've always been keen to play with this language since reading the question that spawned it! – Dom Hastings Mar 27 '18 at 12:04 # Wolfram Language (Mathematica), 119 bytes (x=StringLength/@#~StringSplit~"\n")/.{{1}->3,s~(t=Table)~{ s=Tr[1^x]}:>0,x[[1]]~t~s:>1,(r=Range@s)|Reverse@r:>2,_->3}&  Using Replace /. and pattern matching on the character count by line. Replace will kick out the first RHS of a rule that is matched, so the ordering is to test for the 1 character input, then squares, rectangles, triangles, and a fall-through for messes. square=0,rectangle=1,triangle=2,mess=3 Try it online! • @DomHastings, it's fixed. – Kelly Lowder Mar 23 '18 at 16:49 # Red, 209 bytes func[s][c: copy[]foreach a split s"^/"[append c length? a]d: unique c r: 0 if 1 < l: length? c[if 1 = length? d[r: 2 if(do d)= l[r: 1]]n: 0 v: copy[]loop l[append v n: n + 1]if(v = c)or(v = reverse c)[r: 3]]r]  Try it online! 0 Mess 1 Square 2 Rectangle 3 Triangle # AWK, 119 bytes {p=l;l=L[NR]=length($0)
D=d}{d=p-l;x=x?x:NR>2?\
d!=D:0}END{print x==1?\
3:d*d==1?(L[NR]+L[1]==\
NR+1)?2:3:p!=NR}#######


Try it online!

Output:

0 = Square
1 = Rectangle
2 = Triangle
3 = Mess

# Ruby, 115 111 bytes

->s{m=s.split(?\n).map &:size;r=*1..s=m.size;s<2?4:(m|[
]).size<2?m[0]<2?4:s==m[0]?1:2:r==m.reverse||r==m ?3:4}


Try it online!

Anonymous lambda. Outputs:

1. Square
2. Rectangle
3. Triangle
4. Mess
• This looks to fail on some that should be flagged as mess: Try it online! – Dom Hastings Mar 23 '18 at 17:33
• Ouch, I guess this will have to go as a quick fix. Probably will need to try golfing it a bit more... – Kirill L. Mar 23 '18 at 18:00

# C (gcc), 125 123 bytes

Thanks to ceilingcat for -2 bytes.

f(L,n)int**L;{int i,l,c,F=strlen(*L),s=-F;for(l=i=0;i<n;l=c)c
=strlen(L[i++]),s+=c-l;s=n>1?s||F<2?~abs(s)+n?0:3:n^F?2:1:0;}


Try it online!