We've all seen the pictures captioned "How many squares are in this image? 98% will not get this right!" Well, here's your chance to laugh at that 98%.

Input

A rectangular block made of only 2 characters. In a general form, this is defined by m lines, each containing n characters.

Example:

0000xxx
00x00xx
00000xx
xxxxx0x

This can be represented as a newline-separated string, an array of strings, or a 2D array of characters. Any other input types should be suggested in the comments.

Output

The output will be an integer representing the total amount of squares represented individually by both characters (in pseudocode, num_squares(char1) + num_squares(char2))

A square is defined as a set of instances of the same character that fully outline a geometric square of side length at least 2. These squares need not be filled by the character that outlines it. The following examples illustrate this concept:

Scoring

Your program will be scored by 2 criteria, in descending order of importance:

Number of characters in your code block that aren't part of a square, as defined above (you should aim to minimize this!) (Note: characters inside of a square are not automatically considered as part of that square) (Note 2: newlines do not count toward this score)

Number of bytes (you should aim to minimize this!)

The second criterion will act as a tie breaker for the first.

Challenge Rules

For the sake of flexibility, you may choose to use any 2 alphanumeric characters to replace the 0 and x from my examples, as long as they are not the same character.

Each line in the input rectangle must have the same length, and must not contain any character other than the 2 specified for your answer to the challenge (besides the newline character, if applicable)

Trivial squares (1x1 squares denoted by a single character) do not count toward the output. They suck.

Your program does not have to handle empty input, but it should handle cases where no squares are possible (when one of the dimensions of the input rectangle is 1)

You may also choose to specify that you are handling diagonally aligned squares if you relish the challenge. This would be added to the output specified in the challenge specs.

\$\begingroup\$How does the number of squares in your code affect your score (I feel like having squares should reduce your score)? This should also be tagged code-challenge instead of code-golf because the scoring isn't just length.\$\endgroup\$
– FryAmTheEggmanSep 20 '18 at 18:12

\$\begingroup\$Scoring criteria is now primarily based on squares and ties are broken by byte count. Thanks for the feedback!\$\endgroup\$
– TCFPSep 20 '18 at 18:21

1

\$\begingroup\$Does that mean that some very lengthy code with \$N\$ squares beats any shorter code with less than \$N\$ squares?\$\endgroup\$
– ArnauldSep 20 '18 at 19:27

1

\$\begingroup\$Diagonal squares are not counted for scoring. I'd say nonrectangular code is fine, squares remain defined the same as in the specs. The rectangular specification for the input is mostly for simplicity's sake.\$\endgroup\$
– TCFPSep 20 '18 at 20:56

1

\$\begingroup\$Admittedly, I'm not as knowledgeable of esoteric languages like that. It's necessary to have a newline to even count something as a square to begin with, so I don't think it should count toward anyone's score.\$\endgroup\$
– TCFPSep 21 '18 at 13:57

