파이썬 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 스타일이어야합니다 (줄 바꿈 만 해당). 마지막 줄의 후행 개행은 선택 사항입니다.
테스트하려면 :
> 파이썬 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
핵심은 내가 설명하겠다고 말한 세 가지 비밀 라인에 있습니다.
테트로 미노의 모양은 16 진수로 인코딩됩니다. 각 테트로 니모는 셀의 3x4 그리드를 차지하는 것으로 간주되며 각 셀은 공백 (공백) 또는 전체 (숫자 기호)입니다. 그런 다음 각 조각은 3 개의 16 진수로 인코딩되며 각 숫자는 하나의 4 셀 열을 설명합니다. 최하위 숫자는 가장 왼쪽 열을 설명하고 각 숫자의 최하위 비트는 각 열의 최상위 셀을 설명합니다. 비트가 0이면 해당 셀은 비어 있고 그렇지 않으면 '#'입니다. 예를 들어, I tetronimo는 00F
최하위 열에있는 4 개의 숫자 기호를 인코딩하기 위해 설정된 최하위 숫자의 4 비트와 왼쪽 및 오른쪽에 설정된 상단 비트 를 사용하여로 인코딩됩니다 . 중간에 설정된 상위 2 개 비트입니다. T 는131
그러면 전체 16 진수가 왼쪽으로 1 비트 이동됩니다 (2 배). 이렇게하면 맨 아래 부분을 무시할 수 있습니다. 잠시 후에 이유를 설명하겠습니다.
따라서 입력에서 현재 조각이 주어지면 모양을 설명하는 12 비트가 시작되는 16 진수로 인덱스를 찾은 다음 bits
변수 의 1-12 비트 (비트 0 건너 뛰기)가 현재 조각을 설명 하도록 아래로 이동합니다 .
에 대한 할당 drop
은 조각이 다른 조각 조각에 착지하기 전에 조각이 떨어지는 그리드의 맨 위에서 몇 개의 행 을 결정합니다. 첫 번째 줄은 경기장의 각 열 상단에 얼마나 많은 빈 셀이 있는지 찾는 반면 두 번째 줄은 조각의 각 열에서 가장 낮은 점유 셀을 찾습니다. 이 zip
함수는 튜플 목록을 반환합니다. 여기서 각 튜플은 입력 목록의 각 항목에서 n 번째 셀로 구성됩니다 . 따라서 샘플 입력 보드를 사용하면 zip(board[:6] + [full])
다음이 반환됩니다.
[
('[', '[', '[', '[', '[', '[', '['),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(']', ']', ']', ']', ']', ']', ']')
]
이 목록에서 적절한 열에 해당하는 튜플을 선택하고 열에서 첫 번째 인덱스를 찾습니다 '#'
. 이것은 우리가 호출하기 전에 "전체"행을 추가하는 이유입니다 zip
, 그래서 index
열이 비어 그렇지 않으면 때 (예외 상황을 던지는 대신에) 합리적인 수익을해야합니다.
그런 다음 '#'
조각의 각 열 에서 가장 낮은 값을 찾기 위해 해당 열을 설명하는 4 비트를 이동하고 마스킹 한 다음 bin
함수를 사용하여이를 1과 0의 문자열로 변환합니다. 이 bin
함수는 중요한 비트 만 반환하므로 가장 낮은 점유 셀 (최상위 세트 비트)을 찾기 위해이 문자열의 길이 만 계산하면됩니다. bin
기능은 앞에 추가 '0b'
우리가 그것을 뺄 그래서. 또한 최하위 비트도 무시합니다. 이것이 16 진수가 왼쪽으로 1 비트 이동하는 이유입니다. 이것은 문자열 표현이 맨 위 셀만 가득 찬 열 (예 : T 조각) 과 길이가 동일한 빈 열을 고려하기위한 것 입니다.
예를 들어,의 열 I의 로, 앞서 언급의 Tetromino이 있습니다 F
, 0
그리고 0
. bin(0xF)
입니다 '0b1111'
. 를 무시하면 '0b'
길이가 4가됩니다. 그러나 bin(0x0)
입니다 0b0
. 를 무시한 '0b'
후에도 여전히 '1'의 길이가 있으며 이는 올바르지 않습니다. 이를 설명하기 위해 우리는이 중요하지 않은 비트를 무시할 수 있도록 끝에 추가 비트를 추가했습니다. 따라서 +3
코드 '0b'
의 시작 부분과 끝 부분에 중요하지 않은 비트가 차지하는 추가 길이를 설명합니다 .
이 모든 것은 세 열 ( (0,1,2)
)에 대한 생성기 표현식 내에서 발생하며 , min
결과를 가져와 세 열 중 하나에 닿기 전에 조각이 드롭 할 수있는 최대 행 수를 찾습니다.
나머지는 코드를 읽으면 이해하기 쉬울 것입니다. 그러나 for
이러한 할당을 따르는 루프는 조각을 보드에 추가합니다. 그 후 while
루프는 전체 행을 제거하고 상단의 빈 행으로 대체하고 점수를 집계합니다. 마지막에 보드와 점수가 출력에 인쇄됩니다.