3文字で「Godel-Escher-Bachキューブ」を形成できるかどうかを確認します


29

この質問は、本「Godel、Escher、Bach」の表紙から着想を得ています。

ここでの課題は、指定された3つの文字が3辺から読み取ることができる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

彫刻は、次の順序で3文字で構成されています。

  • 上の文字1、
  • 左側の文字2
  • 右側の文字3
  • 文字1の下部は文字2の上部にバインドされます。

例:

関数は、入力として3つの大文字(3文字または1文字の3文字列)を受け入れ、対応する彫刻が存在できるかどうかを示すブール値(true / falseまたは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)

注:彫刻に「フライングピクセル」(何にも接続されていないキューブまたはキューブのグループ)が含まれている場合でも、trueを返すことがあります。

標準の抜け穴が適用されます。

より正確には、3文字以外の外部入力を使用することはできません。また、ソースコードで17576の可能な回答をハードコードすることはできません。

どの言語の文字でも最短回答が勝ちます!

楽しむ :)



うん、それは私を本を発見させたMUパズルであり、この挑戦​​を考えさせたのは本の表紙です。問題はありますか?これは18ホールのものの一部でしたか?
xem

2
ホール1を交換するのは良い選択肢だったでしょう。;)...気にしないでください。+1は本当にまともな挑戦です!
マーティンエンダー

外部ファイルから文字の形状を定義するデータを取得できますか、それともソースに含める必要がありますか?
CesiumLifeJacket

あなたのバイナリBは、左上隅に、ない1. 0を持っている
カルバンの趣味

回答:


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"}有効ですか?(つまり、3文字は壁に正しく投影されますか?)

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ピクセルをキャンセルして、文字が互いにどのように干渉するかを視覚化したい人がいるかもしれません。

BGEキューブレンダリングで、文字Gに何が起こるかを見てみましょう。

以下のボクセル(3Dピクセルまたは単位立方体)に特に注意を払います。それは、BGEキューブで消えるピクセルです。これは、ビット配列および対応する配列プロットの行4、列5に対応するピクセルです。

ブロック1


xy平面では、ピクセルはポイント(5,2)の灰色ディスクに対応します。しかし、3Dで作業するため、シャフトの(5,1,2)から(5,5,2)までの5つの​​位置を考慮する必要があります。これらのピクセルのいずれかが文字BとEによる彫刻を生き延びた場合、壁の3D投影で対象のピクセルを見ることができます。

ブロッキング2


ピクセルがソリッドブロックから削除されると、文字が干渉します。左の黒い矢印は、右下のビットに対応するピクセルのカービングを表します。文字Bの値は0です。切り出すことで、(5,1,2)のピクセルとその上下のピクセルが削除されます。4つのピクセルはまだ考慮されていません。

ブロッキング3

しかし、右側のペインが示すように、文字Eは残りの対象ピクセル(5,2,2)(5,3,2)、(5,4,2)および(5,5,2)を削り出します。(これは、文字Eの4行目の2桁目から5桁目までのビットが0であるためです。)その結果、ポイント(5 、2)向こう側の壁(文字Gの場合)。代わりに、文字Gの穴に対応する明るいスポットがあります!キューブBGEは、Gを誤ってレンダリングするため、良くありません。

ゴルフ423文字

この関数hは、validQunGolfedコードと同じ役割を果たしました。レンダリング関数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 14

あなたは正しいです。最後のブロックはゴルフです。見出しを修正しました。3Dビューの優れた点の1つは、インタラクティブであることです。回転とズームはマウスで実行できます。
DavidC 14

ところで、私のカウントでは、15600の可能な順列の中に564個の有効なキューブがあります。
DavidC 14

それはいい情報です。それを計算するのにどれくらい時間がかかりましたか?また、26 * 26 * 26 = 17576であり、15600ではありません。または、何か不足していますか?
xem 14

タプルではなく順列を使用しました。すなわち、繰り返される文字はありません。26 * 25 * 24 = 15600。564件のケースを見つけるのに21秒かかりました。
DavidC 14

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.

