Vérifiez si trois lettres peuvent former un «cube Godel-Escher-Bach»


29

Cette question est inspirée de la couverture du livre "Godel, Escher, Bach":

Le défi ici est d'écrire une fonction qui indique si trois lettres données peuvent produire une sculpture 3D qui peut être lue sur trois côtés.

Pour cet exercice, les seules lettres que vous pouvez utiliser sont 26 bitmaps 5px * 5px:

Ou en binaire (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

La sculpture est formée de trois lettres dans l'ordre suivant:

  • lettre un sur le dessus,
  • lettre deux à gauche
  • lettre trois à droite
  • le bas de la lettre un est lié au haut de la lettre deux.

Exemple:

Votre fonction peut accepter en entrée trois lettres majuscules (trois caractères ou trois chaînes d'une lettre) et produire un booléen (vrai / faux ou 0/1) indiquant si la sculpture correspondante peut exister.

Exemple:

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)

NB: vous pouvez retourner vrai même si la sculpture contient des "pixels volants" (cubes ou groupe de cubes attachés à rien).

Des échappatoires standard s'appliquent.

Plus précisément, vous ne pouvez pas utiliser d'entrée externe en plus des trois lettres, et vous ne pouvez pas coder en dur les 17576 réponses possibles dans votre code source

La réponse la plus courte en caractères dans n'importe quelle langue gagne!

S'amuser :)



Oui, c'est le puzzle MU qui m'a fait découvrir le livre, et c'est la couverture du livre qui m'a fait penser à ce défi. Y-a-t-il un problème? Cela faisait-il partie de votre truc 18 trous?
2014

2
Cela aurait été une bonne option pour remplacer le trou 1.;) ... Qu'à cela ne tienne, au moins c'est ma faute de ne pas avoir levé quelque chose plus tôt. C'est un défi vraiment décent, +1!
Martin Ender

Pouvons-nous récupérer les données définissant les formes des lettres à partir d'un fichier externe, ou cela doit-il également être inclus dans la source?
CesiumLifeJacket

Votre B binaire a 0 dans le coin supérieur gauche, pas 1.
Calvin's Hobbies

Réponses:


13

Mathematica 423

J'ai ajouté une section intitulée "Comment fonctionne le blocage".

Non golfé

(* Les données binaires de l'alphabet sont stockées sous la forme d'une seule chaîne s. L' varsimportent et les convertissent en tableau.)

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]

Exemple

Le cube est-il {"B", "G", "E"}valide? (c.-à-d. les trois lettres se projetteront-elles correctement sur les murs?)

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

Faux

Des illustrations

Les figures ci-dessous montrent comment le BGE est rendu. La rangée supérieure de figures prend des perspectives orthogonales, comme si le spectateur était positionné à des distances infinies du cube. La rangée inférieure montre à quoi ressembleraient les blocs de près. Les figures 3D peuvent être tournées manuellement pour inspecter précisément où les cubes unitaires individuels sont positionnés.

Un problème se produit avec la lettre "G". Il n'y a rien qui relie l'empattement au reste de la lettre.

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

bge


BEG, cependant, devrait fonctionner correctement.

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

Vrai

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

mendier


Comment fonctionne le blocage?

Veuillez m'excuser si cela semble évident, mais peut-être que certaines personnes voudront voir comment les lettres interfèrent les unes avec les autres, annulant leurs pixels 3D.

Suivons ce qui arrive à la lettre G, dans le rendu du cube BGE.

Nous porterons une attention particulière au voxel (pixel 3D ou cube d'unité) ci-dessous. C'est le pixel qui disparaît dans le cube BGE. Il s'agit du pixel correspondant à la ligne 4, à la colonne 5 dans le tableau de bits et dans le tracé de tableau correspondant.

blocage 1


Dans le plan xy, le pixel correspond au disque gris au point (5,2). Mais parce que nous allons travailler en 3D, nous devons considérer les 5 positions dans l' arbre de (5,1,2) à (5,5,2). Si l'un de ces pixels survit à la sculpture par les lettres B et E, nous serons en mesure de voir le pixel d'intérêt dans la projection 3D sur le mur.

blocage 2


Les lettres interfèrent lorsque les pixels sont supprimés du bloc solide. A gauche, la flèche noire représente la découpe des pixels, correspondant au bit en bas à droite; il a la valeur 0 pour la lettre B. La découpe supprime le pixel en (5,1,2), ainsi que ceux directement au-dessus et en dessous. Quatre pixels restent à prendre en compte.

blocage 3

Mais comme le montre le volet droit, la lettre E sculpte les pixels d'intérêt restants, (5,2,2) (5,3,2), (5,4,2) et (5,5,2). (Cela est dû au fait que la lettre E a des bits égaux à 0 dans la quatrième ligne, de la colonne 2 à la colonne 5.) Par conséquent, aucun pixel ne reste parmi ceux qui étaient nécessaires pour assurer l'ombre au point (5 , 2) sur le mur du fond (pour la lettre G). Au lieu de cela, il y aura un point lumineux correspondant à un trou dans la lettre G! Le cube BGE n'est pas bon car il rend incorrectement G.

Golfé 423 caractères

La fonction a hjoué le même rôle que validQdans le code non golfé. La fonction de rendu perspective, n'est pas incluse car elle ne contribue pas et n'est pas requise par le défi.

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

Woah, ces vues 3D sont très soignées! Etes-vous sûr que le dernier bloc de code est "UnGolfed"? Il me semble avoir joué au golf. :)
xem

