¿Es este cuadrado simétrico?

22

Escriba un programa o función que tome una cuadrícula de texto de 4 × 4 que consta exactamente de 4 A's, 4 B' s, 4 C's y 4 D' s, tales como:

ACDC
BBCA
BADD
ABCD

El ABCD's puede estar en cualquier disposición, pero siempre habrá 4 de cada uno. Puede asumir que la entrada es válida. Si lo desea, también puede suponer que tiene una nueva línea final y / o que viene como una línea en el orden de lectura, por ejemplo ACDCBBCABADDABCD. También puede reemplazar los caracteres ABCDcon 0123o 1234respectivamente, si lo desea (pero eso es todo).

Produzca un valor verdadero si la cuadrícula de texto tiene alguna forma de simetría reflexiva o rotacional. Específicamente:

  • Si hay una línea horizontal central de simetría. p.ej

    BACD
    BACD 
    BACD \___ bottom mirrors top
    BACD /
    
  • Si hay una línea vertical central de simetría. p.ej

    BCCB
    DAAD
    CAAC
    BDDB
      \/___ right mirrors left
    
  • Si hay una línea diagonal de simetría (en cualquier dirección). p.ej

         ___ diagonally mirrored
        /
    ABDC
    BACD
    DCAB
    CDBA
        \___ diagonally mirrored
    
  • Si hay una simetría rotacional de 90 °. p.ej

    BDAB
    ACCD    same if rotated 90 degrees (or 180 or 270)
    DCCA
    BADB
    
  • Si hay una simetría rotacional de 180 °. p.ej

    DBCA
    BDCA    same if rotated 180 degrees
    ACDB
    ACBD
    

(Tenga en cuenta que la simetría traslacional no entra en juego aquí).

Genere un valor falso si la cuadrícula no tiene una de las simetrías mencionadas anteriormente. por ejemplo, la primera cuadrícula de ejemplo.

El código más corto en bytes gana.

Pasatiempos de Calvin
fuente
¿Podemos tomar una lista de cuatro cadenas como entrada?
Martin Ender
@ MartinEnder Sí, está bien.
Aficiones de Calvin
44
Acabo de leer eso y pensé "no" jajaja
Shaun Wild
Si hubiera pensado en mosaico del cuadrado, entonces también podría haber tenido en cuenta la simetría traslacional.
Neil
1
@ Adám No. No más formatos de entrada. Siento que realmente no debería haber permitido Martin's.
Hobbies de Calvin

Respuestas:

16

CJam, 16 bytes

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

Un bloque sin nombre que espera la entrada como una lista de cuatro cadenas en la parte superior de la pila y deja un 0(falso) para entradas asimétricas y un entero positivo (verdadero) para entradas simétricas.

Pruébalo aquí. O ejecute un conjunto de pruebas completo.

Explicación

Las simetrías del cuadrado son los elementos del grupo diédrico de orden 8 (que son solo las 4 rotaciones del cuadrado y las mismas 4 rotaciones de alguna versión reflejada del cuadrado). No es posible generar este grupo a partir de la aplicación repetida de una sola permutación. Pero dos reflexiones siempre dan algo de rotación. Por lo tanto, todo el grupo se puede generar alternando entre dos reflexiones cuatro veces. (Solo necesitamos asegurarnos de que las dos reflexiones den una rotación de 90 grados o 270 grados, no 0 o 180).

El desafío pregunta si el cuadrado de entrada es igual a cualquiera de las otras 7 simetrías. Entonces, esta respuesta solo los genera a todos y luego verifica si la entrada está entre las demás.

{      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 cómo la aplicación repetida de zy W%genera todas las simetrías, eche un vistazo a este "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
fuente
Wow, ¿puedes explicar esto? ¿Tiene un incorporado para todas las rotaciones / volteos?
Adám
@ Adám Agregaré una explicación completa en un momento, pero zes transponer e W%invertir las líneas, así que solo estoy generando todas las simetrías mediante la aplicación repetida de esas.
Martin Ender
44
Por supuesto, no hay nada especial sobre el primer valor, pero lamentablemente el enfoque más purista de contar si obtiene 8 valores distintos cuesta un char más.
Peter Taylor
8

Pyth, 11 bytes

<7.u?%Y2CN_

Banco de pruebas

Utiliza la técnica de transposición y reversa de Martin, pero con un giro. Mientras que otras soluciones han generado explícitamente las 8 simetrías, luego contaron el número de apariencias del original, este programa utiliza la .ufunción de Pyth .

La .ufunción es "Aplicar hasta que se encuentre la repetición". En este caso, transponemos e invertimos alternativamente hasta que ocurre una repetición, luego acumulamos los resultados en una lista. Luego, elimino los últimos 7 valores, por lo que solo quedará un valor si no hubiera simetrías, y la primera repetición ocurrió después de que se generaron las 8 reflexiones y repeticiones.

Explicación:

<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
fuente
5

05AB1E , 13 bytes

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

Explicación

Utiliza el método experto explicado por Martin en su respuesta de 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

Pruébalo en línea

Emigna
fuente
4

Perl, 61 60 bytes

Incluye +3 para -p0a

Proporcione un cuadrado de entrada en STDIN, imprime 0 sin simetría, de lo contrario, algún 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
fuente
4

Dyalog APL , 37 19 17 bytes

¡@ngn lo redujo en 20 bytes!

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

TryAPL en línea!

Adán
fuente
⍉¨en lugar de ⌽∘⍉¨obras también.
ngn
@ngn Hecho. Gracias. Te veo mañana.
Adám
3

Brachylog , 38 36 bytes

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

Pruébalo en línea!

Esto espera una lista de cadenas como entrada. Esto imprime ya sea true.o false..

Explicación

  • 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: La salida es una de las 8 simetrías de la 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
fuente
3

TSQL, 229 bytes

Tenga en cuenta que TSQL no tiene una función incorporada para la rotación, por lo que se incluye en el código.

Golfizado:

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

Sin golf:

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

Violín

t-clausen.dk
fuente
2

Python 2, 154 146 bytes

Comprueba si alguna de las transformaciones necesarias es equivalente a la original usando matrices numpy. La entrada se toma como una lista de cuatro cadenas.

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

Pruébalo en línea

Tomar la entrada como una sola cadena es un carácter más largo, con A=array(list(input())).reshape(4,4). A[:,::-1]es el mismo que fliplr(A). A[::-1]es el mismo que flipud(A).

mbomb007
fuente
Tal vez usar en map(list,input())lugar de[list(r)for r in input()]
Cyoce
@Cyoce Gracias. No sé cómo me perdí eso.
mbomb007
anytoma una expresión de generador, por lo que puede guardar algunos bytes al soltar el par externo de corchetes.
TheBikingViking
@TheBikingViking Ya lo había intentado. Si pasa un generador, entonces devuelve un generador, haciendo que la printdeclaración no funcione. Intente bifurcar mi código en línea y ejecutarlo de esa manera para ver.
mbomb007
Ah ok No me di cuenta de que rompería el 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

Una función que toma la entrada, a través del argumento, de una lista de cadenas y retornos Trueo Falsesegún sea relevante.

Utiliza el mismo enfoque que la respuesta de @ MartinEnder .

Cómo 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

Pruébalo en Ideone

TheBikingViking
fuente
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 podrían eliminarse si pasa una matriz de 4 cadenas directamente. Intenté bit-twiddling (entrada en "0123301223011230"formato) pero eso me llevó 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
fuente