Перевірте, чи можуть три букви утворювати "куб Годель-Ешер-Баха"


29

Це питання натхнене обкладинкою книги "Годель, Ешер, Бах":

Завдання тут полягає в тому, щоб написати функцію, яка визначає, чи можуть три задані букви створити 3D-скульптуру, яку можна прочитати з трьох сторін.

Для цієї вправи можна використовувати лише букви 26 5px * 5px:

Або у двійковій формі (від A до Z):

01110  11110  01111  11110  11111  11111  11111  10001  11111  11111  10001  10000  10001  10001  01110  11110  01110  11110  01111  11111  10001  10001  10001  10001  10001  11111
10001  10001  10000  10001  10000  10000  10000  10001  00100  00100  10010  10000  11011  11001  10001  10001  10001  10001  10000  00100  10001  10001  10001  01010  01010  00010
10001  11110  10000  10001  11100  11110  10011  11111  00100  00100  11100  10000  10101  10101  10001  10001  10001  11111  01110  00100  10001  01010  10001  00100  00100  00100
11111  10001  10000  10001  10000  10000  10001  10001  00100  10100  10010  10000  10001  10011  10001  11110  10011  10010  00001  00100  10001  01010  10101  01010  00100  01000
10001  11110  01111  11110  11111  10000  11111  10001  11111  11100  10001  11111  10001  10001  01110  10000  01111  10001  11110  00100  01110  00100  01010  10001  00100  11111

Скульптура утворена трьома літерами у такому порядку:

  • лист один зверху,
  • літеру два зліва
  • літера три справа
  • нижня частина літери одна прив’язана до верхньої частини другої літери.

Приклад:

Ваша функція може приймати як введення три великі літери (три символи або три рядки однієї літери) та виводити булеву (справжню / помилкову або 0/1), що повідомляє, чи може існувати відповідна скульптура.

Приклад:

f("B","E","G") // true  (because if you "sculpt out" B on top + E on the left + G on the right, and watch the three sides of the sculpture, you'll see exactly B, E and G as they are defined)
f("B","G","E") // false (because if you "sculpt out" B on top + G on the left + E on the right, and watch the three sides of the sculpture, you won't see a complete G and a complete E. Their shapes bother each other)

Примітка: ви можете повернути справжнє, навіть якщо скульптура містить "літаючі пікселі" (кубики або група кубів, які не прикріплені до нічого).

Застосовуються стандартні лазівки.

Точніше, ви не можете використовувати зовнішній вхід, крім трьох букв, і не можете жорстко кодувати 17576 можливих відповідей у ​​своєму вихідному коді

Найкоротша відповідь символами будь-якої мови виграє!

Приємно :)



Так, саме загадка MU змусила мене відкрити книгу, і саме обкладинка книги змусила мене задуматися над цим викликом. Є проблема? Це була частина вашої 18 дірок?
xem

2
Було б хорошим варіантом замінити отвір 1.;) ... Не забувайте, якщо що-небудь я винен, що щось раніше не встаю. Це дійсно гідний виклик, +1!
Мартін Ендер

Чи можемо ми отримати дані, що визначають форми літер із зовнішнього файлу, чи це також потрібно включити до джерела?
CesiumLifeJacket

Ваш бінарний B має 0 у верхньому лівому куті, а не 1.
Захоплення Кальвіна

Відповіді:


13

Mathematica 423

Я додав розділ під назвою "Як працює блокування".

Безумовно

(* Двійкові дані алфавіту зберігаються як один рядок в s. varsІмпортує його та перетворює у масив.)

