Apakah kotak ini simetris?

22

Tulis program atau fungsi yang menggunakan kisi-kisi teks 4 × 4 yang terdiri dari tepat 4 A's, 4 B' s, 4 C's, dan 4 D' s, seperti:

ACDC
BBCA
BADD
ABCD

The ABCD's mungkin dalam pengaturan apapun tetapi akan selalu ada 4 masing-masing. Anda dapat menganggap input tersebut valid. Jika diinginkan, Anda juga dapat menganggap itu memiliki baris baru dan / atau bahwa itu datang sebagai satu baris dalam urutan membaca, misalnya ACDCBBCABADDABCD. Anda juga dapat mengganti karakter ABCDdengan 0123atau 1234masing - masing, jika diinginkan (tapi hanya itu).

Keluarkan nilai kebenaran jika kotak teks memiliki segala bentuk simetri reflektif atau rotasi. Secara khusus:

  • Jika ada garis simetri horizontal tengah. misalnya

    BACD
    BACD 
    BACD \___ bottom mirrors top
    BACD /
    
  • Jika ada garis vertikal pusat simetri. misalnya

    BCCB
    DAAD
    CAAC
    BDDB
      \/___ right mirrors left
    
  • Jika ada garis simetri diagonal (di kedua arah). misalnya

         ___ diagonally mirrored
        /
    ABDC
    BACD
    DCAB
    CDBA
        \___ diagonally mirrored
    
  • Jika ada simetri rotasi 90 °. misalnya

    BDAB
    ACCD    same if rotated 90 degrees (or 180 or 270)
    DCCA
    BADB
    
  • Jika ada simetri rotasi 180 °. misalnya

    DBCA
    BDCA    same if rotated 180 degrees
    ACDB
    ACBD
    

(Perhatikan bahwa simetri translasi tidak ikut berperan di sini.)

Keluarkan nilai palsu jika grid tidak memiliki salah satu simetri yang disebutkan di atas. contoh grid contoh pertama.

Kode terpendek dalam byte menang.

Hobi Calvin
sumber
Bisakah kita mengambil daftar empat string sebagai input?
Martin Ender
@ MartinEnder Ya, baiklah.
Calvin Hobi
4
Saya baru saja membaca itu dan berpikir "tidak" lol
Shaun Wild
Seandainya Anda berpikir untuk memasang kotak maka Anda bisa memperhitungkan simetri translasi juga.
Neil
1
@ Adám No. Tidak ada lagi format input. Kurasa aku seharusnya tidak mengizinkan Martin.
Calvin Hobbies

Jawaban:

16

CJam, 16 byte

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

Blok tanpa nama yang mengharapkan input sebagai daftar empat string di atas tumpukan dan meninggalkan 0(falsy) untuk input asimetris dan integer positif (benar) untuk input simetris.

Uji di sini. Atau jalankan test suite lengkap.

Penjelasan

Simetri alun-alun adalah unsur-unsur dari kelompok dihedral orde 8 (yang hanya merupakan 4 rotasi persegi dan 4 rotasi yang sama dari beberapa versi kuadrat yang dipantulkan). Itu tidak mungkin untuk menghasilkan grup ini dari aplikasi berulang permutasi tunggal. Tetapi dua refleksi selalu memberikan rotasi. Oleh karena itu, seluruh kelompok dapat dihasilkan dengan bergantian antara dua refleksi empat kali. (Kita hanya perlu memastikan bahwa kedua pantulan memberikan rotasi 90 derajat atau 270 derajat, bukan 0 atau 180.)

Tantangannya bertanya apakah kotak input sama dengan salah satu dari 7 simetri lainnya. Jadi jawaban ini hanya menghasilkan semuanya dan kemudian memeriksa apakah inputnya ada di antara yang lain.

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

Untuk melihat bagaimana aplikasi berulang zdan W%menghasilkan semua simetri, lihat "diagram" ini:

     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
