Sprawdź, czy trzy litery mogą tworzyć „sześcian Godela-Eschera-Bacha”

29

To pytanie jest inspirowane okładką książki „Godel, Escher, Bach”:

Wyzwanie polega na napisaniu funkcji, która mówi, czy trzy podane litery mogą wytworzyć rzeźbę 3D, którą można odczytać z trzech stron.

W tym ćwiczeniu jedynymi literami, których możesz użyć, są 26 bitmap * 5 pikseli * 5 pikseli:

Lub binarnie (od A do 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

Rzeźba składa się z trzech liter w następującej kolejności:

  • litera pierwsza na górze,
  • litera druga po lewej
  • litera trzecia po prawej
  • dolna część litery pierwszej jest związana z górą litery drugiej.

Przykład:

Twoja funkcja może przyjąć jako dane wejściowe trzy wielkie litery (trzy znaki lub trzy ciągi jednej litery) i wygenerować wartość logiczną (prawda / fałsz lub 0/1) informującą, czy odpowiednia rzeźba może istnieć.

Przykład:

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)

Uwaga: możesz zwrócić prawdę, nawet jeśli rzeźba zawiera „latające piksele” (kostki lub grupy kostek, które są przymocowane do niczego).

Obowiązują standardowe luki.

Mówiąc dokładniej, nie możesz używać zewnętrznych danych wejściowych poza trzema literami i nie możesz zakodować 17576 możliwych odpowiedzi w kodzie źródłowym

Najkrótsza odpowiedź w postaci w dowolnym języku wygrywa!

Baw się dobrze :)

Xem
źródło
Tak, to układanka MU sprawiła, że ​​odkryłem książkę, a okładka książki sprawiła, że ​​pomyślałem o tym wyzwaniu. Jest jakiś problem? Czy to była część twojej 18-dołkowej rzeczy?
xem
2
Byłoby dobrą opcją zastąpienia otworu 1.;) ... Nieważne, jeśli cokolwiek, to moja wina, że ​​nie wstałem wcześniej. To naprawdę przyzwoite wyzwanie, +1!
Martin Ender
Czy możemy pobrać dane określające kształty liter z zewnętrznego pliku, czy też należy to uwzględnić w źródle?
CesiumLifeJacket
Twoje binarne B ma wartość 0 w lewym górnym rogu, a nie 1.
Hobby Calvina

Odpowiedzi:

13

Mathematica 423

Dodałem sekcję „Jak działa blokowanie”.

Nie golfił

(* Dane binarne alfabetu są przechowywane jako pojedynczy ciąg znaków w s. varsImportuje je i konwertuje na tablicę.)

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]

Przykład

Czy kostka jest {"B", "G", "E"}ważna? (tj. czy trzy litery będą poprawnie rzutować na ściany?)

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

Fałszywe

Ilustracje

Poniższe liczby pokazują, w jaki sposób renderowany jest BGE. Górny rząd figur przyjmuje perspektywy ortogonalne, tak jakby widz znajdował się w nieskończonej odległości od sześcianu. Dolny rząd pokazuje, jak bloki wyglądałyby z bliska. Figury 3D można ręcznie obracać, aby dokładnie sprawdzić, gdzie są rozmieszczone poszczególne kostki jednostek.

Wystąpił problem z literą „G”. Nic nie łączy szeryfa z resztą listu.

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

bge


BEG powinno jednak działać dobrze.

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

Prawdziwe

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

błagać


Jak działa blokowanie?

Przepraszam, jeśli wydaje się to oczywiste, ale być może niektórzy ludzie będą chcieli wyobrazić sobie, w jaki sposób litery kolidują ze sobą, anulując ich piksele 3D.

Zobaczmy, co stanie się z literą G w renderowaniu kostki BGE.

Zwrócimy szczególną uwagę na woksel (piksel 3D lub sześcian jednostkowy) poniżej. To piksel, który znika w sześcianie BGE. Jest to piksel odpowiadający wierszowi 4, kolumnie 5 w tablicy bitów i na odpowiednim wykresie tablicy.

blokowanie 1


