Controlla se tre lettere possono formare un "cubo Godel-Escher-Bach"


29

Questa domanda è ispirata alla copertina del libro "Godel, Escher, Bach":

La sfida qui è scrivere una funzione che indichi se tre lettere date possono produrre una scultura 3D che può essere letta da tre lati.

Per questo esercizio, le uniche lettere che puoi usare sono 26 bitmap 5px * 5px:

O in binario (dalla A alla 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 scultura è formata da tre lettere nel seguente ordine:

  • lettera uno in alto,
  • lettera due a sinistra
  • lettera tre a destra
  • la parte inferiore della lettera uno è legata alla parte superiore della lettera due.

Esempio:

La tua funzione può accettare come input tre lettere maiuscole (tre caratteri o tre stringhe di una lettera) e generare un valore booleano (vero / falso o 0/1) che indica se la scultura corrispondente può esistere.

Esempio:

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: puoi tornare vero anche se la scultura contiene "pixel volanti" (cubi o gruppo di cubi che non sono collegati a nulla).

Si applicano scappatoie standard.

Più precisamente, non è possibile utilizzare input esterni oltre alle tre lettere e non è possibile codificare nel codice sorgente le possibili 17576 risposte

Vince la risposta più breve in caratteri in qualsiasi lingua!

Divertiti :)



Sì, è il puzzle MU che mi ha fatto scoprire il libro, ed è la copertina del libro che mi ha fatto pensare a questa sfida. C'è un problema? Questa era una parte delle tue 18 buche?
xem

2
Sarebbe stata una buona opzione per sostituire il foro 1.;) ... Non importa, se non altro è colpa mia se non ho alzato qualcosa prima. È una sfida davvero decente, +1!
Martin Ender,

Possiamo recuperare i dati che definiscono le forme delle lettere da un file esterno o devono essere inclusi anche nell'origine?
CesiumLifeJacket,

Il tuo binario B ha 0 nell'angolo in alto a sinistra, non 1.
Calvin's Hobbies

Risposte:


13

Mathematica 423

Ho aggiunto una sezione chiamata "Come funziona il blocco".

Ungolfed

(* I dati binari dell'alfabeto sono memorizzati come una singola stringa in s. Lo varsimporta e lo converte in un array.)

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]

Esempio

Il cubo è {"B", "G", "E"}valido? (cioè le tre lettere si proiettano correttamente sui muri?)

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

falso

Illustrazioni

Le figure seguenti mostrano come viene eseguito il rendering di BGE. La fila superiore di figure assume prospettive ortogonali, come se lo spettatore fosse posizionato a distanze infinite dal cubo. La riga inferiore mostra l'aspetto dei blocchi da vicino. Le figure 3D possono essere ruotate manualmente per ispezionare con precisione dove sono posizionati i cubi delle singole unità.

Si verifica un problema con la lettera "G". Non c'è nulla che colleghi il serif al resto della lettera.

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

bge


BEG, tuttavia, dovrebbe funzionare bene.

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

Vero

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

elemosinare


Come funziona il blocco?

Per favore, scusami se questo sembra ovvio, ma forse alcune persone vorranno visualizzare come le lettere interferiscono l'una con l'altra, annullando i loro pixel 3D.

Seguiamo cosa succede alla lettera G, nel rendering del cubo BGE.

Presteremo particolare attenzione al voxel (pixel 3D o cubo unità) di seguito. Questo è il pixel che scompare nel cubo BGE. È il pixel corrispondente alla riga 4, colonna 5 nell'array di bit e nel grafico dell'array corrispondente.

blocco 1


Nel piano xy, il pixel corrisponde al disco grigio nel punto (5,2). Ma poiché lavoreremo in 3D, dobbiamo considerare le 5 posizioni nel pozzo da (5,1,2) a (5,5,2). Se uno di quei pixel sopravvive scolpendo con le lettere B ed E, saremo in grado di vedere il pixel di interesse per la proiezione 3D sul muro.

blocco 2


Le lettere interferiscono quando i pixel vengono rimossi dal blocco solido. A sinistra, la freccia nera rappresenta l'intaglio di pixel, corrispondente al bit in basso a destra; ha il valore 0 per la lettera B. Scolpendo rimuove il pixel in (5,1,2), insieme a quelli direttamente sopra e sotto di esso. Rimangono da considerare quattro pixel.

blocco 3

Ma come mostra il riquadro destro, la lettera E scolpisce i pixel rimanenti di interesse, (5,2,2) (5,3,2), (5,4,2) e (5,5,2). (Ciò è dovuto al fatto che la lettera E ha bit pari a 0 nella quarta riga, dalla colonna 2 alla colonna 5.) Di conseguenza, non rimane un singolo pixel tra quelli necessari per garantire l'ombra nel punto (5 , 2) sulla parete opposta (per la lettera G). Invece, ci sarà un punto luminoso corrispondente a un buco nella lettera G! Il cubo BGE non va bene perché rende erroneamente G.