Vous avez raison. Le dernier bloc est joué au golf. J'ai corrigé le titre. Une chose intéressante à propos des vues 3D est qu'elles sont interactives: la rotation et le zoom peuvent être effectués par la souris.
DavidC

BTW, à mon avis, il y a 564 cubes valides parmi les 15600 permutations possibles.
DavidC

Voilà une belle information. Combien de temps vous a-t-il fallu pour calculer cela? aussi, 26 * 26 * 26 = 17576, pas 15600. Ou est-ce que je manque quelque chose?
xem

J'ai utilisé des permutations, pas des tuples; c'est-à-dire pas de lettres répétées. 26 * 25 * 24 = 15600. Il a fallu 21 secondes pour retrouver les 564 cas.
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.

Le programme est appelé comme ceci:

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

Prologsemblait être un bon choix, car il est facile de représenter le problème dans une logique de premier ordre. PrologFournit également des fonctionnalités puissantes pour résoudre ce type de problème.

Cependant, comme le code est joué, je suppose que je devrais ajouter quelques explications.

Version légèrement golfée

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

Les coordonnées correspondant aux pixels de chaque côté des dés peuvent être facilement converties en un système de coordonnées 3D. J'utilise T, Let Rpour le haut (1), le côté gauche (2) et le côté droit (3). uet vsont utilisés pour les coordonnées dans les images:

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

