Este quadrado é simétrico?

22

Escreva um programa ou função que utilize uma grade de texto 4 × 4 composta exatamente por 4 A, 4 B, 4 Ce 4 D, como:

ACDC
BBCA
BADD
ABCD

Os ABCDpodem estar em qualquer arranjo, mas sempre haverá 4 de cada. Você pode assumir que a entrada é válida. Se desejado, você também pode assumir que ela possui uma nova linha à direita e / ou que vem como uma linha na ordem de leitura, por exemplo ACDCBBCABADDABCD. Você também pode substituir os caracteres ABCDcom 0123ou 1234respectivamente, se desejar (mas isso é tudo).

Emita um valor verdadeiro se a grade de texto tiver qualquer forma de simetria refletiva ou rotacional. Especificamente:

  • Se houver uma linha horizontal central de simetria. por exemplo

    BACD
    BACD 
    BACD \___ bottom mirrors top
    BACD /
    
  • Se houver uma linha vertical central de simetria. por exemplo

    BCCB
    DAAD
    CAAC
    BDDB
      \/___ right mirrors left
    
  • Se houver uma linha diagonal de simetria (em qualquer direção). por exemplo

         ___ diagonally mirrored
        /
    ABDC
    BACD
    DCAB
    CDBA
        \___ diagonally mirrored
    
  • Se houver simetria rotacional de 90 °. por exemplo

    BDAB
    ACCD    same if rotated 90 degrees (or 180 or 270)
    DCCA
    BADB
    
  • Se houver simetria rotacional de 180 °. por exemplo

    DBCA
    BDCA    same if rotated 180 degrees
    ACDB
    ACBD
    

(Observe que a simetria da tradução não entra em jogo aqui.)

Emita um valor falso se a grade não tiver uma das simetrias mencionadas acima. por exemplo, o primeiro exemplo de grade.

O código mais curto em bytes vence.

Passatempos de Calvin
fonte
Podemos pegar uma lista de quatro strings como entrada?
Martin Ender
@MartinEnder Sim, tudo bem.
Hobbies de Calvin
4
Acabei de ler isso e pensou "Não" lol
Shaun selvagem
Se você tivesse pensado em ladrilhar o quadrado, também poderia ter levado em conta a simetria da tradução.
Neil
1
@ Adám No. Não há mais formatos de entrada. Acho que não deveria ter permitido o de Martin.
Hobbies de Calvin

Respostas:

16

CJam, 16 bytes

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

Um bloco sem nome que espera a entrada como uma lista de quatro cadeias no topo da pilha e deixa um 0(falso) para entradas assimétricas e um número inteiro positivo (verdade) para entradas simétricas.

Teste aqui. Ou execute um conjunto de testes completo.

Explicação

As simetrias do quadrado são os elementos da grupo diédrico da ordem 8 (que são apenas as 4 rotações do quadrado e as mesmas 4 rotações de alguma versão refletida do quadrado). Não é possível gerar esse grupo a partir da aplicação repetida de uma única permutação. Mas duas reflexões sempre dão alguma rotação. Portanto, todo o grupo pode ser gerado alternando entre duas reflexões quatro vezes. (Precisamos apenas garantir que as duas reflexões produzam rotação de 90 ou 270 graus, e não 0 ou 180.)

O desafio pergunta se o quadrado de entrada é igual a qualquer uma das outras 7 simetrias. Portanto, essa resposta apenas gera todos eles e depois verifica se a entrada está entre as outras.