423 caratteri golfizzati

La funzione ha hsvolto lo stesso ruolo validQdel codice unGolfed. La funzione di rendering perspectivenon è inclusa perché non contribuisce alla sfida e non è richiesta da essa.

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, quelle viste 3D sono molto pulite! Sei sicuro che l'ultimo blocco di codice sia "UnGolfed"? Mi sembra golfista. :)
xem

Hai ragione. L'ultimo blocco è giocato a golf. Ho corretto l'intestazione. Una cosa interessante delle viste 3D è che sono interattive: la rotazione e lo zoom possono essere fatti con il mouse.
DavidC

A proposito, secondo il mio conto, ci sono 564 cubi validi tra le 15600 possibili permutazioni.
DavidC

Questa è una bella informazione. Quanto tempo hai impiegato per calcolarlo? inoltre, 26 * 26 * 26 = 17576, non 15600. O mi sto perdendo qualcosa?
XX

Ho usato permutazioni, non tuple; cioè senza lettere ripetute. 26 * 25 * 24 = 15600. Ci sono voluti 21 secondi per trovare i 564 casi.
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.

Il programma si chiama così:

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

Prologsembrava essere una buona scelta, dal momento che è facile rappresentare il problema nella logica del primo ordine. PrologFornisce inoltre potenti funzionalità per risolvere questo tipo di problema.

Tuttavia, dal momento che il codice è golfato, suppongo che dovrei aggiungere qualche spiegazione.

Versione leggermente golfata

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

Le coordinate corrispondenti ai pixel su ciascun lato dei dadi possono essere facilmente convertite in un sistema di coordinate 3D. Uso T, Le Rper la parte superiore (1), sinistra (2) e destro (3) lato. ue vsono usati per le coordinate nelle immagini:

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

I risultati per ciascun pixel attivo (cioè nero) sono combinati a un insieme di "pixel 3D" che possono essere attivati ​​senza cambiare l'aspetto dell'oggetto da questo lato. L'intersezione degli insiemi per ciascun lato è costituita da tutti i pixel 3D, che possono essere attivati ​​senza l'aggiunta di pixel, che ostruiscono la vista (ovvero guardando da almeno un lato ci sarebbe un pixel che non dovrebbe essere lì).

Non resta che verificare per ogni lato, se c'è un pixel nell'intersezione che blocca la vista, dove è necessario.

Questo porta ai predicati nel programma:

  • f : esegue il controllo finale; prende le lettere in alto, a sinistra e a destra
  • u , v e w : esegui i controlli, se per ogni pixel attivo sul lato è presente un pixel 3D nell'intersezione, che blocca la vista
  • h : verifica l'esistenza di un pixel nell'intersezione
  • t , l , r : controlla se un pixel 3D può essere bloccato dalla parte superiore, sinistra e destra.
  • c : controlla il pixel nell'immagine di una lettera. La stringa lì dentro può sembrare un po 'strana, ma è solo un modo compatto per memorizzare i dati dell'immagine. È semplicemente una sequenza di caratteri con i seguenti valori (notazione esadecimale):

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

    Ognuno di questi caratteri memorizza i dati per righe di 3 pixel in immagini di lettere (= 15 pixel). I pixel vengono inoltre riordinati in modo che i dati vengano archiviati in una posizione e non divisi su più righe, come i dati dell'OP.

Formulazione matematica

formula

Dati in ingresso

formula

Conversione da pixel in un carattere a set di pixel 3D che ostruiscono la vista per questo pixel

formula

formula

formula

Pixel che possono essere aggiunti in modo sicuro (senza ostruire la vista nel posto sbagliato)

formula

Verifica per ciascun lato che i pixel che devono essere ostruiti possano essere ostruiti in modo sicuro

formula

formula

formula

Combinazione di controlli per ciascun lato

formula


1
Io .. Uh .. Cosa? Lo trovo incomprensibile. (+1)
seequ,

Santo ... vado a letto ...
BrunoJ,

Impressionante! Grazie per questa risposta
xem,

