这是哪个tetromino?


54

给定一个无符号的16位整数N,您的任务是确定映射在4x4矩阵内的二进制表示形式是否与tetromino形状匹配,如果匹配,则匹配哪个形状。

矩阵

N的每一位都从最高有效位开始,从左到右,从上到下映射到4x4矩阵内。

范例

N = 17600
binary representation: 0100010011000000
matrix: [ [ 0, 1, 0, 0 ],
          [ 0, 1, 0, 0 ],
          [ 1, 1, 0, 0 ],
          [ 0, 0, 0, 0 ] ]

Tetromino形状

基本形状

有7种tetromino形状,由字母OISZLJT标识:

四丁胺

旋转和平移

如果在4x4矩阵中平移和/或旋转形状,则仍将其视为同一四聚胺的有效变体。例如,应该将17600、1136、2272和1604都标识为J trotrominoes:

有效的J范例

不要包!

但是,形状不能环绕或移出矩阵的任何边界。例如,既不是 568 也不 688应当认定为Ĵ tetrominoes(更不用说任何其它形状):

无效的J范例

澄清和规则

  • 您可以将输入作为整数,也可以直接将其作为16位二进制数字以任何合理的格式输入,例如2D数组,平面数组或定界字符串。
  • 确保输入为无符号的16位整数(或其等效表示为数组或字符串)。
  • 标识有效形状后,必须以大写小写字母打印或返回标识该形状的字母
  • 如果未识别出任何形状,则必须打印或返回不与任何Tetromino字母匹配的值。您也可以选择不返回任何内容。
  • 为了被认为是有效的,矩阵必须包含确切的四聚体形状,而没有任何其他单元格(在测试案例中请参见1911和34953)。
  • 这是,因此最短答案以字节为单位!

测试用例

您可以单击此链接将测试用例作为2D数组获取。

0      -> false
50     -> false
51     -> 'O'
1911   -> false
15     -> 'I'
34952  -> 'I'
34953  -> false
1122   -> 'S'
3168   -> 'Z'
785    -> 'L'
1136   -> 'J'
568    -> false
688    -> false
35968  -> 'T'
19520  -> 'T'

有趣的是,前几天我在研究一个极其类似的问题,然后才分心创建一种func1 . func2 . func3在JS中使用功能链的技术:P
ETHproductions

我可以接受输入,因为四行与连在一起0,即1111011110111101111for 65535吗?
ETHproductions'Aug

@ETHproductions看起来不错。我使用稍微宽松的输入格式编辑了挑战。
Arnauld

3
I:15,240,3840,4369,8738,17476,34952,61440J:71,113,142,226,275,550,802,1100,1136,1604,1808,2272,3208,3616,4400,8800,12832,17600,18176,25664,28928,36352,51328,57856L:23,46,116,232,368,547,736,785,1094,1570,1856,2188,3140,3712,5888,8752,11776,12560,17504,25120,29696,35008,50240,59392O:51,102,204,816,1632,3264,13056,26112,52224S:54,108,561,864,1122,1728,2244,8976,13824,17952,27648,35904T:39,78,114,228,305,562,610,624,1124,1220,1248,1824,2248,3648,4880,8992,9760,9984,17984,19520,19968,29184,35968,58368Z:99,198,306,612,1224,1584,3168,4896,9792,19584,25344,50688
Engineer Toast

^使用Lynn的Python 3答案生成,因为它具有方便的输入/输出格式。
Engineer Toast

Answers:


6

果冻 54 43 42  41 字节

-1个字节感谢Outgolfer的Erik(在重复的链中移动转置)

T€FṀ⁸ṙ€Zµ⁺F
ZU$3СǀḄṂ“çc3Ð6'G‘i’ị“¥Çıƭ⁵»

单键链接,该链接采用2D整数数组(1s和0s),并oiszljt为相应的Tetromino 返回小写字母,或者返回w无效的字母。

在线尝试!或查看测试套件

另请参阅此程序,其中列出了所有1820种可能的2D二进制数组,它们的输出正好设置了四个位,并按这些输出排序。

怎么样?

这首先进行输入的所有四个旋转。然后,将每个位的设置位尽可能向右移动,然后尽可能地向底部移动,并将结果转换为二进制数。然后,它在每个有效的Tetromino的最小此类表示形式的列表中查找最小结果,并使用递减后的结果索引到两个串联的字典词zoist+中jowlw如果未找到匹配项,则会产生该结果。