{      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.

Para ver como a aplicação repetida de ze W%gera todas as simetrias, dê uma olhada neste "diagrama":

     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
Martin Ender
fonte
Uau, você pode explicar isso? Você tem um built-in para todas as rotações / inversões?
Adám 18/08/16
@ Adám vou adicionar uma explicação completa daqui a pouco, mas zé a transposição e a W%reversão das linhas, por isso estou gerando todas as simetrias pela aplicação repetida delas .
Martin Ender
4
Obviamente, não há nada de especial no primeiro valor, mas, infelizmente, a abordagem mais purista de contar se você obtém 8 valores distintos custa um char a mais.
Peter Taylor
8

Pitão, 11 bytes

<7.u?%Y2CN_

Suíte de teste

Isso usa a técnica de transposição e reversão de Martin, mas com um toque. Enquanto outras soluções geraram explicitamente todas as 8 simetrias e contaram o número de aparências do original, este programa usa a .ufunção de Pyth .

A .ufunção é "Aplicar até que a repetição seja encontrada". Nesse caso, transpomos e invertemos alternadamente até que uma repetição aconteça e, em seguida, acumulamos os resultados em uma lista. Em seguida, removo os últimos 7 valores, para que restará apenas um valor se não houvesse simetria e a primeira repetição ocorreu depois que todas as 8 reflexões e repetições foram geradas.

Explicação:

<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
isaacg
fonte
5

05AB1E , 13 bytes

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

Explicação

Usa o método habilmente explicado por Martin em sua resposta 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

Experimente online

Emigna
fonte
4

Perl, 61 60 bytes

Inclui +3 para -p0a

Dê um quadrado de entrada em STDIN, imprime 0 sem simetria, caso contrário, algum número positivo

./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}{
Ton Hospel
fonte
4

Dyalog APL , 37 19 17 bytes

@ngn reduziu em 20 bytes!

8>≢(∪⊢,⌽¨,⍉¨)⍣≡⊂⎕

TryAPL online!

Adão
fonte
⍉¨em vez de ⌽∘⍉¨funciona também.
NGN
@ngn Feito. Obrigado. Te vejo amanhã.
Adám 21/08/16
3

Braquilog , 38 36 bytes

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

Experimente online!

Isso espera uma lista de strings como entrada. Isso imprime true.ou false..

Explicação

  • Predicado principal:

    @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
    
  • Predicado 1: A saída é uma das 8 simetrias da entrada.

    (
        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
    )
    
Fatalizar
fonte
3

TSQL, 229 bytes

Esteja ciente de que o TSQL não possui build-in para rotação, portanto isso está incluído no código.

Golfe:

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

Ungolfed:

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

Violino

t-clausen.dk
fonte
2

Python 2, 154 146 bytes

Verifica se alguma das transformações necessárias é equivalente ao original usando matrizes numpy. A entrada é tomada como uma lista de quatro cadeias.

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))])

Experimente online

Receber a entrada como uma única string é um caractere mais longo, com A=array(list(input())).reshape(4,4). A[:,::-1]é o mesmo que fliplr(A). A[::-1]é o mesmo que flipud(A).

mbomb007
fonte
Talvez use em map(list,input())vez de[list(r)for r in input()]
Cyoce
Obrigado @Cyoce. Idk como eu perdi isso.
mbomb007
anyusa uma expressão de gerador, para que você possa salvar alguns bytes, removendo o par externo de colchetes.
TheBikingViking
@TheBikingViking Eu já tinha tentado isso. Se você passa um gerador, ele retorna um gerador, fazendo com que a printinstrução não funcione. Tente digitar meu código on-line e executá-lo dessa maneira para ver.
mbomb007
Ah ok. Eu não percebi que isso iria quebrar o print.
TheBikingViking
2

Python 3, 99 bytes

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

Uma função que recebe entrada, via argumento, de uma lista de strings e retornos TrueouFalse como relevante.

Isso usa a mesma abordagem da resposta do @ MartinEnder .

Como funciona

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

Experimente no Ideone

TheBikingViking
fonte
2

JavaScript (ES6), 131 bytes

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)

17 bytes podem ser removidos se você passar uma matriz de 4 seqüências diretamente. Eu tentei mexer em bits (entrada em "0123301223011230"formato), mas isso me levou em 199 bytes:

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)
Neil
fonte