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')
只需一个换行符,我将其视为一个字符。
浏览器代码页上的“ mumbo jumbo”可能会阻止成功复制和粘贴此代码,因此您可以选择从以下代码生成文件:
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 <整数
[]
[]
[]
[####]
[####]
[##### ####]
[===========]
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
关键在于我要解释的三个隐喻。
四聚体的形状在那里以十六进制编码。每个tetronimo都被认为占据了一个3x4的单元格网格,其中每个单元格都是空白(空格)或完整(数字符号)。然后,每个片段都用3个十六进制数字编码,每个数字描述一个4单元格的列。最低有效数字描述最左边的列,而每个数字的最低有效位描述每列的最上面的单元格。如果某位为0,则该单元格为空,否则为“#”。例如,我tetronimo被编码成00F
与在至少-显著数字集的四个位来编码在最左侧的列的四个数字符号,和Ť是131
,最高位设置在左侧和右侧,最高两位设置在中间。
然后将整个十六进制数向左移动一位(乘以2)。这将使我们忽略最底端的位。一分钟后,我将解释原因。
因此,根据输入的当前片段,我们找到该十六进制数的索引,在该索引处描述其形状的12位开始,然后向下移,以使bits
变量的位1-12(跳过位0)描述当前片段。
分配以drop
确定在落在其他片段上之前,该片段将从网格顶部下降多少行。第一行查找比赛场地每一列顶部的空白单元格,而第二行查找该作品每一列中占用最少的单元格。该zip
函数返回一个元组列表,其中每个元组由输入列表中每个项目的第n个单元格组成。因此,使用示例输入板,zip(board[:6] + [full])
将返回:
[
('[', '[', '[', '[', '[', '[', '['),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(']', ']', ']', ']', ']', ']', ']')
]
我们从该列表中选择与相应列对应的元组,然后'#'
在该列中找到第一个的索引。这就是为什么我们在调用之前添加了“完整”行的原因zip
,以便index
在该列为空时返回明智的返回值(而不是引发异常)。
然后,要查找该'#'
作品的每一列中的最低位,我们将描述该列的四位移位并屏蔽,然后使用该bin
函数将其转换为一串一和零。该bin
函数仅返回有效位,因此我们只需要计算此字符串的长度即可找到占用最低的单元(最高有效设置位)。该bin
函数还前置'0b'
,因此我们必须减去它。我们也忽略了最低有效位。这就是为什么十六进制数向左移动一位。这是为了解决空列的问题,空列的字符串表示长度将与仅顶部单元格已满(例如T片)的列的长度相同。
例如,的列我四格拼板正如前面提到的,是F
,0
和0
。 bin(0xF)
是'0b1111'
。忽略后'0b'
,我们的长度为4,这是正确的。但是bin(0x0)
是0b0
。忽略之后'0b'
,我们仍然有一个长度'1,这是不正确的。为了解决这个问题,我们在末尾添加了一个额外的位,因此我们可以忽略此无关紧要的位。因此,+3
代码中的占'0b'
了开始时由占用的额外长度,而末尾占了无关紧要的位。
所有这一切都在生成器表达式中出现在三列((0,1,2)
)中,然后我们min
求出结果以找出该片段在接触到三列中的任何一列之前可以掉落的最大行数。
通过阅读代码,其余部分应该很容易理解,但是for
遵循这些分配的循环会将代码添加到了开发板上。此后,while
循环将删除完整的行,将其替换为顶部的空白行,并计分。最后,木板和得分被打印到输出中。