检查三个字母是否可以构成“ Godel-Escher-Bach立方体”


29

这个问题的灵感来自《 Godel,Escher,Bach》一书的封面:

这里的挑战是编写一个函数,该函数告诉三个给定的字母是否可以产生可以从三个侧面读取的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

该雕塑由三个字母组成,顺序如下:

  • 在上面的第一个字母
  • 左边的第二个字母
  • 右边的三个字母
  • 第一字母的底部绑定到第二字母的顶部。

例:

您的函数可以接受三个大写字母(三个字符或一个字母三个字符串)作为输入,并输出一个布尔值(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。

有标准漏洞。

更准确地说,除了三个字母之外,您不能使用外部输入,也不能在源代码中对17576个可能的答案进行硬编码。

以任何语言显示的字符中最短的答案将获胜!

玩得开心 :)



是的,是让我发现本书的MU难题,也是使我想到这一挑战的书的封面。有问题吗?这是您18洞游戏的一部分吗?
xem

2
替换孔1是一个不错的选择;;)...没关系,如果有什么事是我没有早点起床的错。+1是一个非常不错的挑战!
Martin Ender 2014年

我们是否可以从外部文件中检索定义字母形状的数据,还是也需要将其包含在源文件中?
CesiumLifeJacket 2014年

你的二进制乙方在左上角为0,而不是1
加尔文的爱好

Answers:


13

Mathematica 423

我添加了一个名为“阻止的工作原理”的部分。

不打高尔夫球

(*字母表的二进制数据作为单个字符串存储在s。中vars,将其导入并将其转换为数组。)

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

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

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

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

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

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

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


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

多维数据集{"B", "G", "E"}有效吗?(即,三个字母是否可以正确地投射到墙上?)

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

插图

下图显示了如何渲染BGE。上排图形采用正交透视图,就好像观看者与立方体的距离无穷远。下一行显示了从近处看这些块的外观。可以手动旋转3D图形,以精确检查各个单位立方体的位置。

字母“ G”出现问题。衬线与其余字母没有任何关系。

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

博格


但是,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)处的像素,以及位于其上方和下方的像素。仍有四个像素需要考虑。

封锁3

但是,如右窗格所示,字母E雕刻出剩下的关注像素(5,2,2)(5,3,2),(5,4,2)和(5,5,2)。(这是由于字母E在第2列到第5列的第四行中具有等于0的位的事实。)因此,在确保点(5处的阴影)所需的像素中没有剩下一个像素。 ,2)在远处的墙壁上(对于字母G)。而是在字母G上有一个对应于孔的亮点!立方体BGE不好,因为它错误地渲染了G。

打了423个字符

该功能与UnGolfed代码中的功能h相同validQperspective不包括渲染功能,因为它对挑战没有帮助,也不是挑战所必需的。

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”吗?在我看来好像打高尔夫球了。:)
xem14年

你是对的。最后一块打高尔夫球。我更正了标题。关于3D视图的一件很酷的事情是它们是交互式的:旋转和缩放可以通过鼠标完成。
DavidC 2014年

顺便说一句,根据我的计算,在15600个可能的排列中有564个有效的多维数据集。
DavidC 2014年

这是一个很好的信息。您花费了多长时间进行计算?同样,26 * 26 * 26 = 17576,而不是15600。还是我错过了什么?
xem

我使用排列,而不是元组。即没有重复的字母。26 * 25 * 24 = 15600。找到564个案例,花了21秒钟。
DavidC

12

序言,440,414

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

该程序的调用如下:

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

Prolog看起来很不错,因为很容易用一阶逻辑表示问题。还Prolog提供了解决此类问题的强大功能。

但是,由于代码很复杂,我想我应该添加一些解释。

轻度高尔夫球版

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

与骰子每一侧的像素相对应的坐标可以轻松转换为3D坐标系。我用TLR对顶(1),左(2)和右(3)侧。uv用于图像中的坐标:

  • 电话(u,v) -> (4-v, ?, u)
  • L(u,v) -> (?, v, u)
  • R(u,v) -> (u, v, ?)

每个有效(即黑色)像素的结果被组合到一组“ 3D像素”中,这些像素可以被激活而无需从该侧改变对象的外观。每个侧面的集合的交集都是3D像素,可以在不添加像素的情况下将其激活,这会阻塞视图(即从至少一侧看,应该有一个不应存在的像素)。

剩下的就是检查每一侧,如果需要的话,在相交处是否有像素阻塞了视图。

