这个正方形对称吗?


22

写一个程序或函数,它在一个4×4栅格的文本组成的正好是4 A的,4 B'S,4 C's和4 D的,如:

ACDC
BBCA
BADD
ABCD

所述ABCD的可以是任何布置,但总是会有各自的4。您可以假定输入有效。如果需要,您还可以假定它具有尾随换行符和/或它按阅读顺序排成一行,例如ACDCBBCABADDABCD。如果需要,您也可以分别ABCD0123或替换字符1234(仅此而已)。

如果文本网格具有任何形式的反射对称或旋转对称,则输出真实值。特别:

  • 如果有一条中心水平对称线。例如

    BACD
    BACD 
    BACD \___ bottom mirrors top
    BACD /
    
  • 如果有一条中心垂直对称线。例如

    BCCB
    DAAD
    CAAC
    BDDB
      \/___ right mirrors left
    
  • 如果有对角线对称线(在任一方向上)。例如

         ___ diagonally mirrored
        /
    ABDC
    BACD
    DCAB
    CDBA
        \___ diagonally mirrored
    
  • 如果存在90°旋转对称性。例如

    BDAB
    ACCD    same if rotated 90 degrees (or 180 or 270)
    DCCA
    BADB
    
  • 如果存在180°旋转对称性。例如

    DBCA
    BDCA    same if rotated 180 degrees
    ACDB
    ACBD
    

(请注意,此处不涉及平移对称性。)

如果网格不具有上述对称性之一,则输出虚假值。例如第一个示例网格。

以字节为单位的最短代码获胜。


我们可以将四个字符串的列表作为输入吗?
马丁·恩德

@MartinEnder是的,好的。
加尔文的爱好

4
我刚读完这个书,就想到“不”大声笑
肖恩·

如果您想平铺正方形,那么您也可以考虑平移对称性。
尼尔

1
@Adám号。没有其他输入格式。我觉得我本不该允许马丁的。
加尔文的爱好

Answers:


16

CJam,16个字节

{{z_W%_}4*;])e=}

一个未命名的块,期望将输入作为堆栈顶部的四个字符串的列表,并0为非对称输入保留(虚假),为对称输入保留正整数(真实)。

在这里测试。 或运行完整的测试套件。

说明

正方形的对称性是8阶二面体组的元素(它们只是正方形的4旋转和正方形的某些反射版本的相同4旋转)。无法通过重复应用单个排列来生成此组。但是两次反射总是会产生一些旋转。因此,可以通过在两次反射之间交替四次来生成整个组。(我们只需要确保两个反射可以旋转90度或270度即可,而不是0或180度即可。)

质询询问输入平方是否等于其他7个对称中的任何一个。因此,此答案仅生成所有答案,然后检查输入是否在其他答案之中。

{      e# Run this block 4 times.
  z_   e# Transpose the grid and duplicate it. (This is one type of reflection.)
  W%_  e# Reverse the lines and duplicate it. (This is another type of
       e# reflection. Together they rotate the grid by 90 degrees.)
}4*    e# The last element will be the original grid again.
;      e# Discard one copy of that original grid.
]      e# Wrap all symmetries in a list.
)      e# Pull off the original grid.
e=     e# Count how many times it appears among the other symmetries.

要查看重复应用z和如何W%产生所有对称性,请看以下“关系图”:

     0123
     4567
     89ab
     cdef

     original

 z   048c       W%       37bf
-->  159d  ----------->  26ae
     26ae                159d
     37bf                048c

     diag. refl.         rot. 90 degrees ccw

 z   3210       W%       fedc
-->  7654  ----------->  ba98
     ba98                7654
     fedc                3210

     vert. refl.        rot. 180 degrees

 z   fb73       W%       c840
-->  ea62  ----------->  d951
     d951                ea62
     c840                fb73

     antidiag. refl.     rot. 270 degrees ccw

 z   cdef       W%       0123
-->  89ab  ----------->  4567
     4567                89ab
     0123                cdef

     horiz. refl.        original

哇,你能解释一下吗?您是否有内置的所有旋转/翻转功能?
2013年

@Adám我会稍加补充说明,但z会转置并W%颠倒线条,因此我只是通过重复应用这些对称来生成所有对称。
马丁·恩德

4
当然,第一个值没有什么特别的,但是令人遗憾的是,更纯粹的方法来计算是否获得8个不同的值会多花一个字符。
彼得·泰勒

8

Pyth,11个字节

<7.u?%Y2CN_

测试套件

这使用了马丁的转置和反转技术,但有所不同。虽然其他解决方案已明确生成所有8个对称性,然后计算了原始的出现次数,但此程序使用了Pyth .u函数。

.u功能是“应用直到找到重复”。在这种情况下,我们交替转置和反转直到发生重复,然后将结果累加到一个列表中。然后,我删除了最后7个值,因此只有在没有对称性的情况下才会剩下一个值,并且第一次重复是在生成所有8个反射和重复之后发生的。

说明:

<7.u?%Y2CN_
<7.u?%Y2CN_NQ    Implicit variables
                 Q = eval(input())
  .u        Q    Starting with Q, apply the following until a repeat occurs, 
                 then accumulate all values into a list.
    ?%Y2         If the iteration number is odd
        CN       Transpose
          _N     Else reverse
<7               Remove the last 7 results

5

05AB1E,13个字节

4Fø€JÂD}\\)¹å