W płaszczyźnie xy piksel odpowiada szaremu dyskowi w punkcie (5,2). Ponieważ jednak zamierzamy pracować w 3D, musimy rozważyć 5 pozycji w wale od (5,1,2) do (5,5,2). Jeśli któryś z tych pikseli przetrwa rzeźbienie za pomocą liter B i E, będziemy mogli zobaczyć interesujący piksel w projekcji 3D na ścianie.

blokowanie 2


Litery przeszkadzają, gdy piksele są usuwane z bryły. Czarna strzałka po lewej stronie przedstawia wycinanie pikseli, odpowiadające bitowi w prawym dolnym rogu; ma wartość 0 dla litery B. Wycięcie usuwa piksel w punkcie (5,1,2) wraz z tymi znajdującymi się bezpośrednio nad i pod nim. Należy uwzględnić cztery piksele.

blokowanie 3

Ale jak pokazuje prawy panel, litera E przedstawia pozostałe interesujące piksele, (5,2,2) (5,3,2), (5,4,2) i (5,5,2). (Wynika to z faktu, że litera E ma bity równe 0 w czwartym rzędzie, od kolumny 2 do kolumny 5.) W rezultacie nie ma ani jednego piksela spośród tych, które były potrzebne, aby zapewnić cień w punkcie (5) , 2) na przeciwległej ścianie (dla litery G). Zamiast tego będzie jasna plama odpowiadająca otworowi w literze G! Kostka BGE nie jest dobra, ponieważ niepoprawnie renderuje G.

Gra w golfa 423 znaki

Funkcja hpełniła tę samą rolę, co validQw kodzie unGolfed. Funkcja renderowania perspectivenie jest uwzględniona, ponieważ nie przyczynia się do wyzwania i nie jest wymagana.

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}}]
DavidC
źródło
Woah, te widoki 3D są bardzo fajne! Czy na pewno ostatni blok kodu to „UnGolfed”? Wydaje mi się, że gra w golfa. :)
xem.
Masz rację. Ostatni blok jest golfowy. Poprawiłem nagłówek. Jedną fajną rzeczą w widokach 3D jest to, że są one interaktywne: obracanie i powiększanie można wykonywać za pomocą myszy.
DavidC
BTW, według moich obliczeń, wśród 15600 możliwych kombinacji jest 564 prawidłowych kostek.
DavidC
To miła informacja. Jak długo zajęło ci to obliczenie? także 26 * 26 * 26 = 17576, a nie 15600. Czy coś mi brakuje?
xem
Użyłem permutacji, a nie krotek; tzn. brak powtarzających się liter. 26 * 25 * 24 = 15600. Znalezienie 564 skrzynek zajęło 21 sekund.
DavidC
12

Prolog, 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.

Program nazywa się tak:

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

Prologwydawało się być dobrym wyborem, ponieważ łatwo jest przedstawić problem w logice pierwszego rzędu. PrologZapewnia również potężną funkcjonalność do rozwiązywania tego rodzaju problemów.

Ponieważ jednak kod jest golfowy, powinienem dodać wyjaśnienie.

Wersja lekko golfowa

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

Współrzędne odpowiadające pikselom z każdej strony kości można łatwo przekonwertować na układ współrzędnych 3D. Korzystać T, La Rz góry (1) i lewy (2) i (3) prawego boku. ui vsą używane do współrzędnych na obrazach:

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

Wyniki dla każdego aktywnego (tj. Czarnego) piksela są łączone w zestaw „pikseli 3D”, które można aktywować bez zmiany wyglądu obiektu z tej strony. Przecięcie zbiorów dla każdej strony to wszystkie piksele 3D, które można aktywować bez dodawania pikseli, które utrudniają widok (tzn. Patrząc z przynajmniej jednej strony byłby piksel, którego nie powinno tam być).

Pozostaje tylko sprawdzić po każdej stronie, czy na skrzyżowaniu znajduje się piksel, który blokuje widok, tam gdzie jest to konieczne.

