# JavaScript (ES6), 165 bytes Expects a list of binary strings. <!-- language-all: lang-javascript --> m=>m.map(M=r=>(M|=v='0b'+r|0,m&=v||m,v),m=~0).map(v=>v?(b=v+(v&-v))&b-1?3:v^m?2^v<M:1:0).join``.match(`^0*(1+${s=(g=m=>m?2+g(m&m-1):'')(m)}|${s}1+)0*$`)&&M*2&M/2&m^m [Try it online!][TIO-m3f328fy] [JavaScript (Node.js)]: https://nodejs.org [TIO-m3f328fy]: https://tio.run/##jVHLboMwELznKyIUGZtHuktvqIZbb9x6o0E8mpBEGCKglqqS/jqlaQtEJUn3tLZnZ3bG@0hGVVLuDrWZFy/rdsNbwR2xFNGBerzkDvUaLrkKsaqXDRiCcNk0wpDMEPwD2AkouSNdGnOpU0lMyRiJTXTvbRkI1wrkg2ej3UH3xS4Pw26iTrY0DECjqC/eK05T/qXpWnpKBREmMltVGRXs2HTPR9QZaIuQEeJpFvHuLCIC0SZFXhXZepkVKVX8p/K13r6tFDYb32@oP5vPFQDsChRj8gAAymzFJic7ZA/8bS6j4VQ9btTjuMdpDNyg7pfGkQE8MzNNd8anPOf@Y5RVl7LCq@5@yAfJM/HLMY7T@977hteefsj/P0LwN/ZhU8SrPw2jSE@w9hM "JavaScript (Node.js) – Try It Online" ## How? ### Step 1 We first convert the input matrix \$m[\:]\$ into a list of integers. At the same time, we compute the bit mask \$M\$ of all rows OR'd together and the bit mask \$m\$ of all non-empty rows AND'd together. <!-- language: lang-javascript --> m.map(M = // start with M zero'ish r => // for each row r in m[]: ( M |= v = '0b' + r | 0, // turn r into an integer v by parsing it as binary // and update M by doing M = M OR v m &= v || m, // if v is not equal to 0, update m by doing m = m AND v v // yield v as the actual value for the map() ), // m = ~0 // start with all bits set in m ) // end of map() If the shape is valid: - \$m\$ is the pattern for the vertical leg - \$M\$ is the pattern for the horizontal leg - the list returned by `map()` contains only \$m\$, \$M\$ and optional \$0\$'s **Example:** input | bin -> dec | M | m -----------+------------+----+----- "0000000" | 0 | 0 | ~0 "0100000" | 32 | 32 | 32 "0100000" | 32 | 32 | 32 "0111110" | 62 | 62 | 32 "0000000" | 0 | 62 | 32 ### Step 2 We convert the list into a string of digits, using \$0\$ for empty rows, \$1\$ for rows equal to \$m\$, \$2\$ for rows equal to \$M\$, or \$3\$ for invalid rows. <!-- language: lang-javascript --> .map(v => // for each value v in the list: v ? // if v is not equal to 0: (b = v + (v & -v)) // if adding to v the least significant bit set in v & b - 1 ? // results in more than one bit set: 3 // this is an invalid row where at least one 0 // breaks a pattern of consecutive 1's : // else: v ^ m ? // if v is not equal to m: 2 ^ // yield 2 if v = M v < M // or yield 3 if v != M (invalid) : // else (v = m): 1 // yield 1 : // else (empty row): 0 // yield 0 ) // end of map() .join`` // join all digits ### Step 3 We build a regular expression to test whether the string is valid. <!-- language: lang-javascript --> .match( // test the resulting string: "^0*(" + // optional leading 0's // followed by either: "1+" + // one or several 1's ( s = // followed by as many 2's as the number of bits set ( g = m => // in m m ? // 2 + g(m & m - 1) // this string of 2's is computed with the recursive : // function g and saved in s '' // )(m) // ) + // "|" + // or: s + "1+" + // as many 2's as the number of bits set // in m, followed by one or several 1's ")0*$" // followed by optional trailing 0's ) // end of match() ### Step 4 Finally, we make sure that \$m\$ and \$M\$ form a right angle. Either \$m\text{ AND }(M\times 2)\$ or \$m\text{ AND }\lfloor M/2\rfloor\$ must be different from \$m\$: <!-- language: lang-javascript --> M * 2 & M / 2 & m ^ m