Python 2.6+ - 334 322 316个字符
397 368 366个未压缩字符
exec'xÚEPMO!½ï¯ i,P*Ýlš%ì‰=‰Ö–*†þz©‰:‡—Lò¾fÜ”bžAù,MVi™.ÐlǃwÁ„eQL&•uÏÔ‹¿1O6ǘ.€LSLÓ’¼›î”3òšL¸tŠv[ѵl»h;ÁºŽñÝ0Àë»Ç‡ÛûH.ª€¼âBNjr}¹„V5¾3Dë@¼¡•gO. ¾ô6 çÊsÃЮürÃ1&›ßVˆùZ`Ü€ÿžcx±ˆ‹sCàŽ êüRô{U¯ZÕDüE+³ŽFA÷{CjùYö„÷¦¯Î[0þøõ…(Îd®_›â»E#–Y%’›”ëýÒ·X‹d¼.ß9‡kD'.decode('zip')
必须有一个换行符,我将其计为一个字符。
浏览器代码页可能会阻止成功复制和粘贴此代码,因此您可以选择从此代码生成文件:
s = """
23 63 6F 64 69 6E 67 3A 6C 31 0A 65 78 65 63 27 78 DA 45 50 4D 4F 03 21
10 BD EF AF 20 69 2C 50 2A 02 DD 6C 9A 25 EC AD 07 8D 89 07 3D 89 1C D6
96 2A 86 05 02 1B AD FE 7A A9 89 3A 87 97 4C F2 BE 66 DC 94 62 9E 41 F9
2C 4D 56 15 69 99 0F 2E D0 6C C7 83 77 C1 16 84 65 51 4C 26 95 75 CF 8D
1C 15 D4 8B BF 31 4F 01 36 C7 98 81 07 2E 80 4C 53 4C 08 D3 92 BC 9B 11
EE 1B 10 94 0B 33 F2 9A 1B 4C B8 74 8A 9D 76 5B D1 B5 6C BB 13 9D 68 3B
C1 BA 8E F1 DD 30 C0 EB BB C7 87 DB FB 1B 48 8F 2E 1C AA 80 19 BC E2 42
4E 6A 72 01 7D B9 84 56 35 BE 33 44 8F 06 EB 40 BC A1 95 67 4F 08 2E 20
BE F4 36 A0 E7 CA 73 C3 D0 AE FC 72 C3 31 26 9B DF 56 88 AD F9 5A 60 DC
80 FF 9E 63 78 B1 88 8B 73 43 E0 8E A0 EA FC 52 F4 7B 55 8D AF 5A 19 D5
44 FC 45 2B B3 8E 46 9D 41 F7 7B 43 6A 12 F9 59 F6 84 F7 A6 01 1F AF CE
5B 30 FE F8 F5 85 28 CE 64 AE 5F 9B E2 BB 45 23 96 59 25 92 9B 94 EB FD
10 D2 B7 58 8B 64 BC 2E DF 39 87 6B 44 27 2E 64 65 63 6F 64 65 28 27 7A
69 70 27 29
"""
with open('golftris.py', 'wb') as f:
f.write(''.join(chr(int(i, 16)) for i in s.split()))
测试
俄罗斯方块
[ ]
[ ]
[ ]
[ ]
[ # # #]
[ ## ######]
[==========]
T2 Z6 I0 T7
换行符必须是Unix风格(只有换行符)。最后一行可以选择性地带有尾随换行符。
测试方法:
> python golftris.py < intetris
[ ]
[ ]
[ ]
[# ###]
[# ### ]
[##### ####]
[==========]
10
该代码解压缩了原始代码,并使用exec
执行它。这个被解压的代码大小为366个字符,看起来像这样:
import sys
r=sys.stdin.readlines();s=0;p=r[:1];a='[##########]\n'
for l in r.pop().split():
n=int(l[1])+1;i=0xE826408E26246206601E>>'IOZTLSJ'.find(l[0])*12;m=min(zip(*r[:6]+[a])[n+l].index('#')-len(bin(i>>4*l&31))+3for l in(0,1,2))
for l in range(12):
if i>>l&2:c=n+l/4;o=m+l%4;r[o]=r[o][:c]+'#'+r[o][c+1:]
while a in r:s+=10;r.remove(a);r=p+r
print''.join(r),s
需要换行,每个换行符占一个字符。
不要试图阅读此代码。变量名称是随机选择的,旨在寻求最高压缩率(使用不同的变量名称,我看到压缩后有342个字符)。下面是更易理解的版本:
import sys
board = sys.stdin.readlines()
score = 0
blank = board[:1]
full = '[##########]\n'
for piece in board.pop().split():
column = int(piece[1]) + 1
bits = 0xE826408E26246206601E >> 'IOZTLSJ'.find(piece[0]) * 12
drop = min(zip(*board[:6]+[full])[column + x].index('#') -
len(bin(bits >> 4 * x & 31)) + 3 for x in (0, 1, 2))
for i in range(12):
if bits >> i & 2:
x = column + i / 4
y = drop + i % 4
board[y] = board[y][:x] + '#' + board[y][x + 1:]
while full in board:
score += 10
board.remove(full)
board = blank + board
print ''.join(board), score
关键在于我说过要解释的三行神秘代码。
方块的形状被编码在十六进制数中。每个俄罗斯方块都被认为占据一个3x4的单元格网格,其中每个单元格可以是空白(空格)或填充(#)。然后,每个方块用3个十六进制数字进行编码,每个数字描述一个4个单元格的列。最低有效数字描述最左边的列,并且每个数字的最低有效位描述每个列中最上面的单元格。如果某一位为0,则该单元格为空白,否则为“#”。例如,“I”型方块编码为“00F”,其中最低有效数字的四位设置为编码最左边列中的四个“#”,而“T”型方块编码为“131”,其中顶部两个位在中间设置。
然后将整个十六进制数向左移动一位(乘以2)。这将使我们忽略最下面的位。稍后我会解释为什么。
因此,给定输入的当前方块,我们找到索引,其中包含描述其形状的12位,然后将其向下移位,以便
bits
变量的1-12位(跳过第0位)描述当前方块。
对
drop
的赋值确定了方块落到网格顶部以下的行数。第一行找到玩家场地每列顶部有多少空单元格,而第二行找到方块每列中最低的填充单元格。
zip
函数返回一个元组列表,其中每个元组由输入列表中每个项目的第n个单元格组成。因此,使用示例输入板,
zip(board[:6] + [full])
将返回:
[
('[', '[', '[', '[', '[', '[', '['),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(']', ']', ']', ']', ']', ']', ']')
]
我们从该列表中选择与适当列对应的元组,并找到该列中第一个
'#'
的索引。这就是为什么在调用
zip
之前附加了一个“完整”行的原因,因此当该列为空时,
index
将具有合理的返回值(而不是抛出异常)。
然后,为了找到每个方块的最低
'#'
,我们移位并掩码描述该列的四个位,然后使用
bin
函数将其转换为一串由一和零组成的字符串。
bin
函数仅返回有效位,因此我们只需要计算该字符串的长度即可找到最低占用单元格(最高有效位)。
bin
函数还会在前面添加
'0b'
,因此我们需要减去它。我们还忽略了最低有效位。这就是十六进制数向左移位一位的原因。这是为了解决空列的问题,其字符串表示形式与仅填满顶部单元格的列(例如T形方块)的长度相同。
例如,如前所述,
I方块的列为
F
、
0
和
0
。
bin(0xF)
为
'0b1111'
。忽略
'0b'
后,我们有一个长度为4,这是正确的。但是
bin(0x0)
是
0b0
。忽略
'0b'
后,我们仍然有一个长度为1,这是不正确的。为了解决这个问题,我们在末尾添加了一个附加位,以便我们可以忽略这个无关紧要的位。因此,代码中的
+3
用于解决
'0b'
在开头占用的额外长度和末尾无关紧要的位占用的额外长度。
所有这些都发生在三列(
(0,1,2)
)的生成器表达式中,并且我们取
min
结果以找到该方块在任何三列中接触之前可以下落的最大行数。
其余的内容通过阅读代码应该很容易理解,但是在这些赋值之后的
for
循环将该方块添加到棋盘中。在此之后,
while
循环删除满行,在顶部替换为空行,并计算得分。最后,将棋盘和分数打印到输出。