说明

使用Martin在CJam答案中专门解释的方法。

4F     }       # 4 times do:
  ø€J          # zip and join each
     ÂD        # bifurcate, duplicate
        \\     # delete the top 2 items on the stack
          )    # wrap stack in list
           ¹å  # check if input is in that list

在线尝试


4

Perl,61 60字节

包括+3 -p0a

在STDIN上输入平方,不对称打印0,否则为正数

./symmetry.pl
DBCA
BDCA
ACDB
ACBD
^D

symmetry.pl

#!/usr/bin/perl -p0a
s,.,chop$F[$i++/($j-4?1:4)%4],eg;$\+=$$_++;++$j<8&&redo}{


3

Brachylog38岁 36字节

@eL:1fbeL
(L;?:raL)(.;L$\.;L$/.;Lr.)

在线尝试!

这需要一个字符串列表作为输入。这将打印true.false.

说明

  • 主要谓词:

    @eL    Split each line into a list of chars ; call that list of lists L
    :1f    Find all symmetries
    b      Remove the first one (the identity)
    eL     L is an element of that list of symmetries
    
  • 谓词1:输出是输入的8个对称之一。

    (
        L             L = Input
    ;             Or
        ?:raL         L = reverse all lines of the input
    )
    (
        .             Output = L
    ;             Or
        L$\.          Output = transpose of L    
    ;             Or
        L$/.          Output = antitranspose of L
    ;             Or
        Lr.           Output = reverse of L
    )
    

3

TSQL,229个字节

请注意,TSQL没有用于旋转的内置程序,因此它包含在代码中。

打高尔夫球:

DECLARE @1 char(16)=
'BCCBDAADCAACBDDB'

,@i INT=0,@ varchar(16)=''WHILE @i<16SELECT @+=substring(@1,@i*4%16+@i/4+1,1),@i+=1SELECT sign(count(*))FROM(SELECT LEFT(x,8)a,RIGHT(x,4)b,substring(x,9,4)c FROM(values(@1),(@))x(x))x WHERE c+b=reverse(a)or a=reverse(b+c)or a=b+c

取消高尔夫:

DECLARE @1 char(16)=
'BCCBDAADCAACBDDB'

,@i INT=0,@ varchar(16)=''
WHILE @i<16
  SELECT @+=substring(@1,@i*4%16+@i/4+1,1),@i+=1

SELECT sign(count(*))
FROM
  (SELECT LEFT(x,8)a,RIGHT(x,4)b,substring(x,9,4)c
   FROM(values(@1),(@))x(x))x
WHERE c+b=reverse(a)or a=reverse(b+c)or a=b+c

小提琴


2

Python 2中,154个 146字节

检查是否有任何必要的转换与使用numpy数组的原始转换等效。输入被视为四个字符串的列表。

from numpy import*
A=array(map(list,input()))
R=rot90
T=transpose(A)
print any([all(A==Z)for Z in(A[:,::-1],A[::-1],R(A),R(A,2),R(A,3),T,R(T,2))])

在线尝试

将输入作为单个字符串的时间要长一个字符,使用A=array(list(input())).reshape(4,4)A[:,::-1]与相同fliplr(A)A[::-1]与相同flipud(A)


也许用map(list,input())代替[list(r)for r in input()]
Cyoce

@Cyoce谢谢。我很想念我。
mbomb007 '16

any需要一个生成器表达式,因此您可以通过删除外部的一对方括号来节省一些字节。
TheBikingViking

@TheBikingViking我已经尝试过了。如果传递了生成器,则它将返回生成器,从而使该print语句不起作用。尝试分叉我的在线代码并以这种方式运行它以查看。
mbomb007

喔好吧。我没意识到它将打破僵局print
TheBikingViking

2

Python 3,99个字节

def f(x):
 t=x;c=[]
 for i in range(7):*t,=[map(''.join,zip(*t)),t[::-1]][i%2];c+=t,
 return x in c

该函数通过参数输入字符串列表并返回TrueFalse相关的。

这使用与@MartinEnder的答案相同的方法。

怎么运行的

def f(x)                Function with input list of strings x
 t=x;c=[]               Initilaise temporary square t and combination list c
 for i in range(7):...  For i in range [0,6]:
 [...][i%2]              If i is even:
 zip(*t)                  transpose(t)
 *t,=map(''.join,...)     t = t with each line concatenated (such that t is in the same
                          format as x)
                         Else:
 *t,=t[::-1]              t = reverse(t)
 c+=t,                   Append t to c
 return x in c           Return True if x is in c else return False

在Ideone上尝试


2

JavaScript(ES6),131个字节

s=>[...`0101010`].map(c=>+c?``+b.reverse():`${b=b.map((s,i)=>s.replace(/./g,(_,j)=>b[j][i]))}`,b=a=s.match(/..../g)).includes(``+a)

如果直接传递4个字符串组成的数组,则可以删除17个字节。我尝试了位旋转("0123301223011230"格式输入),但是这花了我199个字节:

s=>[...'0101010'].map(c=>r=+c?r<<24&255<<24|r<<8&255<<16|r>>8&255<<8|r>>>24:r&0xc0300c03|r<<6&806093568|r<<12&3075<<16|r<<18&3<<24|r>>6&0xc0300c|r>>12&49200|r>>18&192,r=n=parseInt(s,4)|0).includes(n)
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.