vars=IntegerDigits[#,10,5]&/@Transpose[ImportString[s,"Table"]];
get[char_]:=(ToCharacterCode[char]-64)[[1]];
cube=Flatten[Table[{i,j,k},{i,5},{j,5},{k,5}],2];

(* character slice along axis *)
slice[char_,layer_,axis_,bit_]:=Insert[(Reverse@#),layer,axis]&/@Position[Reverse@vars[[get[char]]],bit]

(* cuboid assembly  *)
charBlocks[{char_,axis_,bit_}]:=Flatten[Table[slice[char,k,axis,bit],{k,5}],1]

(* letters are those whose HOLES should be sculped out of the full cube *)
sculpturePoints[letters_(*{char_,axis_,bit_}*)]:=Complement[cube,Union[Join@@(charBlocks/@letters(*{char,axis,bit}*))]];

collapse[letters_(*{char_,axis_,bit_}*),axis_]:=Union[Reverse/@(Delete[#,axis]&/@sculpturePoints[letters(*{char,axis,bit}*)])](*/.{x_,y_}\[RuleDelayed] {6-x,y}*)

vQ[l_]:=collapse[l,3]==collapse[{l[[1]]},3]\[And]collapse[l,2]==collapse[{l[[2]]},2]\[And]collapse[l,1]==collapse[{l[[3]]},1]

validQ@l_:= vQ[{{l[[1]],3,0},{l[[2]],2,0},{l[[3]],1,0}}]


perspective[letts_,view_:1]:=
Graphics3D[{AbsolutePointSize[10],Cuboid/@sculpturePoints[letts]},
ImageSize-> 120,
ViewPoint-> Switch[view,1,{0,0,\[Infinity]},2,{0,-\[Infinity],0},3,{\[Infinity],0,0},4,Top,5,Front,6,Right,True,{0,0,\[Infinity]}],
PlotLabel-> Switch[view,1,"top orthogonal view",2,"front orthogonal view",3,"right orthogonal view",4,"top close-up view",5,"front close-up view",6,"right close-up view"],
ImagePadding->10]

Приклад

Чи куб {"B", "G", "E"}дійсний? (тобто чи правильно надрукуються три літери на стіни?)

validQ[{"B", "G", "E"}]

помилковий

Ілюстрації

На малюнках нижче показано, як відображається BGE. Верхній ряд фігур займає ортогональну перспективу, ніби глядач розміщувався на нескінченній відстані від куба. У нижньому рядку показано, як будуть виглядати блоки зблизька. 3D-фігури можна обертати вручну, щоб точно оглянути місце розташування окремих кубів одиниці.

Проблема виникає з літерою "G". Немає нічого, що з'єднує сериф з рештою листа.

pts = {{"B", 3, 0}, {"G", 2, 0}, {"E", 1, 0}}
GraphicsGrid@Partition[Table[perspective[pts, view], {view, 1, 6}], 3]

bge


BEG, однак, повинен працювати добре.

 validQ[{"B", "E", "G"}]

Правда

pts2 = {{"B", 3, 0}, {"E", 2, 0}, {"G", 1, 0}}
GraphicsGrid@Partition[Table[perspective[pts2, view], {view, 1, 6}], 3]

просити


Як працює блокування?

Вибачте, будь ласка, якщо це здається очевидним, але, можливо, деякі люди захочуть уявити, як літери перешкоджають одне одному, скасовуючи свої 3D-пікселі.

Давайте слідкуємо за тим, що відбувається з буквою G у візуалізації куба BGE.

Ми звернемо особливу увагу на воксель (3D-піксель або куб одиниці) нижче. Це піксель, який зникає в кубі BGE. Це піксель, відповідний рядку 4, стовпцю 5 в бітовому масиві та відповідному графіку масиву.

блокування 1


У площині xy піксель відповідає сірому диску в точці (5,2). Але оскільки ми будемо працювати в 3D, нам потрібно врахувати 5 положень у валу від (5,1,2) до (5,5,2). Якщо будь-який з цих пікселів витримає ліплення літер B і E, ми зможемо побачити піксель, що цікавить, у 3D-проекції на стіні.

блокування 2


Букви втручаються, коли пікселі виймаються із суцільного блоку. У лівій частині чорна стрілка зображує різьблення з пікселів, відповідне біту в нижній правій частині; воно має значення 0 для букви В. Вирізання з пікселя видаляє піксель у (5,1,2), а також значення прямо над і під ним. Залишається врахувати чотири пікселі.

блокування 3

Але, як показано на правій панелі, буква Е ліпить решта пікселів, що цікавлять, (5,2,2) (5,3,2), (5,4,2) та (5,5,2). (Це пов'язано з тим, що літера E має біти, рівні 0 в четвертому ряду, від стовпця 2 до стовпця 5.) В результаті жоден піксель не залишається серед тих, які були потрібні для забезпечення відтінку в точці (5 , 2) на дальній стіні (для літери G). Натомість з’явиться яскрава пляма, відповідне отвору в букві G! Кубік BGE не корисний, оскільки він неправильно видає G.

Полювали 423 символи

Функція hвиконувала ту саму роль, що і validQв коді unGolfed. Функція візуалізації, perspectiveне включена, оскільки вона не сприяє і не вимагає виклику.

x=Reverse;q=Flatten;
g@c_:=(ToCharacterCode[c]-64)[[1]];
r[{c_,a_,b_}]:=q[Table[Insert[(x@#),k,a]&/@Position[x@(IntegerDigits[#,10,5]&/@
Transpose[ImportString[s,"Table"]])[[g[c]]],b],{k,5}],1]
p@l_:=Complement[q[Table[{i,j,k},{i,5},{j,5},{k,5}],2],Union[Join@@(r/@l)]];
w[l_,a_]:=Union[x/@(Delete[#,a]&/@p[l])]
v@l_:=w[l,3]==w[{l[[1]]},3]\[And]w[l,2]==w[{l[[2]]},2]\[And]w[l,1]==w[{l[[3]]},1]

h@l_:= v[{{l[[1]],3,0},{l[[2]],2,0},{l[[3]],1,0}}]

Вау, ці 3D-зображення дуже акуратні! Ви впевнені, що останній блок коду - "UnGolfed"? Мені здається, гольф. :)
xem

Ви праві. Заключний блок - це гольф. Я виправив заголовок. Хороша річ у 3D-переглядах - це те, що вони інтерактивні: обертання та масштабування можна робити мишею.
DavidC

До речі, по моєму підрахунку, серед 15600 можливих перестановок є 564 дійсних кубів.
DavidC

Це приємна інформація. Скільки часу вам знадобилося обчислити це? також, 26 * 26 * 26 = 17576, а не 15600. Або я щось пропускаю?
xem

Я використовував перестановки, а не кортежі; тобто немає повторних листів. 26 * 25 * 24 = 15600. Щоб знайти 564 справи, знадобилося 21 секунда.
DavidC

12

Пролог, 440 , 414

:- encoding(utf8).
i(I) :- between(0,4,I).
h(T,L,R,X,Y,Z) :- i(X),i(Y),i(Z),I is 4-X,c(T,Z,I),c(L,Z,Y),c(R,X,Y).
f(T,L,R) :- forall((i(U),i(V),I is 4-V),((\+c(T,U,V);h(T,L,R,I,Y,U)),(\+c(L,U,V);h(T,L,R,X,V,U)),(\+c(R,U,V);h(T,L,R,U,V,Z)))).
c(C,X,Y) :- char_code(C,N),i(X),i(Y),Z is X+5*Y+25*(N-65),I is floor(Z/15),O is (Z mod 15),string_code(I,"䙎㹟䘑߯硁䙏縑ԁࠟя摟䠑䠑ᐑ粤Ⴟ䔅┉ё籁垑䙑曓䗱㩑䙏㡏晑䘞䕟㡞縐Ⴄ䙄㩑⩑䒪噑⩊䕤ᅱ粤ࢨ?",V),1 is (V-32)>>O/\1.

Програма називається так:

?- f('B','E','G').
true.
?- f('B','G','E').
false.

Prologздавалося, вдалий вибір, оскільки проблему представляти проблему логікою першого порядку легко. Також Prologнадається потужна функціональність для вирішення подібної проблеми.

Однак, оскільки код гольф, я думаю, я повинен додати деякі пояснення.

Легка версія для гольфу

:- encoding(utf8).
i(I) :- between(0,4,I).
t(C,X,Z) :- I is 4-X,c(C,Z,I).
l(C,Y,Z) :- c(C,Z,Y).
r(C,X,Y) :- c(C,X,Y).
h(T,L,R,X,Y,Z) :- i(X),i(Y),i(Z),t(T,X,Z),l(L,Y,Z),r(R,X,Y).
u(T,L,R) :- forall((i(U),i(V),I is 4-V,c(T,U,V)),h(T,L,R,I,Y,U)).
v(T,L,R) :- forall((i(U),i(V),c(L,U,V)),h(T,L,R,X,V,U)).
w(T,L,R) :- forall((i(U),i(V),c(R,U,V)),h(T,L,R,U,V,Z)).
f(T,L,R) :- u(T,L,R),v(T,L,R),w(T,L,R).
c(C,X,Y) :- char_code(C,N),i(X),i(Y),Z is X+5*Y+25*(N-65),I is floor(Z/15),O is (Z mod 15),string_code(I,"䙎㹟䘑߯硁䙏縑ԁࠟя摟䠑䠑ᐑ粤Ⴟ䔅┉ё籁垑䙑曓䗱㩑䙏㡏晑䘞䕟㡞縐Ⴄ䙄㩑⩑䒪噑⩊䕤ᅱ粤ࢨ?",V),1 is (V-32)>>O/\1.

Координати, відповідні пікселям на кожній стороні кістки, можна легко перетворити в тривимірну систему координат. Я використовую T, Lі Rдля верхньої частини (1), вліво (2) і вправо (3) сторони. uі vвикористовуються для координат на зображеннях:

  • T :(u,v) -> (4-v, ?, u)
  • L :(u,v) -> (?, v, u)
  • R :(u,v) -> (u, v, ?)

Результати для кожного активного (тобто чорного) пікселя поєднуються з набором "3D-пікселів", які можна активувати, не змінюючи виду об'єкта з цієї сторони. Перетин наборів для кожної сторони - це всі 3D-пікселі, які можна активувати без додавання пікселів, що перешкоджатиме перегляду (тобто, дивлячись щонайменше на одну сторону, не буде пікселя, якого там не повинно бути).

Залишилося лише перевірити для кожної сторони, чи є в перехресті піксель, який блокує подання, де це необхідно.

Це призводить до предикатів у програмі:

  • f : робить остаточну перевірку; бере букви у верхній, лівій і правій частині
  • u , v і w : зробіть перевірки, якщо для кожного пікселя, який є активним збоку, в перетині є 3D-піксель, який блокує вигляд
  • h : перевірки на наявність пікселя в перетині
  • t , l , r : перевіряє, чи можна блокувати 3D-піксель у верхній, лівій та правій частині.
  • c : перевірка на піксель у зображенні букви. Рядок там може виглядати дещо дивним, але це лише компактний спосіб зберігання даних зображення. Це просто послідовність символів із наступними значеннями (шістнадцяткова нотація):

    [464e,3e5f,4611,7ef,7841,464f,7e11,501,81f,44f,645f,4811,4811,1411,7ca4,10bf,4505,2509,451,7c41,5791,4651,66d3,45f1,3a51,464f,384f,6651,461e,455f,385e,7e10,10a4,4644,3a51,2a51,44aa,5651,2a4a,4564,1171,7ca4,8a8,3f]
    

    Кожен з цих символів зберігає дані для 3-х піксельних рядків у зображеннях літер (= 15 пікселів). Пікселі також упорядковуються так, що дані зберігаються в одному місці та не поділяються на кілька рядків, як дані ОП.

Математична постановка

формула

Вхідні дані

формула

Перетворення з пікселя в одному графі в набір 3D-пікселів, які перешкоджають перегляду цього пікселя

формула

формула

формула

Пікселі, які можна безпечно додавати (не перешкоджаючи перегляду в неправильному місці)

формула

Кожна сторона перевіряє, що пікселі, які потрібно перешкодити, можуть бути безпечно перешкоджені

формула

формула

формула

Поєднання чеків для кожної сторони

формула


1
Я .. Ага .. Що? Я вважаю це незрозумілим. (+1)
seequ

Святий ... Я лягаю спати ...
BrunoJ

Вражає! Дякую за цю відповідь
xem

1
Приємно. btw, я думаю, що процес починається з міцного кубічного блоку. (Ви, здається, вважаєте це додаванням пікселів, де раніше не було жодного.) Кожен лист видаляє з цього блоку деякі три пікселі. Отже, втручання виникає, коли сусідня літера видаляє пікселі, які буква "хотіла зберегти". Інтерференція випливає із "відсутніх пікселів", а не із зайвих пікселів.
DavidC

9

J - 223 197 191 char

Функція, яка бере аргумент трьох списку знаків.

(_5#:\".'1b',"#:'fiiifalllvhhhheehhhvhhllvgkkkvnlhhvv444vhhvhhggvhjha44v1111vv848vv248vehhheciiivfjhhedmkkvilll9ggvggu111uo616ou121uha4ahg878ghpljh')((-:0<+/"1,+/"2,:+/)*`(*"1/)/)@:{~_65+3&u:

Цей гольф багато в чому покладається на потужну особливість J, яку називають рангом , яка дає нам операції "ліпити" та "спостерігати" майже безкоштовно. Щоб трохи спростити його, ранг позначає розмірність іменника або природні аргументи дієслова.

J має багатовимірні масиви, і очевидно, що, скажімо, 3D-масив можна інтерпретувати як єдиний 3D-масив, або як список матриць, або 2D-масив векторів, або 3D-масив скалярів. Таким чином, кожна операція в J може контролювати додаток wrt, як поширюватись на аргумент. Ранг 0 означає застосувати на скалярах, ранг 1 означає застосувати на вектори тощо.

   1 + 2 + 3 + 4  NB. add these things together
10
   +/ 1 2 3 4     NB. sum the list by adding its items together
10
   i. 3 4         NB. 2D array, with shape 3-by-4
0 1  2  3
4 5  6  7
8 9 10 11
   +/"2 i. 3 4    NB. add the items of the matrix together
12 15 18 21
   0 1 2 3 + 4 5 6 7 + 8 9 10 11    NB. equivalent
12 15 18 21
   +/"1 i. 3 4    NB. now sum each vector!
6 22 38
   +/"0 i. 3 4    NB. now sum each scalar!
0 1  2  3
4 5  6  7
8 9 10 11

Це стає дуже потужним, коли ви вводите діадичні (двоаргументаційні) функції, тому що, якщо форми двох аргументів (після обліку ранжування) є придатними, J зробить певну циклічну циклічність:

   10 + 1             NB. scalar addition
11
   10 20 30 + 4 5 6   NB. vector addition, pointwise
14 25 36
   10 + 4 5 6         NB. looping! 
14 15 16
   10 20 + 4 5 6      NB. shapes do not agree...
|length error
|   10 20    +4 5 6

Коли всі ваші форми приємні і ви можете самі вказати ранг, існує багато способів поєднати аргументи. Тут ми демонструємо деякі способи, як можна множити 2D-матрицю та 3D-масив.

   n =: i. 5 5
   n
 0  1  2  3  4
 5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
   <"2 n *"2 (5 5 5 $ 1)  NB. multiply by 2-cells
+--------------+--------------+--------------+--------------+--------------+
| 0  1  2  3  4| 0  1  2  3  4| 0  1  2  3  4| 0  1  2  3  4| 0  1  2  3  4|
| 5  6  7  8  9| 5  6  7  8  9| 5  6  7  8  9| 5  6  7  8  9| 5  6  7  8  9|
|10 11 12 13 14|10 11 12 13 14|10 11 12 13 14|10 11 12 13 14|10 11 12 13 14|
|15 16 17 18 19|15 16 17 18 19|15 16 17 18 19|15 16 17 18 19|15 16 17 18 19|
|20 21 22 23 24|20 21 22 23 24|20 21 22 23 24|20 21 22 23 24|20 21 22 23 24|
+--------------+--------------+--------------+--------------+--------------+
   <"2 n *"1 (5 5 5 $ 1)  NB. multiply by vectors
+---------+---------+--------------+--------------+--------------+
|0 1 2 3 4|5 6 7 8 9|10 11 12 13 14|15 16 17 18 19|20 21 22 23 24|
|0 1 2 3 4|5 6 7 8 9|10 11 12 13 14|15 16 17 18 19|20 21 22 23 24|
|0 1 2 3 4|5 6 7 8 9|10 11 12 13 14|15 16 17 18 19|20 21 22 23 24|
|0 1 2 3 4|5 6 7 8 9|10 11 12 13 14|15 16 17 18 19|20 21 22 23 24|
|0 1 2 3 4|5 6 7 8 9|10 11 12 13 14|15 16 17 18 19|20 21 22 23 24|
+---------+---------+--------------+--------------+--------------+
   <"2 n *"0 (5 5 5 $ 1)  NB. multiply by scalars
+---------+---------+--------------+--------------+--------------+
|0 0 0 0 0|5 5 5 5 5|10 10 10 10 10|15 15 15 15 15|20 20 20 20 20|
|1 1 1 1 1|6 6 6 6 6|11 11 11 11 11|16 16 16 16 16|21 21 21 21 21|
|2 2 2 2 2|7 7 7 7 7|12 12 12 12 12|17 17 17 17 17|22 22 22 22 22|
|3 3 3 3 3|8 8 8 8 8|13 13 13 13 13|18 18 18 18 18|23 23 23 23 23|
|4 4 4 4 4|9 9 9 9 9|14 14 14 14 14|19 19 19 19 19|24 24 24 24 24|
+---------+---------+--------------+--------------+--------------+

Ви помітите, що це насправді не вирізняється літерами в орієнтації, про яке задається питання, воно просто записує їх, однак це зручно для логіки ранжування. Якщо ми не перевернемо або не обернемо букви, перш ніж їх застосувати, це не спрацює правильно. Але виправлення подібних речей зайняло б дорогоцінні символи, тому замість цього ми будемо кодувати літери такими, що, коли J вирізає їх природним чином, деякі трійки облич будуть знаходитись у правильних орієнтаціях та відносних положеннях. Виявляється, найкоротшим рішенням є обертання всіх форм листів на чверть обороту проти годинникової стрілки. Враховуючи третій вимір J для подання осі спереду та назад, на наведеній нижче схемі показано, чому ця схема працює.

візуалізація куба Малюнок A: Три сторони куба, в які вирізається J. Малюнок В: Три сторони, які мають літери, орієнтовані так, як задається питанням.

Цей вибір кодування заощаджує 12 символів порівняно з попереднім методом і робить це все більш акуратним. Справжній гольф створює кубик із"1 і "2вирізає з якоюсь дивною логікою, завдяки незв’язаній оптимізації.

Тоді ми повинні перевірити обличчя. Так як ми закодувати блок як 1 і 0, ми можемо просто підсумовувати уздовж кожної осі , як ми хочемо (вони є +/"1, +/"2і+/ бітами), пристосовуються до булевих ( 0<), а потім порівняти їх все безпосередньо до вихідних 90 ° - перевернуті літери.

Схема стиснення кодує кожен 5px рядок кожної літери як базове 32 представлення двійкового числа. Використовуючи ряд синтаксичних цукрів і перевантаження оператора, ".'1b',"#:це найкоротший спосіб перетворити список символів у базові 36 чисел. Ну, технічно, база 32, але Дж вважає, що це не є одинаковою, так хто ж рахує?

Використання нижче. Зауважте, що рядки - це масиви символів у J, тому три списки елементів 'A','B','C'можна записати 'ABC'коротко. Також булевими є 1/0.

   NB. can be used inline...
   (_5#:\".'1b',"#:'fiiifalllvhhhheehhhvhhllvgkkkvnlhhvv444vhhvhhggvhjha44v1111vv848vv248vehhheciiivfjhhedmkkvilll9ggvggu111uo616ou121uha4ahg878ghpljh')((-:0<+/"1,+/"2,:+/)*`(*"1/)/)@:{~_65+3&u:'BEG'
1
   NB. or assigned to a name
   geb=:(_5#:\".'1b',"#:'fiiifalllvhhhheehhhvhhllvgkkkvnlhhvv444vhhvhhggvhjha44v1111vv848vv248vehhheciiivfjhhedmkkvilll9ggvggu111uo616ou121uha4ahg878ghpljh')((-:0<+/"1,+/"2,:+/)*`(*"1/)/)@:{~_65+3&u:
   geb 'BGE'
0

4

Пітона, 687 682 671

import itertools as t,bz2
s=range(5)
c=dict([(i,1)for i in t.product(*3*[s])])
z=dict([(chr(i+65),[map(int,bz2.decompress('QlpoOTFBWSZTWXndUmsAATjYAGAQQABgADABGkAlPJU0GACEkjwP0TQlK9lxsG7aomrsbpyyosGdpR6HFVZM8bntihQctsSiOLrWKHHuO7ueAyiR6zRgxbMOLU2IQyhAEAdIJYB0ITlZwUqUlAzEylBsw41g9JyLx6RdFFDQEVJMBTQUcoH0DEPQ8hBhXBIYkXDmCF6E/F3JFOFCQed1Saw='.decode('base64')).split('\n')[j].split()[i])for j in s])for i in range(26)])
def m(a,g):
 for e in c:c[e]&=g[e[a]][e[a-2]]
def f(a):
 g=map(list,[[0]*5]*5)
 for e in c:g[e[a]][e[a-2]]|=c[e]
 return g
r=lambda g:map(list,zip(*g)[::-1])
def v(T,L,R):T,L,R=r(r(z[T])),r(z[L]),z[R];m(1,T);m(2,L);m(0,R);return(T,L,R)==(f(1),f(2),f(0))

Телефонуйте за допомогою v:

v('B','E','G') => True
v('B','G','E') => False

Все, що нижче, - з моєї попередньої версії, що не має волі, яка включає корисні функції малювання. Не соромтеся використовувати його як точку стрибка.

import string as s
import itertools as t

az = """01110  11110  01111  11110  11111  11111  11111  10001  11111  11111  10001  10000  10001  10001  01110  11110  01110  11110  01111  11111  10001  10001  10001  10001  10001  11111
10001  10001  10000  10001  10000  10000  10000  10001  00100  00100  10010  10000  11011  11001  10001  10001  10001  10001  10000  00100  10001  10001  10001  01010  01010  00010
10001  11110  10000  10001  11100  11110  10011  11111  00100  00100  11100  10000  10101  10101  10001  10001  10001  11111  01110  00100  10001  01010  10001  00100  00100  00100
11111  10001  10000  10001  10000  10000  10001  10001  00100  10100  10010  10000  10001  10011  10001  11110  10011  10010  00001  00100  10001  01010  10101  01010  00100  01000
10001  11110  01111  11110  11111  10000  11111  10001  11111  11100  10001  11111  10001  10001  01110  10000  01111  10001  11110  00100  01110  00100  01010  10001  00100  11111""".split('\n')

dim = range(len(az))
az = dict([(c, [map(int, az[j].split()[i]) for j in dim]) for i, c in enumerate(s.uppercase)])
cube = dict([(i, 1) for i in t.product(*3*[dim])])

def mask(axis, grid):
    for c in cube:
        if not grid[c[axis]][c[axis - 2]]:
            cube[c] = 0

def face(axis):
    grid = [[0 for j in dim] for i in dim]
    for c in cube:
        if cube[c]:
            grid[c[axis]][c[axis - 2]] = 1
    return grid

def rot(grid):
    return map(list, zip(*grid)[::-1])

def draw(grid, filled='X', empty=' '):
    s = ''
    for y in dim:
        for x in dim:
            s += filled if grid[y][x] else empty
        s += '\n'
    print s

def drawAll():
    print 'TOP:\n'
    draw(rot(rot(face(1))))
    print 'LEFT:\n'
    draw(rot(rot(rot(face(2)))))
    print 'RIGHT:\n'
    draw(face(0))

def valid(top, left, right):
    top, left, right = rot(rot(az[top])), rot(az[left]), az[right]
    mask(1, top)
    mask(2, left)
    mask(0, right)
    return top == face(1)and left == face(2) and right == face(0)

letters = 'BEG'

if valid(*letters):
    print letters, 'is valid.\n'
else:
    print letters, 'is not valid!\n'

drawAll()

Зателефонуйте, validщоб запустити його:

valid('B', 'E', 'G') #returns True
valid('B', 'G', 'E') #returns False

Зараз код налаштовано для перевірки дійсності B E Gта роздрукування отриманих граней:

BEG is valid.

TOP:

XXXX 
X   X
XXXX 
X   X
XXXX 

LEFT:

XXXXX
X    
XXX  
X    
XXXXX

RIGHT:

XXXXX
X    
X  XX
X   X
XXXXX

Запустивши його, B G Eми можемо побачити, що G неправильний:

BGE is not valid!

TOP:

XXXX 
X   X
XXXX 
X   X
XXXX 

LEFT:

XXXXX
X    
X  XX
X    
XXXXX

RIGHT:

XXXXX
X    
XXX  
X    
XXXXX

вау, хороша робота! +1 для малюванняВсі та повноти відповіді. +1 за використання такого короткого алгоритму. <3 це
xem

@xem Дякую! Я нарешті пограв у нього. Хоча я не міг зрозуміти, як змусити bz2 розпаковувати символи unicode.
Захоплення Кальвіна

+1. Гарна відповідь. Сподіваюсь, що більше людей будуть підтримувати гольфи, які складаються з менших гольфів, як це, адже це дійсно потребує зусиль.
Векторизований

1
g=[[0 for j in s]for i in s]можна скоротити до g=map(list,[[0]*5]*5). Крім того, ви можете уникнути відступи блоків , якщо вони одна заява: if c[e]:g[e[a]][e[a-2]]=1.
Бакуріу

@Bakuriu та bitpwner, дякую за пропозиції та зміни :)
Захоплення Calvin's

1

Python 3 + numpy, 327C

from numpy import*
B=hstack([ord(x)>>i&1for x in'옮弟ჹ羂옱쏷)ជ࿂︹缘龌ℿ쓥剴ℌᾄ起츱ꎚㆋឺ௣옮忬⧼ﯠႄ挒⺌ꕆ豈ꪱ袨冊䈑∾Ϣ'for i in range(16)])[:-6].reshape(26,5,5)
T=transpose
def f(*X):
 A=ones((5,5,5));F=list(zip([A,T(A,(1,0,2)),T(fliplr(A),(2,0,1))],[B[ord(x)-65]for x in X]))
 for r,f in F:r[array([f]*5)==0]=0
 return all([all(r.sum(0)>=f)for r,f in F])

Це рішення для гольфу потребує зовнішньої бібліотеки, нуме, яка досить популярна, тому я вважаю, що це нормально.

Рядок unicode знаходиться в 41 символі, тоді як те саме у відповіді прологів @ fabian - 44.

Найцікавішим тут є те, що індексація масиву numpy. В a[ix], ixможе бути булевим масивом тієї ж форми, що і a. Це те саме, що говоритиa[i, j, k] where ix[i, j, k] == True .

Безгольова версія

import numpy as np
table = '옮弟ჹ羂옱쏷)ជ࿂︹缘龌ℿ쓥剴ℌᾄ起츱ꎚㆋឺ௣옮忬⧼ﯠႄ挒⺌ꕆ豈ꪱ袨冊䈑∾Ϣ'

def expand_bits(x):
    return [ord(x) >> i & 1 for i in range(16)]

# B.shape = (26, 5, 5), B[i] is the letter image matrix of the i(th) char
B = np.hstack([expand_bits(x) for x in table])[:-6].reshape(26, 5, 5)

def f(*chars):
    """
    cube:    ----------   axis:           
            /         /|      --------->2  
           /   1     / |     /|            
          /         /  |    / |            
         /         /   |   /  |            
        |---------|  3 |  v   |           
        |         |    /  1   |           
        |    2    |   /       v          
        |         |  /        0         
        |         | /                  
        -----------
    """
    cube = np.ones((5, 5, 5))
    cube_views = [
        cube,
        cube.transpose((1, 0, 2)),  # rotate to make face 2 as face 1
        np.fliplr(cube).transpose(2, 0, 1),  # rotate to make face 3 as face 1
    ]
    faces = [B[ord(char) - ord('A')] for char in chars]
    # mark all white pixels as 0 in cube
    for cube_view, face in zip(cube_views, faces):
        # extrude face to create extractor
        extractor = np.array([face] * 5)
        cube_view[extractor == 0] = 0

    return np.all([
        # cube_view.sum(0): sum along the first axis
        np.all(cube_view.sum(0) >= face)
        for cube_view, face in zip(cube_views, faces)
    ])

Сценарій для стиснення таблиці

import numpy as np

def make_chars():
    s = """
01110  11110  01111  11110  11111  11111  11111  10001  11111  11111  10001  10000  10001  10001  01110  11110  01110  11110  01111  11111  10001  10001  10001  10001  10001  11111
10001  10001  10000  10001  10000  10000  10000  10001  00100  00100  10010  10000  11011  11001  10001  10001  10001  10001  10000  00100  10001  10001  10001  01010  01010  00010
10001  11110  10000  10001  11100  11110  10011  11111  00100  00100  11100  10000  10101  10101  10001  10001  10001  11111  01110  00100  10001  01010  10001  00100  00100  00100
11111  10001  10000  10001  10000  10000  10001  10001  00100  10100  10010  10000  10001  10011  10001  11110  10011  10010  00001  00100  10001  01010  10101  01010  00100  01000
10001  11110  01111  11110  11111  10000  11111  10001  11111  11100  10001  11111  10001  10001  01110  10000  01111  10001  11110  00100  01110  00100  01010  10001  00100  11111
""".strip().split('\n')
    bits = np.zeros((26, 5, 5), dtype=np.bool)
    for c_id in range(26):
        for i in range(5):
            for j in range(5):
                bits[c_id, i, j] = s[i][j + c_id * 7] == '1'
    bits = np.hstack([bits.flat, [0] * 7])
    bytes_ = bytearray()
    for i in range(0, len(bits) - 8, 8):
        x = 0
        for j in range(8):
            x |= bits[i + j] << j
        bytes_.append(x)
    chars = bytes_.decode('utf16')
    return chars
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.