T€FṀ⁸ṙ€Zµ⁺F - Link 1, shift set bits right & then down : list of lists of bits          
        µ⁺  - perform the following twice, 1st with x=input, then with x=result of that):
T€          -   truthy indexes of €ach
  F         -   flatten into a single list
   Ṁ        -   maximum (the index of the right-most bit)
    ⁸       -   chain's left argument, x
     ṙ€     -   rotate €ach left by that amount
       Z    -   transpose the result
          F - flatten (avoids an € in the main link moving this into here)

ZU$3СǀḄṂ“çc3Ð6'G‘i’ị“¥Çıƭ⁵» - Main link: list of lists of bits (the integers 0 or 1)
   3С                        - repeat this 3 times collecting the 4 results:
  $                           -   last two links as a monad:
Z                             -     transpose
 U                            -     upend (reverse each) -- net effect rotate 90° CW
      Ç€                      - call the last link as a monad for €ach
        Ḅ                     - convert from binary (vectorises)
         Ṃ                    - minimum (of the four results)
          “çc3Ð6'G‘           - code-page indexes = [23,99,51,15,54,39,71]
                              -   ...the minimal such results for l,z,o,i,s,t,j shapes
                   i          - 1-based index of minimum in there or 0 if not found
                    ’         - decrement
                      “¥Çıƭ⁵» - compressed words: "zoist"+"jowl" = "zoistjowl"
                     ị        - index into (1 indexed & modular, so -1 yields 'w',
                              -             0 yields 'l', 1 yields 'z', ...)

前一种方法(54个字节)

Fœr0Ḅ“çc3Ðñ'G‘i
;Z$Ḅ©f“¦µ½¿Æ‘ȯ®¬S>2ȧZU$3СǀṀ’ị“¥Çıƭ⁵»

单键链接,该链接采用2D整数数组(1s和0s),并oiszljt为相应的Tetromino 返回小写字母,或者返回w无效的字母。

在线尝试!

这将检查至少有三个空行(行+列),并且任何行中都不存在某些位模式(具体为数字5、9、10、11和13),这些共同保证了下一步不会产生误报。然后将其平整,然后平移四次旋转的每一个的二进制数(通过在转换前去除尾随零),并使用减少的结果索引两个串联的字典词,在数字列表中查找最小结果。zoist+ jowlw在找不到匹配项时产生。


而且我知道还有比硬编码更好的方法了
Outgolfer的Erik

顺便说一句,我认为这段代码取决于一个巧合(因为,zoistjowl否则,通常不适合一个字符串:p)
Egg the Outgolfer

您的意思是“取决于巧合”?(...Ṁị“LZOISTJW无论如何,字典查找都只会节省一个字节)
乔纳森·艾伦

嗯...是的,我知道这不会持续很长时间...顺便说一句,我想你偷了我的ZU$3С:p
乡下人埃里克(Erik the Outgolfer)

提交上一个方法后,昨天我尝试使用相同的方法,但我觉得有点累。
乔纳森·艾伦,

28

Python 3,124字节

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]

在线尝试!

期望整数n表示4×4二进制矩阵。如果未找到Tetromino,则抛出该异常。

第2行将形状向右滑动,直到最右边的列中为1。(4369是0001 0001 0001 0001二进制的。)第3行降低形状,直到第一行中有1。在一起,例如:

    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

