Find longest consecutive characters in 2D array

Challenge

Given a 2D array, find the length and direction of all the longest consecutive characters.

• If there are ties, output every possible winning combination in any order, (winners can overlap with other winners)
• Zero "0" is a special padding character which cannot be a winner.
• Code golf rules apply, shortest code wins.

Output: n,m,d

(Where n is the identified character of length m in d direction)

Valid characters for d: /|\-. See below examples to interpret meaning.

Input: The 2D array input should be in either of the following format, (your preference):

Option 1:

123
456
789


Option 2*:

[["123"],["456"],["789"]]


*or any combination of "{[()]}" characters can be used, with whitespace characters ignored outside of quotes. Quotes can be single or double. The array must read left-to-right, top-to-bottom.

Assumptions

• The shape of the array will always be rectangular or square

• There will always be at least one non-zero character

• Array characters will only be alphanumeric

Examples

1.

0000000
0111100
0000000


1,4,-

2.

00000000
aaaa0000
00bbbbb0


b,5,-

3.

0y00x000
aayxaaaz
00xy000z
0x00y00z
x0000y0z


x,5,/

y,5,\

*(in any order)

4.

1111
1111
1111


1,4,-

1,4,-

1,4,-

5.

ccc
cwc
ccc


c,3,-

c,3,-

c,3,|

c,3,|

*(in any order)

6.

9


9,1,.

7.

ab
cd


a,1,.

b,1,.

c,1,.

d,1,.

*(in any order)

• Sorry, I don't quite understand the .. What's the expected result of a 2x2 square of 3 1s and a 0?
– Neil
Jun 9, 2019 at 11:39
• @Neil The dot just means it doesn't have a direction because the longest string of characters, is of length one. A 2x2 matrix of 3 1s and a 0, would be: "1,2,| and 1,2,-" Jun 9, 2019 at 12:29
• Are we restricted to those 4 characters for d or can we use any 4 characters of our choosing? Jun 9, 2019 at 13:18
• Why restrict the input format to a string, instead of just saying it is a 2D array and letting the site defaults take care of it?
– Jo King
Jun 9, 2019 at 14:41
• Suggested test case: ab\ncd\nea → [[a,1,.],[b,1,.],[c,1,.],[d,1,.],[e,1,.],[a,1,.]] (contains two [a,1,.], which is a pretty annoying edge case). Jun 11, 2019 at 9:49

Jelly, 52 54 bytes

,UŒD€;,Z$ṣ€€”0ŒrẎ€⁺;€"“\/-|”Ẏ2ị$ÐṀ¹F}ḟ”0;€1,”.ʋØ½œị’Ɗ?


Try it online!

A monadic link that takes a list of strings and returns. list of maximal outputs each in the order n, m, d. A third of the code is to deal with the requirement for dots (last example). Now handles Kevin Cruijssen’s edge case correctly.

• Fails for edge-case ["ab","cd","ea"]. It only outputs a single ['a', 1, '.'] triplet instead of two. Nice answer regardless, so +1 from me. Jun 11, 2019 at 9:50
• @KevinCruijssen I had thought about that, though wasn’t entirely clear what the desired output was. Should be fixable. Jun 11, 2019 at 10:23
• @KevinCruijssen Fixed. Jun 11, 2019 at 12:41
• Nice, and a lot shorter than I thought. :) Just 2 bytes. Jun 11, 2019 at 12:41

Charcoal, 110 bytes

≔⪫Ａ⸿θＰθＦθ«≔⟦⟧ηＦ∧¬№0⸿ι⟦→↘↓↙⟧«≔ＫＤＬθ✳κζＷ›Ｌζ№ζι≔⊟ζε⊞η⟦κιＬζ⟧»¿⁼¹⌈Ｅη§κ²⊞υ⊟ηＦη⊞υκι»⎚≔⌈Ｅυ§ι²εＦΦυ⁼⊟ιε«⊟ι,Ｉε,Ｐ✳⊟ι⎇⊖ε¹.¦⸿


Try it online! Link is to verbose version of code. Takes an array of strings as input. Explanation:

≔⪫Ａ⸿θＰθ


Join the strings with carriage returns (not newlines) and output them without moving the cursor.

Ｆθ«