サイコロの各側のピクセルに対応する座標は、3D座標系に簡単に変換できます。私が使用しTLそして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:最終チェックを行います。上部、左側、右側の文字を取ります
  • uv、およびw:側面でアクティブなすべてのピクセルに対して、交差点に3Dピクセルがある場合、ビューをブロックします。
  • h:交差点にピクセルが存在するかどうかを確認します
  • tlr:3Dピクセルを上下左右からブロックできるかどうかをチェックします。
  • c:文字の画像のピクセルをチェックします。そこの文字列は少し奇妙に見えるかもしれませんが、画像データを保存するためのコンパクトな方法にすぎません。これは、次の値(16進表記)を持つ単なる文字シーケンスです。

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

    これらの各文字は、文字イメージ(= 15ピクセル)の3ピクセル行のデータを格納します。また、OPのデータのように、データが1つの場所に格納され、複数の行に分割されないように、ピクセルが並べ替えられます。

数学定式化

式

入力データ

式

1文字のピクセルから、このピクセルのビューを遮る3Dピクセルのセットへの変換

式

式

式

安全に追加できるピクセル(間違った場所でビューを遮ることなく)

式

両側をチェックし、遮断する必要があるピクセルを安全に遮断できることを確認します

式

式

式

各側のチェックの組み合わせ

式


1
I .. Uh ..何?これは分かりにくいと思います。(+1)
seequ 14

聖...私は...ベッドに行くよ
BrunoJ

印象的!この回答をありがとう
XEM

1
いいね ちなみに、このプロセスは立体立方体ブロックから始まると考えています。(これまでになかったピクセルを追加すると考えているようです。)各文字は、そのブロックからいくつかの3Dピクセルを削除します。そのため、隣接する文字が、文字が「保持したい」ピクセルを削除すると、干渉が発生します。干渉は、余分なピクセルではなく「ピクセルの欠落」に起因します。
DavidC 14

9

J - 223 197 191 CHAR

引数として3文字のリストを取る関数。

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

このゴルフは、ランクと呼ばれるJの強力な機能に大きく依存しています。少し単純化しすぎるために、ランクは名詞または動詞の自然な引数の次元を指します。

Jには多次元配列があり、3D配列は、単一の3D配列、または行列のリスト、ベクトルの2D配列、またはスカラーの3D配列として解釈できることは明らかです。したがって、Jのすべての操作は、引数にどのように広げるかによってアプリケーションを制御できます。ランク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

これは、2項(2引数)関数を導入すると非常に強力になります。2つの引数の形状(ランクを考慮した後)が一致する場合、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が自然にそれらを彫るときに、いくつかのトリプルの顔が正しい向きと相対位置になるようにします。最短の解決策は、すべての文字を4分の1回転反時計回りに回転させることです。Jの3次元目を前後軸を表すと考えると、下図はこのスキームが機能する理由を示しています。

キューブの視覚化 図A:Jが切り込む立方体の3つの側面。図B:質問のように方向付けられた文字を持つ3つの側面。

エンコーディングのこの選択により、以前の方法に比べて12文字節約され、全体がすっきりします。実際のゴルフでは、関連のない最適化により、キューブを外に作成し、ファンキーなロジック"1"2刻みます。

次に、顔を確認する必要があります。我々は、1と0のようにブロックを符号化するので、私たちは(これらは我々が望むように各軸に沿って合計することができ+/"1+/"2および+/、ビット)(ブール値に調整0<)し、元の90にすべてのそれらを直接比較° -回された手紙。

圧縮スキームは、各文字の各5px行を2進数のベース32表現としてエンコードします。多数の構文糖と演算子のオーバーロードを活用することにより".'1b',"#:、文字のリストを36進数に変換する最短の方法です。まあ、技術的にはベース32ですが、Jはそれが単項であると考えています。

使用法は以下です。文字列はJの文字配列であるため、略して3つの項目リスト'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

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

で呼び出す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

うわー、良い仕事です!drawAllおよび回答の完全性のために+1。このような短いアルゴリズムを使用する場合は、+ 1。<3 it
xem 14

@xemありがとう!やっとゴルフをしました。ユニコード文字を解凍するためにbz2を取得する方法を理解できませんでしたが。
カルビンの趣味14

+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
バクリウ14

@Bakuriuとbitpwner、提案と編集に感謝します:)
カルビンの趣味14

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

このゴルフソリューションには外部ライブラリnumpyが必要です。これは非常に人気がありますので、使用しても問題ないと思います。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.