Чи симетричний цей квадрат?


22

Напишіть програму або функцію, яка містить текстову сітку розміром 4 × 4, що складається з точно 4 A-х, 4 B-х, 4 C-х та 4 D-х, таких як:

ACDC
BBCA
BADD
ABCD

Вони ABCDможуть бути в будь-якій домовленості, але завжди їх буде 4. Ви можете припустити, що введення дійсне. За бажанням ви також можете припустити, що у нього є зворотний новий рядок та / або що він є одним рядком у порядку читання, наприклад ACDCBBCABADDABCD. Ви також можете замінити символи ABCDна 0123або, 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
Я щойно прочитав це і подумав "nope" lol
Shaun Wild

Якби ви думали плистити площу, тоді ви могли б також врахувати поступальну симетрію.
Ніл

1
@ Adám Ні. Більше не вводиться форматів введення. Я відчуваю, що насправді не мав би дозволити Мартіну.
Захоплення Кальвіна

Відповіді:


16

CJam, 16 байт

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

Неназваний блок, який очікує на введення як список із чотирьох рядків на вершині стека і залишає 0(фальш) для асиметричних входів та додатне ціле число (truthy) для симетричних входів.

Перевірте це тут. Або запустити повний тестовий набір.

Пояснення

Симетрії квадрата є елементами двогранної групи порядку 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

Вау, ви можете це пояснити? У вас є вбудований для всіх обертів / обертів?
Адам

@ Adám Я трохи додам повне пояснення, але zпереміщую та W%обертаю рядки, тому я просто генерую всі симетрії повторним застосуванням їх.
Мартін Ендер

4
Звичайно, немає нічого особливого в першому значенні, але, на жаль, більш пуристський підхід підрахунку того, чи отримаєте ви 8 різних значень, коштує на одну таблицю більше.
Пітер Тейлор

8

Pyth, 11 байт

<7.u?%Y2CN_

Тестовий набір

Для цього використовується техніка транспонування та зворотного руху Мартіна, але з поворотом. Хоча інші рішення явно генерували всі 8 симетрій, а потім підраховували кількість появи оригіналу, ця програма використовує функцію Pyth .u.

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


4

Перл, 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

Брахілог , 38 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

Пітон 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

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

Функція, яка приймає через аргумент введення списку рядків і повертає TrueабоFalse як відповідна.

Для цього використовується той же підхід, що і у відповіді @ 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)

17 байт можна було б видалити, якщо передати масив із 4 рядків безпосередньо. Я спробував біт-подвійність (введення у "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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.