Loop over each character in the string.

≔⟦⟧η


Collect all of the consecutive characters starting at this position in an array.

Ｆ∧¬№0⸿ι⟦→↘↓↙⟧«


If the current character is not a 0 or a carriage return, then check all four directions.

≔ＫＤＬθ✳κζ


Peek as much as possible in that direction.

Ｗ›Ｌζ№ζι≔⊟ζε


Shorten the string until all of the characters are the same.

⊞η⟦κιＬζ⟧»


Save the results in the array.

¿⁼¹⌈Ｅη§κ²⊞υ⊟ηＦη⊞υκ


If the maximum consecutive character was 1, then only push one of the results to the final array, otherwise push all of them.

ι»


Reprint the current character, this time allowing the cursor to move.

⎚


Clear the input from the canvas.

≔⌈Ｅυ§ι²ε


Find the longest consecutive length.

ＦΦυ⁼⊟ιε«


Loop over the entries with that length.

⊟ι,Ｉε,


Output the character and length.

Ｐ✳⊟ι⎇⊖ε¹.¦⸿


If the length is 1 then output a . otherwise output a direction character. Then move to the start of the next line for the next result.

05AB1E, 82 bytes

í‚εεygÅ0«NFÁ]€øIIø)εεγJ0K}˜D€gøNUε"/\-|"XèªćÙš]€D€ÅsZQÏεDÅsi¤'.:]{γεÐнÅsig4÷∍]€


Input as a matrix of characters. Outputs as a list of triples.

Explanation:

Generate all diagonals and anti-diagonals of the input-matrix:

í                 # Reverse each row of the (implicit) input-matrix
‚                # Pair it with the (implicit) input-matrix
ε               # Map both matrices to:
ε              #  Map each row to:
yg            #   Get the length of the current row
Å0«         #   Append that many 0s at the end of the row
NFÁ      #   Rotate the row the 0-based index amount of times towards the right
]               # Close the rotate-loop and nested maps
€ø             # Transpose/zip (swapping rows/columns) for both matrices
# And push both matrices to the stack


Put them in a list with the input-matrix itself, as well as all columns of the input-matrix:

I                 # Push the input-matrix
Iø               # Push the input-matrix, and transpose/zip (swapping rows/columns)
)              # Wrap everything on the stack into a list


Now that we have a list of all diagonals, all anti-diagonals, all rows, and all columns, we're going to extract chunks of the same characters, and transform them into the output triplets:

ε                 # Map each matrix to:
ε                #  Map each row to:
γ               #   Split into chunks of the same elements
J              #   Join them together to a string
0K            #   Remove all 0s
}˜               #  After the map of the rows: deep-flatten all chunks
€g            #  Get the length of each chunk
D  ø           #  And pair it with the chunk itself
NU         #  Store the current index in variable X
ε          #  Map over the chunk and length pairs:
"/\-|"Xè  #   Get the X'th character from the string "/\|-"
ª #   And append it to the pair
ć         #   Extract head; push the length plus character pair and chunk
#   separately to the stack
Ù        #   Uniquify the chunk so a single character remains
š       #   And prepend it back in front of the length & character pair
]                 # Close both maps
€               # And then flatten once


Now that we have all our triplets, we only leave the largest ones:

 €Ås              # Get the middle element (the chunk-length) of each
Z             # Get the maximum chunk-length (without popping the list itself)
Q            # Check for each chunk-length if it's equal to this maximum
D     Ï           # And only leave the triplets at the truthy indices


And finally we have to fix all . edge cases, for chunk-lengths of size 1:

ε                 # Map each triplet:
DÅsi             #  If the middle element (the chunk-length) is exactly 1:
¤'.:        '#   Replace the trailing character of the triplet with a "."
]                 # Close the if-statement and map
{                # Sort the triplets
γ               # And group them by the exact same triplets
ε              # Map each chunk of the same triplets to:
Ð             #  Triplicate the chunk of triplets
нÅsi         #  If the middle element of each triplet is 1:
g        #   Get the amount of the same triplets in this chunk
4÷      #   Integer-divide it by 4
∍     #   And shorten the chunk of triplets to that size
]              # Close the if-statement and map
€            # Flatten once
# (after which the result is output implicitly)