Les résultats pour chaque pixel actif (c'est-à-dire noir) sont combinés à un ensemble de «pixels 3D» qui peuvent être activés sans changer l'apparence de l'objet de ce côté. L'intersection des ensembles pour chaque côté sont tous des pixels 3D, qui peuvent être activés sans ajouter de pixels, qui obstrueraient la vue (c'est-à-dire qu'en regardant d'au moins un côté, il y aurait un pixel qui ne devrait pas être là).

Il ne reste plus qu'à vérifier de chaque côté, s'il y a un pixel dans l'intersection qui bloque la vue, là où c'est nécessaire.

Cela conduit aux prédicats du programme:

  • f : effectue la vérification finale; prend les lettres en haut, à gauche et à droite
  • u , v et w : faites les vérifications, si pour chaque pixel actif sur le côté il y a un pixel 3D à l'intersection, qui bloque la vue
  • h : vérifie l'existence d'un pixel à l'intersection
  • t , l , r : vérifie si un pixel 3D peut être bloqué en haut, à gauche et à droite.
  • c : recherche le pixel dans l'image d'une lettre. La chaîne peut sembler un peu étrange, mais ce n'est qu'un moyen compact de stocker les données d'image. Il s'agit simplement d'une séquence de caractères avec les valeurs suivantes (notation hexadécimale):

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

    Chacun de ces caractères stocke les données de 3 lignes de pixels dans une ou plusieurs images de lettre (= 15 pixels). Les pixels sont également réorganisés de sorte que les données soient stockées à un emplacement et non divisées sur plusieurs lignes, comme les données de l'OP.

Formulation mathématique

formule

Des données d'entrée

formule

Conversion de pixel dans un caractère en un ensemble de pixels 3D qui obstruent la vue de ce pixel

formule

formule

formule

Pixels qui peuvent être ajoutés en toute sécurité (sans obstruer la vue au mauvais endroit)

formule

Vérifie de chaque côté que les pixels qui doivent être obstrués peuvent être obstrués en toute sécurité

formule

formule

formule

Combinaison de chèques de chaque côté

formule


1
Je .. Euh .. Quoi? Je trouve cela incompréhensible. (+1)
voir le

Saint ... je vais me coucher ...
BrunoJ

Impressionnant! Merci pour cette réponse
xem

1
Agréable. btw, je pense que le processus commence par un bloc cubique solide. (Vous semblez y penser en ajoutant des pixels là où il n'y en avait pas auparavant.) Chaque lettre supprime certains pixels 3D de ce bloc. Des interférences surviennent donc lorsqu'une lettre voisine supprime des pixels qu'une lettre "voulait conserver". L'interférence provient de «pixels manquants» plutôt que de pixels supplémentaires.
DavidC

9

J - 223 197 191 caractères

Une fonction prenant comme argument une liste de trois caractères.

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

Ce golf repose en grande partie sur une puissante caractéristique de J appelée rank , qui nous donne presque gratuitement la fonction "sculpter" et "regarder" des opérations. Pour le simplifier un peu, le rang fait référence à la dimensionnalité d'un nom ou des arguments naturels d'un verbe.

J a des tableaux multidimensionnels, et il est évident que, disons, un tableau 3D peut être interprété comme un tableau 3D unique, ou comme une liste de matrices, ou un tableau 2D de vecteurs, ou un tableau 3D de scalaires. Ainsi, chaque opération dans J peut avoir son application contrôlée par rapport à la répartition sur l'argument. Le rang 0 signifie appliquer sur les scalaires, le rang 1 signifie appliquer sur les vecteurs, etc.

   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

Cela devient très puissant lorsque vous introduisez des fonctions dyadiques (à deux arguments), car si les formes des deux arguments (après avoir pris en compte le rang) sont agréables, J fera une boucle implicite:

   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

Lorsque toutes vos formes sont agréables et que vous pouvez spécifier le rang vous-même, il existe plusieurs façons de combiner les arguments. Ici, nous montrons quelques-unes des façons dont vous pouvez multiplier une matrice 2D et un tableau 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|
+---------+---------+--------------+--------------+--------------+

Vous remarquerez que cela ne s'inscrit pas réellement dans les lettres dans l'orientation que demande la question, il les écrit simplement mais est pratique pour la logique de classement. Sauf si nous inversons ou faisons pivoter les lettres avant de les appliquer, cela ne fonctionnera pas correctement. Mais corriger des choses comme ça prendrait des caractères précieux, donc à la place, nous encoderons les lettres de telle sorte que, lorsque J les découpera naturellement, un triple de visages sera dans les bonnes orientations et positions relatives. Il s'avère que la solution la plus courte consiste à faire pivoter toutes les lettres d'un quart de tour dans le sens antihoraire. Considérant la troisième dimension de J pour représenter l'axe d'avant en arrière, le diagramme brut ci-dessous montre pourquoi ce schéma fonctionne.

visualisation du cube Figure A: Les trois côtés du cube dans lesquels J sculpte. Figure B: Les trois côtés qui ont les lettres orientées comme le demande la question.

Ce choix d'encodage enregistre 12 caractères par rapport à la méthode précédente et rend le tout plus net. Le golf proprement dit crée le cube à partir du "1et "2sculpte avec une logique funky, en raison d'une optimisation indépendante.

Ensuite, nous devons vérifier les visages. Puisque nous chiffrons le bloc comme 1 et de 0, nous pouvons simplement résumer le long de chaque axe de la manière que nous voulons (ce sont les +/"1, +/"2et les +/bits), adapter à booléens ( 0<), puis les comparer directement à 90 ° d' origine - lettres tournées.

Le schéma de compression code chaque ligne de 5 pixels de chaque lettre comme représentation de base 32 d'un nombre binaire. En exploitant un certain nombre de sucres syntaxiques et de surcharges d'opérateurs, ".'1b',"#:c'est le moyen le plus court de transformer la liste de caractères en nombres de base 36. Eh bien, techniquement, en base 32, mais J pense que c'est unaire, alors qui compte?

L'utilisation est ci-dessous. Notez que les chaînes sont des tableaux de caractères en J, donc une liste de trois éléments 'A','B','C'peut être écrite 'ABC'pour faire court. De plus, les booléens sont 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

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

Appelez avec v:

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

Tout ce qui suit est de ma précédente version non golfée qui comprend des fonctions de dessin utiles. N'hésitez pas à l'utiliser comme point de départ.

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

Appelez validpour l'exécuter:

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

À l'heure actuelle, le code est configuré pour tester la validité B E Get imprimer les faces résultantes:

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

En l'exécutant, B G Enous pouvons voir que le G est incorrect:

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

wow, bon travail! +1 pour drawAll et l'exhaustivité de la réponse. +1 pour l'utilisation d'un algorithme aussi court. <3 it
xem

@xem Merci! Je l'ai finalement joué au golf. Bien que je n'arrive pas à comprendre comment obtenir bz2 pour décompresser les caractères unicode.
Calvin's Hobbies

+1. Bonne réponse. J'espère que plus de gens voteront pour les golfs composés de petits golfs, comme ça, car cela demande vraiment des efforts.
Vectorisé

1
g=[[0 for j in s]for i in s]peut être raccourci g=map(list,[[0]*5]*5). Vous pouvez également éviter indenter blocs si elles sont une seule instruction: if c[e]:g[e[a]][e[a-2]]=1.
Bakuriu

@Bakuriu et bitpwner, merci pour les suggestions et modifications :)
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])

Cette solution de golf a besoin d'une bibliothèque externe, numpy, qui est assez populaire, donc je pense que c'est bien de l'utiliser.

La chaîne unicode est en 41 caractères, tandis que la même chose dans la réponse prologue de @ fabian est 44.

Le plus intéressant ici est celui de l'indexation du tableau numpy. Dans a[ix], ixpeut être un tableau booléen de même forme que a. C'est la même chose que de dire a[i, j, k] where ix[i, j, k] == True.

Version non golfée

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

Script pour compresser la table

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.