Which tetromino is this?
Python 3, 124 bytes
def f(n):
while n&4369<n/n:n>>=1
while n&15<1:n>>=4
return'TJLZSIO'["rēȣc63ıGtIJȱᄑ@'̢̑@@@@Ȳq".index(chr(n))%7]
Try it online!
Expects an integer n representing a 4 × 4 binary matrix. Throws if no tetromino is found.
Line 2 slides the shape to the right until a 1 is in the rightmost column. (4369 is 0001 0001 0001 0001
in binary.) Line 3 lowers the shape until a 1 is in the bottom row. Together this turns e.g.:
0 1 0 0 0 0 0 0
1 1 1 0 into 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 1 1 1
Then we look for the index of n
in this list:
[114 275 547 99 54 15 51
305 71 116 306 561 4369 64
39 802 785 64 64 64 64
562 113 23]
# T J L Z S I O
Each column of indices equivalent modulo 7 corresponds to a tetromino shape. 64 (@
) is used as a padding value as n
cannot be 64 at this point in the code.
NB. An exception is thrown for input 0
by computing n/n
instead of 1
.
APL (Dyalog), 95 94 93 89 87 bytes
-2 thanks to Zacharý
Requires ⎕IO←0
which is default on many systems. Takes Boolean matrix (of any shape!) as argument. Returns nothing if the given number of bits is not four, and a blank line if the four given bits do not form a tetromino.
{4=+/,⍵:'OIZSJLT'/⍨∨/1∊¨(((2 2)4⍴¨1),(0 1⌽¨⊂K⌽2⊖J),(⍳3)⊖¨⊂J←1,⍪K←3↑1)∘.⍷⍵∘{⌽∘⍉⍣⍵⊢⍺}¨⍳4}
Try it online!
Works by creating all four rotations of the input, then looking for each tetromino in each rotation.
{
…}
anonymous function where the argument is represented by ⍵
:
,⍵
ravel (flatten) the argument
+/
sum it
4=
is four equal to that?
:
if so, then (else return nothing):
⍳4
first four ɩndices; [0,1,2,3]
⍵∘{
…}¨
apply the following function on each, using the input as fixed left argument
⍺
the left argument i.e. the input
⊢⍺
yield that (separates ⍵
from ⍺
)
⌽∘⍉⍣⍵
mirror and transpose (i.e. rotate 90°) ⍵
times
(
…)∘.⍷
outer "product", but using Find*, of the following list and the rotations:
3↑1
take three elements from one, padding with zeros; [1,0,0]
K←
store that as K
⍪
table (make into column vector); [[1],[0],[0]]
1,
prepend a one; [[1,1],[1,0],[1,0]]
("J")
J←
store as J
(
…)⊖¨⊂
rotate the entire J vertically, each of the following number of steps:
⍳3
first three ɩntegers; [0,1,2]
we have [[[1,1],[1,0],[1,0]],[[1,0],[1,0],[1,1]],[[1,0],[1,1],[1,0]]]
("J", "L, "T")
(
…),
prepend the following list:
2⊖J
rotate J
two steps vertically; [[1,0],[1,1],[1,0]]
("T")
K⌽
rotate the rows of that by 1, 0, and 0 steps respectively; [[0,1],[1,1],[1,0]]
("Z")
0 1⌽¨⊂
rotate the entire array vertically, no times and once; [[[0,1],[1,1],[1,0]],[[1,0],[1,1],[0,1]]]
("Z", "S")
(
…),
prepend the following list:
(2 2)4⍴¨1
reshape a one into each of a 2×2 matrix and a 4-element list; [[[1,1],[1,1]],[1,1,1,1]]
("O", "I")
1∊¨
for each, is one a member?
∨/
horizontal OR reduction (i.e. across rotations; one Boolean for each shape)
'OIZSLJT'/⍨
use that to filter the string
* Find returns a Boolean array of same shape as its right argument, with ones indicating the top left corner of all subarrays identical to the left argument.
JavaScript (ES6), 242 212 172 164 bytes
x=>[...'OISZLJT'].filter((z,y)=>x.match(`^0*(${'99,33825|15,51|2145,195|561,2115|57,1059|135,71|1073'.split`,`[y].replace(/\d+/g,C=x=>x?x%2+C(x>>1)+x%2:'|')})0*$`))
Was supposed to be just to get the ball rolling, but I'm a little late for that ¯\_(ツ)_/¯
Takes a string of bits, with rows separated by 0
s ('0001000110001000000'
representing 0001 0011 0010 0000
) and returns an array containing the character representing the tetromino, or an array containing nothing.
This works by checking each rotation of tetromino to see if the input at any point contains the tetromino, surrounded entirely by zeroes on either side. Each tetromino is represented by one or more binary numbers:
0 0 0 0 -> 0000 0110 1100 0000
0 1 1 0 -> 0000001100110000000
1 1 0 0 -> 110011
0 0 0 0 -> 51
0 1 0 0 -> 0100 0110 0010 0000
0 1 1 0 -> 0100001100001000000
0 0 1 0 -> 100001100001
0 0 0 0 -> 2145
So to check if the input contains an S tetromino, we simply check whether it contains the binary representation of either 51
or 2145
, with only 0
s on either side.
A few of the tetrominoes have 4 orientations. If you look at the binary representations of these, each has 2 representations which are simply the mirror of the other two. To save space, the binary representation is built up forward and backward simultaneously with the recursive C
function, allowing us to only put two of the orientations in and have the other two implied.
Alternate approach with charcodes:
x=>[...'OISZLJT'].filter((z,y)=>x.match(`^0*(${[...'÷,êÿ,óî,ûÝ,ëúüÏ,çöïþ,ßýíÞ'.split`,`[y]].map(c=>(C=n=>n?'1e'+(n%4+2)%5-0+C(n>>2):'')(c.charCodeAt())).join`|`})0*$`))