Python 2.6 +-334322316文字
397368366 文字非圧縮
#coding:l1
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')
改行は1行必要で、1文字として数えています。
ブラウザのコードページのマンボジャンボは、このコードのコピーアンドペーストの成功を妨げる可能性があるため、オプションでこのコードからファイルを生成できます。
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
改行は必須であり、それぞれ1文字です。
このコードを読もうとしないでください。変数名は、最高の圧縮率を求めて文字通りランダムに選択されます(変数名が異なると、圧縮後に342文字も表示されます)。より理解しやすいバージョンは次のとおりです。
import sys
board = sys.stdin.readlines()
score = 0
blank = board[:1] # notice that I rely on the first line being blank
full = '[##########]\n'
for piece in board.pop().split():
column = int(piece[1]) + 1 # "+ 1" to skip the '[' at the start of the line
# explanation of these three lines after the code
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: # if the current cell should be a '#'
x = column + i / 4
y = drop + i % 4
board[y] = board[y][:x] + '#' + board[y][x + 1:]
while full in board: # if there is a full line,
score += 10 # score it,
board.remove(full) # remove it,
board = blank + board # and replace it with a blank line at top
print ''.join(board), score
核心は、私が説明すると言った3つの不可解な行にあります。
テトロミノの形は16進数でエンコードされています。各テトロミノは、セルの3x4グリッドを占めると見なされます。ここで、各セルは空白(スペース)または完全(番号記号)のいずれかです。次に、各ピースは3つの16進数でエンコードされ、各桁は1つの4セル列を表します。最下位桁は左端の列を表し、各桁の最下位ビットは各列の最上部のセルを表します。ビットが0の場合、そのセルは空白です。それ以外の場合は、「#」です。たとえば、I tetronimoはとしてエンコードされ00F
、最下位桁の4ビットがオンに設定されて左端の列の4つの番号記号がエンコードされます。Tは131
、上部のビットが左右に設定され、上部の2つのビットが中央に設定されています。
次に、16進数全体が1ビット左にシフトされます(2が掛けられます)。これにより、最下部のビットを無視できるようになります。その理由をすぐに説明します。
したがって、入力から現在のピースが与えられると、その形状を表す12ビットが始まるこの16進数のインデックスを見つけ、それを下にシフトして、bits
変数のビット1〜12(ビット0をスキップ)が現在のピースを表すようにします。
drop
グリッドの上部から、他のピースフラグメントに着地する前にピースが落下する行数を決定するための割り当て。最初の行は、プレイフィールドの各列の上部にある空のセルの数を検索し、2番目の行は、ピースの各列で最も低い占有セルを検索します。このzip
関数はタプルのリストを返します。各タプルは、入力リストの各項目のn番目のセルで構成されます。したがって、サンプル入力ボードを使用すると、次のようにzip(board[:6] + [full])
なります。
[
('[', '[', '[', '[', '[', '[', '['),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(']', ']', ']', ']', ']', ']', ']')
]
このリストから適切な列に対応するタプルを選択し'#'
、列の最初のインデックスを見つけます。zip
これが、を呼び出す前に「完全な」行を追加した理由です。これによりindex
、列が空白の場合に(例外をスローする代わりに)適切なリターンが得られます。
'#'
次に、ピースの各列の最下位を見つけるために、その列を表す4ビットをシフトしてマスクし、bin
関数を使用してそれを1と0の文字列に変換します。このbin
関数は有効ビットのみを返すため、この文字列の長さを計算するだけで、占有されている最下位のセル(最上位のセットビット)を見つけることができます。bin
関数も先頭に追加する'0b'
ので、それを減算する必要があります。最下位ビットも無視します。これが、16進数が1ビット左にシフトする理由です。これは、空の列を考慮に入れるためです。この列の文字列表現は、一番上のセルのみがいっぱいの列(Tピースなど)と同じ長さになります。
たとえば、前述のように、 IF
テトロミノの列は、、、0
および0
です。 bin(0xF)
です'0b1111'
。を無視する'0b'
と、長さは4になります。これは正しいです。しかしbin(0x0)
です0b0
。を無視した後'0b'
でも、長さは '1であり、これは正しくありません。これを説明するために、この重要でないビットを無視できるように、最後にビットを追加しました。したがって、コード内のinは、最初にで、最後に重要でないビット+3
が占める余分な長さを説明するためにあります。'0b'
これらはすべて、3つの列((0,1,2)
)のジェネレーター式内で発生し、min
その結果を取得して、3つの列のいずれかに接触する前にピースがドロップできる最大行数を見つけます。
残りはコードを読むことでかなり理解しやすいはずですが、for
これらの割り当てに続くループはボードにピースを追加します。この後、while
ループは完全な行を削除し、上部の空白行に置き換えて、スコアを集計します。最後に、ボードとスコアが出力に出力されます。