然后,n在此列表中寻找的索引:

 [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

等效模数为7的索引的每列对应于一个Tetromino形状。代码中的这一点不能将64(@)用作填充值n

注意 0通过计算n/n而不是引发输入异常1


为什么您的二进制字符串起作用?我在Python 3中遇到了问题,请参见注释codegolf.stackexchange.com/a/85201/53667
Karl Napf

Python使用UTF-8作为源代码和文本输出的默认编码。但是在UTF-8 中不会读取 PPM文件。运行时print("ÿ"),写入的字节为c3 bf 0a,不是ff 0a,并且PPM图像变成垃圾。
林恩

8

APL(Dyalog)95 94 93 89 87字节

-2感谢Zacharý

要求⎕IO←0在许多系统上是默认设置。将布尔矩阵(任何形状!)作为参数。如果给定位数不为4,则不返回任何内容;如果给定位数为4,则不返回空白行。

{4=+/,⍵:'OIZSJLT'/⍨∨/1∊¨(((2 2)4⍴¨1),(0 1⌽¨⊂K2J),(⍳3)⊖¨⊂J1,⍪K31)∘.⍷⍵∘{⌽∘⍉⍣⍵⊢⍺}¨⍳4}

在线尝试!

通过创建输入的所有四个旋转,然后在每个旋转中查找每个tetromino来工作。

{} 匿名函数,其中的参数由表示

,⍵ 拉扯(拉平)论点

+/ 总结一下

4= 等于四个吗?

: 如果是这样,则(否则不返回任何内容):

  ⍳4 前四个ɩ ndices; [0,1,2,3]

  ⍵∘{ 对每个应用以下函数,使用输入作为固定的左参数

    左参数,即输入

   ⊢⍺ 得到的是(分离

   ⌽∘⍉⍣⍵ 镜像和转置(即旋转90°)时间

  ()∘.⍷ 外部“产品”,但使用以下列表和轮换的Find *:

   3↑1 从1取三个元素,并以零填充; [1,0,0]

   K← 存储为 K

    表(做成列向量); [[1],[0],[0]]

   1, 前置一个 [[1,1],[1,0],[1,0]](“ J”)

   J← 存储为 J

   ()⊖¨⊂ 垂直旋转整个J,遵循以下步骤:

    ⍳3 前三个ɩ[0,1,2]

   我们有[[[1,1],[1,0],[1,0]],[[1,0],[1,0],[1,1]],[[1,0],[1,1],[1,0]]](“ J”,“ L”,“ T”)

   (), 放在以下列表的前面:

    2⊖J 旋转J垂直两个步骤; [[1,0],[1,1],[1,0]](“ T”)

    K⌽ 将其行分别旋转1、0和0步;[[0,1],[1,1],[1,0]](“ Z”)

    0 1⌽¨⊂ 垂直旋转整个阵列,一次又一次;[[[0,1],[1,1],[1,0]],[[1,0],[1,1],[0,1]]] (“ Z”,“ S”)

    (), 放在以下列表的前面:

     (2 2)4⍴¨1 将一个整形为2×2矩阵和4个元素列表;[[[1,1],[1,1]],[1,1,1,1]](“ O”,“ I”)

  1∊¨ 每个成员是一个成员吗?

  ∨/ 水平OR缩减(即,跨旋转;每个形状一个布尔值)

  'OIZSLJT'/⍨ 用它来过滤字符串

* Find返回一个布尔数组,该数组的形状与其右参数相同,并带有一个布尔数组,该数组指示所有与左参数相同的子数组的左上角。


这行得通吗?{4=+/,⍵:'OIZSJLT'/⍨∨/1∊¨(((2 2)4⍴¨1),(0 1⌽¨⊂K⌽2⊖J),(⍳3)⊖¨⊂J←1,⍪K←3↑1)∘.⍷⍵∘{⌽∘⍉⍣⍵⊢⍺}¨⍳4}
扎卡里

@Zacharý是的,谢谢,完成了。
2013年

7

JavaScript(ES6),242 212 172 164字节

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*$`))

本来只是为了使球滚动,但我对于那个\ _(ツ)_ /有点晚了。

接受一串位,行之间用0s('0001000110001000000'表示0001 0011 0010 0000)分隔,并返回一个包含表示tetromino的字符的数组,或者不包含任何内容的数组。

这是通过检查tetromino的每次旋转来检查输入是否在任何点上包含tetromino,并在两边完全用零包围的方法来工作。每个tetromino用一个或多个二进制数表示:

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

因此,要检查输入包含一个S四格拼板,我们只是检查是否含有任二进制表示51或者2145,只有0两边秒。

一些四聚体具有4个方向。如果查看它们的二进制表示,则每个都有2个表示,它们只是另外两个的镜像。为了节省空间,二进制表示与递归C函数同时进行了向前和向后的构建,这使我们仅可以放置两个方向,并隐含另外两个方向。


字符代码的替代方法:

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*$`))

3

视网膜,125字节

s`(.*1){5}.*

{s`.*1111.*
I
s`.*111(.{2,4})1.*
$.1
T`234`\LTJ
s`.*11(.{2,4})11.*
$.1
T`2-90`S\OZ4-9
s`.*4.*

O#$`.
$.%`
O#$^`

在线尝试!链接包括测试用例和标头,用于将整数转换为4×4矩阵。说明:

s`(.*1){5}.*

如果输入中包含5 1s,则将其删除。

{s`.*1111.*
I

检查输入的所有旋转(请参见下文)。如果输入包含四个连续1的,则为I

s`.*111(.{2,4})1.*
$.1
T`234`\LTJ

如果它包含三个连续的1s,并1在三个中的一个的下一行上加上a ,则将中间字符的数量映射到适当的结果字母。

s`.*11(.{2,4})11.*
$.1

类似地,对于下一行上与两个相邻1s相邻的两个相邻1s。

T`2-90`S\OZ4-9

但也要使用否则未使用的0s 来记录转数。

s`.*4.*

如果执行了太多的旋转,则放弃。

O#$`.
$.%`
O#$^`

转置并反转阵列,从而旋转阵列。


3

MATL,60字节

Itt6tIl7tl7H15vHe"4:"G@X!HYa]4$v@BIthYaEqY+4=aa]v'OSZLJTI'w)