Prowadzi to do predykatów w programie:

  • f : wykonuje kontrolę końcową; bierze litery u góry, po lewej stronie i po prawej stronie
  • u , v i w : wykonaj kontrole, jeśli dla każdego piksela aktywnego z boku jest piksel 3D na skrzyżowaniu, który blokuje widok
  • h : sprawdza obecność piksela na skrzyżowaniu
  • t , l , r : sprawdza, czy piksel 3D można zablokować od góry, lewej i prawej strony.
  • c : sprawdza piksel na obrazie litery. Ciąg tam może wyglądać nieco dziwnie, ale jest to tylko kompaktowy sposób przechowywania danych obrazu. Jest to po prostu sekwencja znaków o następujących wartościach (zapis szesnastkowy):

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

    Każdy z tych znaków przechowuje dane dla 3 wierszy pikseli w obrazie (obrazkach) (= 15 pikseli). Piksele są również ponownie uporządkowane, dzięki czemu dane są przechowywane w jednym miejscu i nie są dzielone na wiele wierszy, takich jak dane PO.

Formułowanie matematyczne

formuła

Dane wejściowe

formuła

Konwersja piksela w jednym znaku do zestawu pikseli 3D, które zasłaniają widok tego piksela

formuła

formuła

formuła

Piksele, które można bezpiecznie dodać (bez zasłaniania widoku w niewłaściwym miejscu)

formuła

Sprawdza z każdej strony, czy piksele, które muszą być zasłonięte, można bezpiecznie zasłonić

formuła

formuła

formuła

Kombinacja czeków dla każdej strony

formuła

fabiański
źródło
1
Ja .. Uch ... Co? Uważam to za niezrozumiałe. (+1)
patrz
Święty ... idę spać ...
BrunoJ
Imponujący! Dzięki za tę odpowiedź
xem.
1
Miły. btw, myślę o tym, że proces zaczyna się od solidnego bloku sześciennego. (Wydaje się, że myślisz o dodawaniu pikseli tam, gdzie wcześniej ich nie było). Każda litera usuwa niektóre piksele 3D z tego bloku. Zatem zakłócenia powstają, gdy sąsiednia litera usuwa piksele, które litera „chciała zachować”. Zakłócenia wynikają raczej z „brakujących pikseli” niż z dodatkowych pikseli.
DavidC
9

J - 223 197 191 znaków

Funkcja przyjmująca listę trzech znaków jako argument.

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

Ten golf w dużej mierze opiera się na potężnej funkcji J o nazwie rank , która daje nam niemal „za darmo” operacje „rzeźbienia” i „obserwowania”. Aby nieco to uprościć, ranga odnosi się do wymiarów rzeczownika lub naturalnych argumentów czasownika.

J ma tablice wielowymiarowe i oczywiste jest, że powiedzmy, tablica 3D może być interpretowana jako pojedyncza tablica 3D, lub jako lista macierzy, lub tablica 2D wektorów, lub tablica 3D skalarów. Tak więc każda operacja w J może mieć kontrolę nad aplikacją, jak rozłożyć na argument. Ranga 0 oznacza zastosowanie na skalarach, ranga 1 oznacza zastosowanie na wektorach i tak dalej.

   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

Staje się to bardzo potężne, gdy wprowadzisz funkcje diadadowe (dwuargumentowe), ponieważ jeśli kształty dwóch argumentów (po uwzględnieniu rangi) są akceptowalne, J wykona pewne niejawne zapętlenie:

   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

Kiedy wszystkie twoje kształty są akceptowalne i możesz sam określić rangę, istnieje wiele sposobów łączenia argumentów. Przedstawiamy kilka sposobów na pomnożenie macierzy 2D i macierzy 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|
+---------+---------+--------------+--------------+--------------+

Zauważysz, że tak naprawdę nie ma liter w orientacji, o którą pyta pytanie, tylko zapisuje je, ale jest to wygodne dla logiki rangi. O ile nie zastosujemy odwrotu lub rotacji liter przed ich zastosowaniem, nie będzie działać poprawnie. Ale poprawianie takich rzeczy zajęłoby cenne znaki, więc zamiast tego zakodujemy litery tak, że kiedy J rzeźbi je w naturalny sposób, niektóre potrójne twarze będą we właściwej orientacji i we względnych pozycjach. Okazuje się, że najkrótszym rozwiązaniem jest obrócenie wszystkich liter o ćwierć obrotu przeciwnie do ruchu wskazówek zegara. Biorąc pod uwagę trzeci wymiar J, który reprezentuje oś przód-tył, przybliżony schemat poniżej pokazuje, dlaczego ten schemat działa.