As you can see, every single character is part of a square. The top half of each big square is commented out by line comments, and the bottom half (including the second non-commented line) is escaped by a big here-document beginning in the middle of the square (<<'';#) and ending at the empty line after the big square.

Anyway, by squaring the code like this, it should be possible to get down to score 0 or 2 with any programming language that has a one-line solution and a line comment character, by transforming the one-liner

The only characters not part of a square are the two spaces. Depending on the language, there may also be ways to use clever multiline strings or comments (like Perl's here-docs) or some sort of redundant code to make those two space characters into a square.

As for getting the byte count low, my solution has a bunch of immediate improvements, and I'm sure there are also lots of other ways to refine this technique, but I don't have the patience for that; I just wanted to provide a demonstration so you guys can go wild with it.

Any attempt to reduce score by introducing characters seems to just increase the score more. I guess the way to win this challenge is to find the right Lenguage!

Since Magma posted a very nice Perl solution scoring \$0\$ I decided to attempt similar using my \$20\$ byte solution:

ẆZṡLƊ€ẎṖƇZU$ƬḢ€ẎEƲ€S

But Jelly has no comment character, so a little extra creativity is required...

Jelly programs consist of "Links" - code separated by newline characters, pilcrow characters (¶ - interpreted as the same byte as newlines) or valid code-page characters lacking a defined behaviour (at present q is an example). The latter actually count as a Link each rather than a pure separator. Program execution starts at the bottom-right most Link, the "Main Link" (here ⁽⁽ĿĿ).

We can call any other Link as a single-argument function (a "monad") by it's \$1\$-indexed position in the rest of the Links of the program using the "quick" Ŀ. These Links are indexable in a modular fashion; so if there are \$n\$ of them then the \$n^\text{th}\$ is the same as the \$0^\text{th}\$ and the \$-m^\text{th}\$ is the same as the \$(-m\mod n)^\text{th}\$.

So the program above starts by executing ⁽⁽ĿĿ, where ⁽⁽Ŀ is a representation of \$-27150\$ so ⁽⁽ĿĿ calls the \$-27150^\text{th}\$ Link which, since there are \$60\$ Links (due to the extra lines and the central nine qs), is the \$30 ^\text{th}\$ Link, ẆZṡLƊ€ẎṖƇZU$ƬḢ€ẎEƲ€S, to the left of the middle row of the \$3\$-by-\$3\$ square of qs. This is called with an argument of the program input:

ẆZṡLƊ€ẎṖƇZU$ƬḢ€ẎEƲ€S - Link: list of lists of characters, lines
Ẇ - contiguous slices (i.e [[line1], [line2], ..., [lineN], [line1, line2], [line2, line3], ..., [lineN-1, lineN], [line1, line2, line3], ...., [lineN-2, lineN-1, lineN], ..., ..., lines])
€ - for each (slice):
Ɗ - last three links as a monad:
Z - transpose - i.e. get the columns of the slice
L - length - i.e. get the number of lines in the slice
ṡ - overlapping slices of given length - i.e. get slices of columns of same length as lines in the original slice ...filled squares of all sizes (including 1-by-1)
Ẏ - tighten - from a list of list of squares of each size to a single list of all squares
Ƈ - filter keep if this is truthy:
Ṗ - pop (truthy for all but the 1-by-1 squares)
€ - for each (filled square)
Ʋ - last four links as a monad:
Ƭ - collect up until results are no longer unique:
$ - last two links as a monad:
Z - transpose }
U - upend } - together a quarter rotation
Ḣ€ - head each - i.e. first row of each rotation
Ẏ - tighten - i.e. get the entire perimeter (with repeated corners)
E - all equal? (1 if so, 0 otherwise)
S - sum

\$\begingroup\$I don't think this actually has a score of 0 since ¶ is really just a proxy for a newline. The program really looks more like this\$\endgroup\$
– dylnanSep 29 '18 at 23:46

\$\begingroup\$@dylnan - the OP talks about characters, not bytes - but the 9 ¶s could be replaced with 9 qs or (s or whatever anyway (like I've said in the blurb).\$\endgroup\$
– Jonathan AllanSep 29 '18 at 23:52

\$\begingroup\$...hmm doesn't seem to work with q like I thought it would :/\$\endgroup\$
– Jonathan AllanSep 30 '18 at 0:05

\$\begingroup\$Changing the character changes which line ⁽⁽ĿĿ evaluates\$\endgroup\$
– dylnanSep 30 '18 at 0:07

1

\$\begingroup\$Woah, nice I didn't expect that to happen. <s>Is that because q is an unused byte? It works with u too which is also unused.</s> nevermind\$\endgroup\$
– dylnanSep 30 '18 at 1:38

Your Answer

If this is an answer to a challenge…

…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.

…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.

…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.

More generally…

…Please make sure to answer the question and provide sufficient detail.

…Avoid asking for help, clarification or responding to other answers (use comments instead).