这导致程序中的谓词:

  • f:做最后检查;将字母放在顶部,左侧和右侧
  • uvw:进行检查,如果侧面的每个有效像素在相交处都存在一个3D像素,则该像素会遮挡视图
  • h:检查相交处是否存在像素
  • tlr:检查是否可以从顶部,左侧和右侧遮挡3D像素。
  • c:检查字母图像中的像素。那里的字符串可能看起来有些奇怪,但这只是存储图像数据的一种紧凑方式。它只是一个具有以下值(十六进制表示法)的字符序列:

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

    这些字符中的每个字符都在字母图像(= 15像素)中存储3个像素行的数据。像素也进行了重新排序,以便将数据存储在一个位置,并且不像OP的数据那样分成多行。

数学公式

式

输入数据

式

从一个char中的像素转换为妨碍该像素视图的3D像素集

式

式

式

可以安全添加的像素(不会在错误的位置遮挡视图)

式

检查每一侧,确保可以安全地遮挡需要遮挡的像素

式

式

式

每侧支票组合

式


1
我..呃..什么?我觉得这令人费解。(+1)
seequ 2014年

天哪

令人印象深刻!感谢您的回答
xem

1
真好 顺便说一句,我认为该过程始于一个立体立方块。(您似乎将其视为在以前没有像素的情况下添加像素。)每个字母都会从该块中删除一些3D像素。因此,当相邻字母删除“想要保留”一个字母的像素时,就会产生干扰。干扰源自“丢失像素”,而不是多余像素。
DavidC 2014年

9

的J - 223 197 191字符

以三个字符列表作为参数的函数。

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

这种高尔夫在很大程度上依赖于J的强大功能,即rank,它使我们几乎完全免费地进行“雕刻”和“观看”操作。为简化起见,等级是指名词或动词自然参量的量纲。

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

当您引入二元(两个参数)函数时,这将变得非常强大,因为如果两个参数的形状(考虑了排名之后)都可以接受,那么J将执行一些隐式循环:

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

当所有形状都可以接受并且您可以自己指定等级时,可以使用多种方法组合参数。在这里,我们展示了一些您可以将2D矩阵和3D数组相乘的方法。

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

您会注意到,这实际上并不是按照问题要求的方向刻出字母,而是将它们写在其中,但是对于等级逻辑来说很方便。除非我们在应用字母之前反转或旋转字母,否则它将无法正常工作。但是纠正这样的事情会占用宝贵的字符,因此我们将对字母进行编码,以使当J自然地将它们雕刻时,大约三倍的面孔将处于正确的方向和相对位置。事实证明,最简单的解决方案是将所有字母逆时针旋转四分之一圈。考虑到J的三维尺寸代表前后轴,下面的粗略图显示了此方案起作用的原因。

立方体的可视化 图A:J切入的立方体的三个面。图B:字母朝向问题的三个面。

与以前的方法相比,这种编码选择节省了12个字符,使整个过程更加整洁。由于不相关的优化,实际的高尔夫从中创造出立方体,"1"2以一些时髦的逻辑进行雕刻。

然后,我们必须检查面部。由于我们编码块作为1和0,我们可以只沿着在我们所希望的方式(这些是各轴综上所述+/"1+/"2+/比特),调整到布尔值(0<),然后将所有直接比较它们原来的90° -转字母。

压缩方案将每个字母的每个5px行编码为二进制数的基数32表示。通过利用多种语法糖和运算符重载,这".'1b',"#:是将字符列表转换为基数36的最短方法。好吧,从技术上讲,基数为32,但是J认为这是一元的,那么谁在计数呢?

用法如下。请注意,字符串是J中的字符数组,因此'A','B','C'可以'ABC'简短地列出三项列表。此外,布尔值是1/0。

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

4

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

哇,干得好!+1为drawAll和答案的完整性。+1用于使用这种简短算法。<3 it
xem

@xem谢谢!我终于打高尔夫球了。虽然我不知道如何使bz2解压缩unicode字符。
卡尔文的爱好2014年

+1。好答案。希望有更多的人赞成像小型高尔夫球这样的高尔夫球,因为这样确实需要努力。
2014年

1
g=[[0 for j in s]for i in s]可以缩短为g=map(list,[[0]*5]*5)。如果它们是单个语句,也可以避免缩进块if c[e]:g[e[a]][e[a-2]]=1
Bakuriu 2014年

@Bakuriu和bitpwner,感谢您的建议和编辑:)
卡尔文的爱好

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.