Questo quadrato è simmetrico?


22

Scrivi un programma o una funzione che includa una griglia di testo 4 × 4 composta esattamente da 4 A', 4 B', 4 C'e 4 D', come ad esempio:

ACDC
BBCA
BADD
ABCD

I ABCD's possono essere in qualsiasi disposizione, ma ci saranno sempre 4 di ciascuno. Si può presumere che l'input sia valido. Se lo si desidera, si può anche supporre che abbia una nuova riga finale e / o che arrivi come una riga in ordine di lettura, ad es ACDCBBCABADDABCD. Puoi anche sostituire i personaggi ABCDcon 0123o 1234rispettivamente, se lo desideri (ma questo è tutto).

Emette un valore veritiero se la griglia del testo ha qualche forma di simmetria riflettente o rotazionale. In particolare:

  • Se esiste una linea orizzontale centrale di simmetria. per esempio

    BACD
    BACD 
    BACD \___ bottom mirrors top
    BACD /
    
  • Se esiste una linea verticale centrale di simmetria. per esempio

    BCCB
    DAAD
    CAAC
    BDDB
      \/___ right mirrors left
    
  • Se esiste una linea diagonale di simmetria (in entrambe le direzioni). per esempio

         ___ diagonally mirrored
        /
    ABDC
    BACD
    DCAB
    CDBA
        \___ diagonally mirrored
    
  • Se esiste una simmetria di rotazione di 90 °. per esempio

    BDAB
    ACCD    same if rotated 90 degrees (or 180 or 270)
    DCCA
    BADB
    
  • Se esiste una simmetria di rotazione di 180 °. per esempio

    DBCA
    BDCA    same if rotated 180 degrees
    ACDB
    ACBD
    

(Notare che la simmetria traslazionale non entra in gioco qui.)

Emette un valore falso se la griglia non ha una delle simmetrie sopra menzionate. ad esempio la prima griglia di esempio.

Vince il codice più breve in byte.


Possiamo prendere un elenco di quattro stringhe come input?
Martin Ender,

@MartinEnder Sì, va bene.
Calvin's Hobbies,

4
L'ho appena letto e ho pensato "no" lol
Shaun Wild il

Se avessi pensato di piastrellare il quadrato, avresti potuto prendere in considerazione anche la simmetria traslazionale.
Neil,

1
@ Adám No. Non più formati di input. Sento che non avrei dovuto davvero permettere a Martin.
Calvin's Hobbies,

Risposte:


16

CJam, 16 byte

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

Un blocco senza nome che prevede l'input come un elenco di quattro stringhe in cima allo stack e lascia un 0(falsy) per input asimmetrici e un numero intero positivo (verità) per input simmetrici.

Provalo qui. Oppure esegui una suite di test completa.

Spiegazione

Le simmetrie del quadrato sono gli elementi del gruppo diedrico di ordine 8 (che sono solo le 4 rotazioni del quadrato e le stesse 4 rotazioni di alcune versioni riflesse del quadrato). Non è possibile generare questo gruppo dall'applicazione ripetuta di una singola permutazione. Ma due riflessi danno sempre una certa rotazione. Quindi, l'intero gruppo può essere generato alternando due volte quattro riflessioni. (Dobbiamo solo assicurarci che le due riflessioni forniscano una rotazione di 90 gradi o 270 gradi, non 0 o 180.)

La sfida chiede se il quadrato di input è uguale a una qualsiasi delle altre 7 simmetrie. Quindi questa risposta genera solo tutti loro e quindi controlla se l'input è tra gli altri.

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

Per vedere come l'applicazione ripetuta ze W%genera tutte le simmetrie, dai un'occhiata a questo "diagramma":

     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

Wow, puoi spiegarlo? Hai un built-in per tutte le rotazioni / ribaltamenti?
Adám,

@Adám Aggiungerò un po 'una spiegazione completa, ma zè trasporre e W%invertire le linee, quindi sto solo generando tutte le simmetrie applicando ripetutamente quelle.
Martin Ender,

4
Naturalmente non c'è nulla di speciale nel primo valore, ma purtroppo l'approccio più purista del conteggio se si ottengono 8 valori distinti costa un carattere in più.
Peter Taylor,

8

Pyth, 11 byte

<7.u?%Y2CN_

Suite di test

Questo utilizza la trasposizione e la tecnica inversa di Martin, ma con una svolta. Mentre altre soluzioni hanno generato esplicitamente tutte e 8 le simmetrie, quindi hanno contato il numero di aspetti dell'originale, questo programma utilizza Pyth's.u funzione .

Il .u funzione è "Applica fino a quando non viene trovata la ripetizione". In questo caso, alternativamente trasponiamo e invertiamo fino a quando si verifica una ripetizione, quindi accumuliamo i risultati in un elenco. Quindi, rimuovo gli ultimi 7 valori, quindi rimarrà solo un valore se non ci fossero simmetrie e la prima ripetizione è avvenuta dopo che sono state generate tutte e 8 le riflessioni e le ripetizioni.

Spiegazione:

<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 byte

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

Spiegazione

Utilizza il metodo abilmente spiegato da Martin nella sua risposta 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

Provalo online


4

Perl, 61 60 byte

Include +3 per -p0a

Fornisci un input quadrato su STDIN, stampa 0 per nessuna simmetria, altrimenti un numero 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}{


3

Brachylog , 38 36 byte

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

Provalo online!

Ciò prevede un elenco di stringhe come input. Questo stampa true.o false..

Spiegazione

  • Predicato principale:

    @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
    
  • Predicato 1: l'output è una delle 8 simmetrie dell'input.

    (
        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 byte

Attenzione, TSQL non ha build-in per la rotazione, quindi questo è incluso nel codice.

golfed:

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


2

Python 2, 154 146 byte

Verifica se una delle trasformazioni necessarie è equivalente all'originale utilizzando array intorpiditi. L'input viene considerato come un elenco di quattro stringhe.

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

Provalo online

Prendere input come una singola stringa è più lungo di un carattere, con A=array(list(input())).reshape(4,4). A[:,::-1]è lo stesso di fliplr(A). A[::-1]è lo stesso di flipud(A).


Forse usare map(list,input())invece di[list(r)for r in input()]
Cyoce il

@Cyoce Grazie. Idk come mi è mancato.
mbomb007,

anyaccetta un'espressione del generatore, quindi puoi salvare alcuni byte rilasciando la coppia esterna di parentesi quadre.
TheBikingViking

@TheBikingViking L'avevo già provato. Se si passa un generatore, restituisce un generatore, facendo in modo che l' printistruzione non funzioni. Prova a cambiare il mio codice online ed eseguirlo in questo modo per vedere.
mbomb007,

Ah ok. Non mi ero reso conto che avrebbe rotto il print.
TheBikingViking

2

Python 3, 99 byte

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 funzione che accetta input, tramite argomento, di un elenco di stringhe e ritorni Trueo Falsecome rilevante.

Questo utilizza lo stesso approccio della risposta di @ MartinEnder .

Come funziona

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

Provalo su Ideone


2

JavaScript (ES6), 131 byte

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 byte potrebbero essere rimossi se si passa direttamente un array di 4 stringhe. Ho provato bit-twiddling (input in "0123301223011230"formato) ma questo mi ha portato 199 byte:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.