1
Bello. a proposito, penso che il processo inizi con un solido blocco cubico. (Sembri pensarlo come l'aggiunta di pixel dove nessuno era prima.) Ogni lettera rimuove alcuni pixel 3D da quel blocco. Quindi l'interferenza sorge quando una lettera vicina rimuove i pixel che una lettera "voleva mantenere". L'interferenza deriva da "pixel mancanti" anziché da pixel extra.
DavidC

9

J - 223 197 191 char

Una funzione che accetta un elenco di tre caratteri come argomento.

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

Questo golf si basa fortemente su una potente funzionalità di J chiamata rank , che ci dà le operazioni "scolpisci" e "guarda il lato" quasi gratis. Per semplificare un po 'troppo, il grado si riferisce alla dimensionalità di un sostantivo o agli argomenti naturali di un verbo.

J ha array multidimensionali ed è ovvio che, per esempio, un array 3D può essere interpretato come un singolo array 3D o come un elenco di matrici o un array 2D di vettori o un array 3D di scalari. Quindi ogni operazione in J può avere la sua applicazione controllata e come diffondersi sull'argomento. Il grado 0 significa applicare sugli scalari, il grado 1 significa applicare sui vettori e così via.

   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

Questo diventa molto potente quando si introducono funzioni diadiche (a due argomenti), perché se le forme dei due argomenti (dopo aver tenuto conto del rango) sono gradevoli, J farà un ciclo implicito:

   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

Quando tutte le forme sono gradevoli e puoi specificare tu stesso il rango, ci sono molti modi per combinare argomenti. Qui mostriamo alcuni dei modi in cui puoi moltiplicare una matrice 2D e una matrice 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|
+---------+---------+--------------+--------------+--------------+

Noterai che questo in realtà non si ritaglia nelle lettere nell'orientamento richiesto dalla domanda, ma le scrive ma è conveniente per la logica di rango. A meno che non invertiamo o ruotiamo le lettere prima di applicarle, non funzionerà correttamente. Ma correggere cose del genere richiederebbe caratteri preziosi, quindi codificheremo le lettere in modo tale che, quando J le scolpisce in modo naturale, alcune triple di facce saranno negli orientamenti e nelle posizioni relative corrette. Si scopre che la soluzione più breve è quella di ruotare tutte le forme letterali di un quarto di giro in senso antiorario. Considerando la terza dimensione di J che rappresenta l'asse da davanti a dietro, il diagramma grezzo di seguito mostra perché questo schema funziona.

visualizzazione del cubo Figura A: I tre lati del cubo in cui J intaglia. Figura B: I tre lati che hanno le lettere orientate come fa la domanda.

Questa scelta nella codifica consente di salvare 12 caratteri rispetto al metodo precedente e rende tutto più ordinato. L'attuale golf crea il cubo dal "1e "2scolpisce con una logica funky, a causa di un'ottimizzazione non correlata.

Quindi dobbiamo controllare le facce. Poiché codifichiamo il blocco come 1 e 0, possiamo solo riassumere lungo ciascun asse in modo che vogliamo (questi sono i +/"1, +/"2e +/bit), regolare booleani ( 0<), e quindi confrontare tutti direttamente all'originale 90 ° - trasformati in lettere.

Lo schema di compressione codifica ogni riga 5px di ogni lettera come rappresentazione di base 32 di un numero binario. Sfruttando una serie di zuccheri sintattici e sovraccarichi dell'operatore, ".'1b',"#:è il modo più breve per trasformare l'elenco di caratteri in 36 numeri di base. Beh, tecnicamente, base 32, ma J pensa che sia unario, quindi chi conta?

L'utilizzo è inferiore. Nota che le stringhe sono matrici di caratteri in J, quindi un elenco di tre voci 'A','B','C'può essere scritto 'ABC'in breve. Inoltre, i booleani sono 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))

Chiama con v:

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

Tutto sotto è dalla mia precedente versione non golfata che include utili funzioni di disegno. Sentiti libero di usarlo come punto di partenza.

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

Chiama validper eseguirlo:

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

In questo momento il codice è configurato per testare la validità B E Ge stampare le facce risultanti:

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

Eseguendolo B G Epossiamo vedere che la G non è corretta:

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, bel lavoro! +1 per drawAll e la completezza della risposta. +1 per l'utilizzo di un algoritmo così breve. <3 it
xem

@xem Grazie! Finalmente l'ho giocato a golf. Anche se non sono riuscito a capire come ottenere bz2 per decomprimere i caratteri unicode.
Calvin's Hobbies,

+1. Bella risposta. Spero che più persone votino a golf che comprendono golf più piccoli, come questo, perché ci vuole davvero uno sforzo.
Vectorized

1
g=[[0 for j in s]for i in s]può essere abbreviato in g=map(list,[[0]*5]*5). Inoltre è possibile evitare il rientro blocchi se sono una singola istruzione: if c[e]:g[e[a]][e[a-2]]=1.
Bakuriu,

@Bakuriu e bitpwner, grazie per i suggerimenti e le modifiche :)
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])

Questa soluzione per il golf ha bisogno di una libreria esterna, intorpidita, che è abbastanza popolare, quindi penso che sia giusto usarla.

La stringa unicode è in 41 caratteri, mentre la stessa cosa nella risposta del prologo di @ fabian è 44.

Il più interessante qui è che l'indicizzazione dell'array numpy. In a[ix], ixpuò essere un array booleano con la stessa forma di a. È come dire a[i, j, k] where ix[i, j, k] == True.

Versione Ungolfed

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 per comprimere la tabella

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.