输入是一个二进制4×4数组(矩阵),;用作行分隔符。Ouput是字母,也可以是空的,而不是tetromino。

在线尝试!验证所有测试用例(输出后附加一个点,以标识空结果)。

说明

该代码以90度为步长对输入4×4数组进行4次旋转。每个旋转的数组上下填充2个零,将其转换为8×4数组。将这4个数组垂直串联成一个32×4数组。由于零填充,此串联数组中的四个旋转数组被“隔离”。

测试了7种可能的模式中的每一种,以查看其是否存在于32×4阵列中。为此使用了一个循环。每个模式均由两个数字定义,以二进制表示,以给出适当的0/1掩码。例如,数字36定义了“S”形。

将7组2个数字排列成2×7矩阵,循环将从中按顺序选择每一列。通过将所有数字压入堆栈,将它们污染为向量,然后重塑为2行矩阵来定义矩阵。由于“ I”形状由数字15后面跟0定义,因此将其放在末尾允许重塑函数隐式填充0。

然后在四个方向上用3个零填充该蒙版。这对于检测输入中不需要的值很有必要。

为了查看掩码是否存在于32×4阵列中,将后者转换为双极形式(即-1/1而不是0/1)并与掩码进行卷积。由于掩码具有4,因此如果卷积结果中的某些项等于4,则会发生匹配。

在循环结束时,已获得7个假/真结果,其中最多一个是真。它用于索引包含可能的输出字母的字符串。


3

果冻,53个字节

ZL0ẋW⁸tZµ⁺ZU$3С“©©“œ“Ç¿“¦©¦“ƽ‘;Uḃ2$’¤iЀṀị“÷¶Ė¡µỵỤ»

在线尝试!

完整程序。需要4x4。打印m如果不是四格拼板,否则打印小写。


是...将位数组视为合法吗?那将为我节省40个字节
ETHproductions'Aug

@ETHproductions 您可以将输入作为整数,也可以直接作为4x4二进制数字的2D数组或16个二进制数字的平面数组。
暴民埃里克(Erik the Outgolfer)'17年

呵呵,为我解决问题提供了正确的服务……
ETHproductions'Aug

1

Perl 5,197 + 1(-p)= 198字节

s/(0000)*$//;1while s/(...)0(...)0(...)0(...)0/0${1}0${2}0${3}0${4}/;$_={51,O,15,I,4369,I,54,S,561,S,99,Z,306,Z,547,L,23,L,785,L,116,L,275,J,113,J,802,J,71,J,114,T,562,T,39,T,609,T}->{oct("0b".$_)}

在线尝试!

接受16位字符串作为输入。如果输入不是单个Tetromino,则不输出任何内容。

怎么样?

这两个替换将输入形状“移动”到右下角。生成的位字符串将转换为整数,然后在有效整数的哈希中进行检查。


1

APL(Dyalog),66字节

{'TIOJSLZ-'[(¯51 144 64,,∘+⍨12J96 ¯48J64)⍳×/(+/-4×⊢)⍵/,0j1⊥¨⍳4 4]}

在线尝试!

arg是布尔向量。

将点到重心的有符号距离计算为复数(实部和虚部为∆x,∆y),然后将复数相乘。事实证明,足够好的不变式可以区分四聚体。


有趣的方法。
Arnauld
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.