wizualizacja kostki Rycina A: Trzy boki sześcianu, w które rzeźbi J. Rycina B: Pytają trzy strony, których litery są zorientowane tak, jak pytanie.

Ten wybór w kodowaniu pozwala zaoszczędzić 12 znaków w stosunku do poprzedniej metody i sprawia, że ​​całość jest ładniejsza. Rzeczywisty golf tworzy sześcian z rzeźby "1i "2ma funky logikę, ze względu na niepowiązaną optymalizację.

Następnie musimy sprawdzić twarze. Ponieważ zakodowania bloku co 1s i 0s, możemy po prostu zsumować wzdłuż każdej osi w sposób chcemy (są to +/"1, +/"2i +/bity), dostosować do wartości logiczne ( 0<), a następnie porównać je wszystkie bezpośrednio do pierwotnego 90 ° - odwrócone litery.

Schemat kompresji koduje każdy wiersz o wielkości 5 pikseli każdej litery jako podstawową 32 reprezentację liczby binarnej. Wykorzystując szereg cukrów składniowych i przeciążenie operatora, ".'1b',"#:jest najkrótszym sposobem na przekształcenie listy znaków w podstawowe liczby 36. Cóż, technicznie rzecz biorąc, podstawa 32, ale J uważa, że ​​to jednoargumentowe, więc kto liczy?

Użycie jest poniżej. Zauważ, że łańcuchy są tablicami znaków w J, więc lista trzech elementów 'A','B','C'może być napisana 'ABC'w skrócie. Również booleany wynoszą 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
algorytmshark
źródło
4

Python, 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))

Zadzwoń z v:

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

Wszystko poniżej pochodzi z mojej poprzedniej wersji bez golfa, która zawiera pomocne funkcje rysowania. Możesz go użyć jako punktu odskoczni.

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

Zadzwoń, validaby go uruchomić:

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

W tej chwili kod jest skonfigurowany do testowania poprawności B E Gi wydrukowania powstałych powierzchni:

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

Po B G Euruchomieniu możemy zauważyć, że G jest niepoprawny:

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
Hobby Calvina
źródło
wow, dobra robota! +1 za remis Wszystko i kompletność odpowiedzi. +1 za użycie tak krótkiego algorytmu. <3 it
xem
@xem Thanks! W końcu grałem w golfa. Chociaż nie mogłem wymyślić, jak uzyskać BZ2 do dekompresji znaków Unicode.
Calvin's Hobbies
+1. Niezła odpowiedź. Mam nadzieję, że więcej osób poprze golfa, które składają się z mniejszych golfów, takich jak ten, ponieważ to naprawdę wymaga wysiłku.
Vectorized
1
g=[[0 for j in s]for i in s]można skrócić do g=map(list,[[0]*5]*5). Ponadto można uniknąć wcięć bloków, jeśli są one jedno stwierdzenie: if c[e]:g[e[a]][e[a-2]]=1.
Bakuriu
@Bakuriu i bitpwner, dzięki za sugestie i zmiany :)
Calvin's Hobbies
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])

To rozwiązanie do gry w golfa wymaga zewnętrznej biblioteki numpy, która jest dość popularna, więc myślę, że można z niego korzystać.

Ciąg znaków Unicode składa się z 41 znaków, podczas gdy ta sama rzecz w odpowiedzi na prolog @ fabian to 44.

Najciekawsze jest tutaj to, że indeksowanie tablicy numpy. W a[ix], ixmoże być tablicą boolowską o takim samym kształcie jak a. To to samo co mówienie a[i, j, k] where ix[i, j, k] == True.

Wersja bez golfa

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

Skrypt do kompresji tabeli

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
Promień
źródło