sumber
Wow, bisakah Anda menjelaskan ini? Apakah Anda memiliki built-in untuk semua rotasi / membalik?
Adám
@ Adám saya akan menambahkan penjelasan lengkap dalam sedikit, tetapi ztranspos dan W%membalikkan garis, jadi saya hanya membuat semua simetri dengan aplikasi berulang dari mereka.
Martin Ender
4
Tentu saja, tidak ada yang istimewa tentang nilai pertama, tetapi sayangnya pendekatan yang lebih murni untuk menghitung apakah Anda mendapatkan 8 nilai berbeda harganya lebih mahal.
Peter Taylor
8

Pyth, 11 byte

<7.u?%Y2CN_

Suite uji

Ini menggunakan teknik transpos dan balik Martin, tetapi dengan twist. Sementara solusi lain telah secara eksplisit menghasilkan semua 8 simetri, kemudian menghitung jumlah kemunculan aslinya, program ini menggunakan .ufungsi Pyth .

The .uFungsi adalah "Terapkan sampai berulang ditemukan". Dalam hal ini, kami secara bergantian memindahkan dan membalikkan hingga terjadi pengulangan, lalu mengakumulasikan hasilnya ke dalam daftar. Lalu, saya menghapus 7 nilai terakhir, jadi hanya akan ada nilai yang tersisa jika tidak ada simetri, dan pengulangan pertama terjadi setelah semua 8 refleksi dan pengulangan dihasilkan.

Penjelasan:

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

05AB1E , 13 byte

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

Penjelasan

Menggunakan metode yang secara ahli dijelaskan oleh Martin dalam jawaban CJam-nya .

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

Cobalah online

Emigna
sumber
4

Perl, 61 60 byte

Termasuk +3 untuk -p0a

Berikan kotak input pada STDIN, cetak 0 tanpa simetri, jika tidak bilangan positif

./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
sumber
4

Dyalog APL , 37 19 17 byte

@ ngn menguranginya hingga 20 byte!

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

TryAPL online!

Adm
sumber
⍉¨bukannya ⌽∘⍉¨bekerja juga.
ngn
@ ngn Selesai. Terima kasih. Sampai jumpa besok.
Adám
3

Brachylog , 38 36 byte

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

Cobalah online!

Ini mengharapkan daftar string sebagai input. Ini mencetak salah satu true.atau false..

Penjelasan

  • Predikat utama:

    @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
    
  • Predikat 1: Output adalah salah satu dari 8 simetri 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
    )
    
Fatalisasi
sumber
3

TSQL, 229 byte

Sadarilah TSQL tidak memiliki built-in untuk memutar, jadi ini termasuk dalam kode.

Golf:

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

Tidak Disatukan:

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

Biola

t-clausen.dk
sumber
2

Python 2, 154 146 byte

Cek apakah ada transformasi yang diperlukan setara dengan yang asli menggunakan array numpy. Input diambil sebagai daftar empat string.

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

Cobalah online

Mengambil input sebagai string tunggal lebih lama, dengan A=array(list(input())).reshape(4,4). A[:,::-1]sama dengan fliplr(A). A[::-1]sama dengan flipud(A).

mbomb007
sumber
Mungkin gunakan map(list,input())sebagai ganti[list(r)for r in input()]
Cyoce
@Cyoce Terima kasih. Idk betapa aku merindukan itu.
mbomb007
anymengambil ekspresi generator, sehingga Anda dapat menghemat beberapa byte dengan menjatuhkan pasangan terluar kurung.
TheBikingViking
@ TheBikingViking Saya sudah mencobanya. Jika Anda melewati generator, maka generator akan kembali, membuat printpernyataan tidak berfungsi. Coba forking kode online saya dan jalankan dengan cara itu untuk melihat.
mbomb007
Ah, baiklah. Saya tidak menyadari bahwa itu akan merusak 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

Fungsi yang mengambil input, melalui argumen, daftar string dan kembali Trueatau yang Falserelevan.

Ini menggunakan pendekatan yang sama dengan jawaban @ MartinEnder .

Bagaimana itu bekerja

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

Cobalah di Ideone

TheBikingViking
sumber
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 dapat dihapus jika Anda melewatkan array 4 string secara langsung. Saya mencoba bit-twiddling (input dalam "0123301223011230"format) tetapi saya butuh 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)
Neil
sumber