기본 사항 :
다음 테트로 미노와 빈 경기장을 고려하십시오.
0123456789 IOZTLSJ [] [] # ## ## ### # ## # [] # ## ## # # ## # [] # ## ## [] # [] [==========]
경기장의 크기는 고정되어 있습니다. 상단의 숫자는 열 번호를 나타 내기 위해 여기에 있습니다 (입력 참조).
입력:
1 . 이미 테트로 미노로 부분적으로 채워질 수있는 특정 경기장 (위에 기반)이 제공됩니다 (이는 별도의 파일에 있거나 stdin을 통해 제공 될 수 있음).
샘플 입력 :
[] [] [] [] [# # #] [## ######] [==========]
2 . 어떤 열에 삽입 (및 드롭 다운) 할 tetromino를 설명 (공백으로 구분)하는 문자열이 제공됩니다. 테트로 미노는 회전 할 필요가 없습니다. 입력은 stdin에서 읽을 수 있습니다.
샘플 입력 :
T2 Z6 I0 T7
입력이 ‘올바른 형식’이라고 가정하거나 그렇지 않은 경우 정의되지 않은 동작을 생성 할 수 있습니다.
산출
결과 필드를 렌더링하고 ( ‘전체’줄이 사라져야 함) 점수 수를 인쇄합니다 (모든 줄이 10 점을 차지함).
위의 샘플 입력을 기반으로 한 샘플 출력 :
[] [] [] [# ###] [# ###] [##### ####] [==========] 10
우승자:
최단 솔루션 (코드 문자 수 기준). 사용 예가 좋습니다. 골프를 즐겨보세요!
편집 : +500
답변자들이 이미 만든 좋은 노력에 더 많은 관심을 끌기 위해 명성 의 현상금을 추가했습니다 (그리고 아마도이 질문에 대한 몇 가지 새로운 해결책) …
답변
GolfScript-181 자
개행은 필요하지 않습니다. 출력은 표준 출력이지만 stderr에 일부 오류가 있습니다.
\10
프로그램이 181자가되도록하려면 해당 ASCII 문자로 대체해야합니다.
{):X!-{2B{" #"=}%X" ":f*+-1%}%:P;:>.{\!:F;>P{\(@{3&\(@.2$&F|:F;|}%\+}%\+F![f]P+:P
;}do;{"= "&},.,7^.R+:R;[>0="#"/f*]*\+}0"R@1(XBc_""~\10"{base}:B/3/~4*"nIOZTLSJR "
";:"*~;n%)n*~ 10R*+n*
샘플 I / O :
$ cat inp
[ ]
[ ]
[ ]
[ ]
[ # # #]
[ ## ######]
[==========]
T2 Z6 I0 T7
$ cat inp|golfscript tetris.gs 2>/dev/null
[ ]
[ ]
[ ]
[# ###]
[# ### ]
[##### ####]
[==========]
10
Tetromino 압축 :
조각은 3 개의 기본 8 자리 숫자로 저장됩니다. 이것은 간단한 이진 표현 T=[7,2,0], S=[6,3,0], J=[2,2,3]
입니다. 압축 [1]
의 I
조각에 사용 되지만 [1,1,1,1]
나중에 명시 적으로 설정됩니다 (예 : 4*
코드에서). 이러한 모든 배열은 단일 배열로 연결되어 정수로 변환 된 다음 문자열 (인쇄 할 수없는 문자, 길이를 최소화하고 utf8이 발생하지 않도록 기본 126)로 변환됩니다. 이 문자열은 매우 짧습니다 : "R@1(XBc_"
.
그러면 감압은 간단합니다. 먼저 기본 126 변환을 수행 한 다음 기본 8 변환을 수행합니다 ( "~\10"{base}/
즉, "~\10"
각 요소에 대해 기본 변환을 반복 하고 수행). 결과 배열은 3 개의 그룹으로 분할되고의 배열 I
은 고정됩니다 ( 3/~4*
). 우리는 다음베이스 2에 각 요소를 변환하고 (0을 제거한 후) 문자열의 해당 인덱스의 문자로 각 이진 숫자를 대체 " #"
( 2base{" #"=}%...-1%
– 메모를 우리가 다른 배열을 반대해야한다는 2
될 것"# "
대신을 " #"
).
보드 / 조각 형식, 조각 떨어 뜨리기
보드는 단순히 각 줄에 하나씩 문자열의 배열입니다. 처음에는 이에 대한 작업이 수행되지 않으므로 n/(
입력에 대해 생성 할 수 있습니다 . 조각은 또한 X 위치에 대해 왼쪽에 공백이있는 문자열 배열이지만 후행 공백은 없습니다. 조각은 어레이에 추가하고 충돌이 있는지 지속적으로 테스트하여 떨어집니다.
충돌 테스트는 조각의 모든 캐릭터를 반복하고 보드에서 동일한 위치의 캐릭터와 비교하여 수행됩니다. #
+ =
와 #
+ #
를 충돌 로 간주하고 싶으 므로 ((piecechar & 3) & boardchar)가 0이 아닌지 테스트합니다. 이 반복을 수행하는 동안 #
+ ,
+ 쌍의 값을 올바르게 설정하는 ((piecechar & 3) | boardchar)로 보드를 업데이트 (복사본)합니다
#
. +
[
. 조각을 다른 행 아래로 이동 한 후 충돌이 발생하면이 업데이트 된 보드를 사용합니다.
채워진 행을 제거하는 것은 매우 간단합니다. "= "&
false 를 반환 하는 모든 행을 제거합니다 . 채워진 행이 어느 것 =
또는 연계가 false로 동일시 빈 문자열이 될 것입니다, 그래서. 그런 다음 제거 된 행의 수를 세고 점수에 수를 더한 다음 그 수를 앞에 추가합니다
"[ ... ]"
. 우리는 그리드의 첫 번째 행을 복용하고 교체하여이 컴팩트하게 생성 #
과를 .
보너스
우리는 조각이 떨어질 때 조각의 각 위치에서 보드가 어떻게 생겼는지 계산하기 때문에이를 삭제하는 대신 스택에 유지할 수 있습니다! 총 3 자 이상이면이 모든 위치를 출력 할 수 있습니다 (또는 보드 상태가 단일 간격 인 경우 2 자).
{):X!-{2B{" #"=}%X" ":f*+-1%}%:P;:>.{>[f]P+:P(!:F;{\(@{3&\(@.2$&F|:F;|}%\+}%\+F!}
do;{"= "&},.,7^.R+:R;[>0="#"/f*]*\+}0"R@1(XBc_""~\10"{base}:B/3/~4*"nIOZTLSJR "
";:"*~;n%)n*~ ]{n*n.}/10R*
답변
Perl, 586523 483472 427407404386387356353 자
(defined-or //
연산자 에는 Perl 5.10이 필요합니다 ).
stdin에서 모든 입력을받습니다. 여전히 심각한 골프가 필요합니다.
^ Q는 ASCII 17 (DC1 / XON), ^ C는 ASCII 3, ^ @는 ASCII 0 (NUL)을 나타냅니다.
while(<>){push@A,[split//]if/]/;while(/\w/g){for$i(0..6){for($f=0,$j=4;$j--;){$c=0;map{if($_){$i--,$f=$j=3,redo if$A[$k=$i+$j][$C=$c+$'+1]ne$";$A[$k][$C]="#"if$f}$c++}split//,unpack"b*",chr vec"3^@'^@c^@^Q^C6^@\"^C^Q^Q",index(OTZLSJI,$&)*4+$j,4;$s+=10,@A[0..$k]=@A[$k,0..$k-1],map{s/#/ /}@{$A[0]},$i++if 9<grep/#/,@{$A[$k]}}last if$f}}}print+(map@$_,@A),$s//0,$/
주석이 달린 버전 :
while(<>){
# store the playfield as an AoA of chars
push@A,[split//]if/]/;
# while we're getting pieces
while(/\w/g){
# for each line of playfield
for$i(0..6){
# for each line of current piece
for($f=0,$j=4;$j--;){
# for each column of current piece
$c=0;
map{
if($_){
# if there's a collision, restart loop over piece lines
# with a mark set and playfield line decremented
$i--,$f=$j=3,redo if$A[$k=$i+$j][$C=$c+$'+1]ne$";
# if we already found a collision, draw piece
$A[$k][$C]="#"if$f
}
$c++
# pieces are stored as a bit vector, 16 bits (4x4) per piece,
# expand into array of 1's and 0's
}split//,unpack"b*",chr vec"3^@'^@c^@^Q^C6^@\"^C^Q^Q",index(OTZLSJI,$&)*4+$j,4;
# if this playfield line is full, remove it. Done by array slicing
# and substituting all "#"'s in line 0 with " "'s
$s+=10,@A[0..$k]=@A[$k,0..$k-1],map{s/#/ /}@{$A[0]},$i++if 9<grep/#/,@{$A[$k]}
}
# if we found a collision, stop iterating over the playfield and get next piece from input
last if$f
}
}
}
# print everything
print+(map@$_,@A),$s//0,$/
편집 1 : 심각한 골프, 출력 버그 수정.
편집 2 : 일부 인라이닝, (드럼 롤 …) 3 문자, 기타 골프의 그물 절약을 위해 두 개의 루프를 하나로 병합했습니다.
편집 3 : 일반적인 하위 표현 제거, 약간의 지속적인 병합 및 정규식 조정.
편집 4 : 테트로 미노 표현을 패킹 된 비트 벡터, 기타 골프로 변경했습니다.
편집 5 : tetromino 문자에서 배열 인덱스로보다 직접 번역, 인쇄 불가능한 문자 사용, 기타 골프.
편집 6 : Nakilon이 발견 한 r3 (편집 2)에 도입 된 버그 정리 상단 라인 수정. 인쇄 할 수없는 문자를 더 많이 사용하십시오.
편집 7 : vec
tetromino 데이터를 가져 오는 데 사용 합니다. 플레이 필드의 크기가 고정되어 있다는 사실을 활용하십시오. if
성명 =>if
수정 자, 편집 2의 루프 병합이 효과가 있기 시작합니다. 사용 //
0 점수의 경우에.
편집 8 : Nakilon에 의해 발견 된 r6 (편집 5)에 도입 된 또 다른 버그를 수정했습니다.
편집 9 : 줄을 지울 때 새 참조를 만들지 말고 배열 슬라이스를 통해 참조를 이동하십시오. 두 개 map
를 하나로 병합하십시오 . 더 똑똑한 정규식. “스마트” for
. 기타 골프.
편집 10 : 인라인 tetromino 배열, 주석 버전 추가.
답변
루비 — 427408 398 369 359
t=[*$<]
o=0
u=->f{f.transpose}
a=u[t.reverse.join.scan /#{'( |#)'*10}/]
t.pop.split.map{|w|m=(g='I4O22Z0121T01201L31S1201J13'[/#{w[0]}\d+/].scan(/0?\d/).zip a.drop w[1].to_i).map{|r,b|(b.rindex ?#or-1)-r.size+1}.max
g.map{|r,b|b.fill ?#,m+r.size,r.to_i}
v=u[a]
v.reject!{|i|i-[?#]==[]&&(o+=10;v)<<[' ']*10}
a=u[v]}
puts u[a].reverse.map{|i|?[+i*''+?]},t[-1],o
답변
Bash 셸 스크립트 ( 301304 자)
업데이트 : 맨 위 줄로 확장되는 조각과 관련된 버그를 수정했습니다. 또한 출력은 이제 표준 출력으로 전송되며, 추가로 스크립트를 다시 실행하여 게임을 계속할 수 있습니다 (이 경우 총 점수를 직접 합산해야 함).
여기에는 인쇄 할 수없는 문자가 포함되어 있으므로 16 진 덤프를 제공했습니다. 다른 이름으로 저장tetris.txt
:
0000000: 7461 696c 202d 3120 245f 7c7a 6361 743e tail -1 $_|zcat>
0000010: 753b 2e20 750a 1f8b 0800 35b0 b34c 0203 u;. u.....5..L..
0000020: 5590 516b 8330 10c7 dff3 296e 4c88 ae64 U.Qk.0....)nL..d
0000030: a863 0c4a f57d 63b0 07f7 b452 88d1 b4da .c.J.}c....R....
0000040: 1a5d 5369 91a6 df7d 899a d05d 5e72 bfbb .]Si...}...]^r..
0000050: fbff 2fe1 45d5 0196 7cff 6cce f272 7c10 ../.E...|.l..r|.
0000060: 387d 477c c4b1 e695 855f 77d0 b29f 99bd 8}G|....._w.....
0000070: 98c6 c8d2 ef99 8eaa b1a5 9f33 6d8c 40ec ...........3m.@.
0000080: 6433 8bc7 eeca b57f a06d 27a1 4765 07e6 d3.......m'.Ge..
0000090: 3240 dd02 3df1 2344 f04a 0d1d c748 0bde 2@..=.#D.J...H..
00000a0: 75b8 ed0f 9eef 7bd7 7e19 dd16 5110 34aa u.....{.~...Q.4.
00000b0: c87b 2060 48a8 993a d7c0 d210 ed24 ff85 .{ `H..:.....$..
00000c0: c405 8834 548a 499e 1fd0 1a68 2f81 1425 ...4T.I....h/..%
00000d0: e047 bc62 ea52 e884 42f2 0f0b 8b37 764c .G.b.R..B....7vL
00000e0: 17f9 544a 5bbd 54cb 9171 6e53 3679 91b3 ..TJ[.T..qnS6y..
00000f0: 2eba c07a 0981 f4a6 d922 89c2 279f 1ab5 ...z....."..'...
0000100: 0656 c028 7177 4183 2040 033f 015e 838b .V.(qwA. @.?.^..
0000110: 0d56 15cf 4b20 6ff3 d384 eaf3 bad1 b9b6 .V..K o.........
0000120: 72be 6cfa 4b2f fb03 45fc cd51 d601 0000 r.l.K/..E..Q....
그런 다음 bash 명령 프롬프트에서 다음과 같이 설치 하는 elvis
것이 좋습니다.vim
vi
.
$ xxd -r tetris.txt tetris.sh
$ chmod +x tetris.sh
$ cat << EOF > b
> [ ]
> [ ]
> [ ]
> [ ]
> [ # # #]
> [ ## ######]
> [==========]
> EOF
$ ./tetris.sh T2 Z6 I0 T7 2>/dev/null
-- removed stuff that is not in standard out --
[ ]
[ ]
[ ]
[# ###]
[# ### ]
[##### ####]
[==========]
10
작동 원리
이 코드는 실행 프로그램이 gzexe
스크립트를 . Tetromino 조각은 vi 편집기 명령의 시퀀스로 표시됩니다. 문자 계수는 충돌을 감지하는 데 사용되며 줄 계수는 점수를 계산하는 데 사용됩니다.
압축을 푼 코드 :
echo 'rej.j.j.:wq!m'>I
echo '2rejh.:wq!m'>O
echo '2rej.:wq!m'>Z
echo '3rejh1.:wq!m'>T
echo 'rej.j2.:wq!m'>L
echo 'l2rej2h.:wq!m'>S
echo 'lrej.jh2.:wq!m'>J
for t
do for y in `seq 1 5`
do echo -n ${y}jk$((${t:1}+1))l|cat - ${t:0:1}|vi b>0
grep ========== m>0||break
[ `tr -cd '#'<b|wc -c` = `tr -cd '#'<m|wc -c` ]||break
tr e '#'<m>n
done
cat n>b
grep -v '##########' b>m
$((S+=10*(`wc -l < b`-`wc -l < m`)))
yes '[ ]'|head -7|cat - m|tail -7>b
done
cat b
echo $S
골프를 치기 전의 원래 코드 :
#!/bin/bash
mkpieces() {
pieces=('r@j.j.j.' '2r@jh.' '2r@j.' '3r@jh1.' 'r@j.j2.' 'l2r@j2h.' 'lr@j.jh2.')
letters=(I O Z T L S J)
for j in `seq 0 9`; do
for i in `seq 0 6`; do
echo "jk$(($j+1))l${pieces[$i]}:wq! temp" > ${letters[$i]}$j
done
done
}
counthashes() {
tr -cd '#' < $1 | wc -c
}
droppiece() {
for y in `seq 1 5`; do
echo -n $y | cat - $1 | vi board > /dev/null
egrep '={10}' temp > /dev/null || break
[ `counthashes board` -eq `counthashes temp` ] || break
tr @ "#" < temp > newboard
done
cp newboard board
}
removelines() {
egrep -v '#{10}' board > temp
SCORE=$(($SCORE + 10 * (`wc -l < board` - `wc -l < temp`)))
yes '[ ]' | head -7 | cat - temp | tail -7 > board
}
SCORE=0
mkpieces
for piece; do
droppiece $piece
removelines
done
cat board
echo $SCORE
답변
파이썬 : (504 개) 519 문자
(Python 3 솔루션) 현재 상단에 표시된 형식으로 입력을 설정해야합니다 (입력 코드는 계산되지 않음). 나중에 파일이나 stdin에서 읽을 수 있도록 확장하겠습니다. 이제 프롬프트로 작동합니다. 입력을 (총 8 줄)에 붙여 넣습니다.
R=range
f,p=[input()[1:11]for i in R(7)],p
for(a,b)in input().split():
t=[' '*int(b)+r+' '*9for r in{'I':'#,#,#,#','O':'##,##','Z':'##, ##','T':'###, # ','L':'#,#,##','S':' ##,##','J':' #, #,##'}[a].split(',')]
for r in R(6-len(t),0,-1):
for i in R(len(t)):
if any(a==b=='#'for(a,b)in zip(t[i],f[r+i])):break
else:
for i in R(0,len(t)):
f[r+i]=''.join(a if b!='#'else b for(a,b)in zip(t[i],f[r+i]))
if f[r+i]=='#'*10:del f[r+i];f[0:0]=[' '*10];p+=10
break
print('\n'.join('['+r+']'for r in f[:7]),p,sep='\n')
거기에 훨씬 더 많이 저축 할 수 있는지 확실하지 않습니다. 비트 필드로의 변환에서 상당히 많은 문자가 손실되지만 문자열로 작업하는 것보다 훨씬 더 많은 문자를 절약 할 수 있습니다. 또한 더 많은 공백을 제거 할 수 있는지 확실하지 않지만 나중에 시도해 보겠습니다.
더 많이 줄일 수는 없습니다. 비트 필드 기반 솔루션을 사용한 후 더 압축하는 방법을 찾았 기 때문에 문자열로 다시 전환했습니다 (비트 필드에 8 자 저장!). 하지만 포함하는 것을 잊고 L
안에있는 포인트에 오류가있어서 캐릭터 수는 한숨 만 올라갈뿐 … 나중에 좀 더 압축 할 무언가를 찾을 수도 있지만, 거의 끝이 났다고 생각합니다. 원본 및 주석 처리 된 코드는 아래를 참조하십시오.
원래 버전 :
field = [ input()[1:11] for i in range(7) ] + [ 0, input() ]
# harcoded tetrominoes
tetrominoes = {'I':('#','#','#','#'),'O':('##','##'),'Z':('##',' ##'),'T':('###',' # '),'L':('#','#','##'),'S':(' ##','##'),'J':(' #',' #','##')}
for ( f, c ) in field[8].split():
# shift tetromino to the correct column
tetromino = [ ' ' * int(c) + r + ' ' * 9 for r in tetrominoes[f] ]
# find the correct row to insert
for r in range( 6 - len( tetromino ), 0, -1 ):
for i in range( len( tetromino ) ):
if any( a == b == '#' for (a,b) in zip( tetromino[i], field[r+i] ) ):
# skip the row if some pieces overlap
break
else:
# didn't break, insert the tetromino
for i in range( 0, len( tetromino ) ):
# merge the tetromino with the field
field[r+i] = ''.join( a if b != '#' else b for (a,b) in zip( tetromino[i], field[r+i] ) )
# check for completely filled rows
if field[r+i] == '#' * 10:
# remove current row
del field[r+i]
# add new row
field[0:0] = [' '*10]
field[7] += 10
# we found the row, so abort here
break
# print it in the requested format
print( '\n'.join( '[' + r + ']' for r in field[:7] ) )
# and add the points = 10 * the number of redundant lines at the end
print( str( field[7] ) )
답변
루비 1.9, 357 355 353 339 330 310 309 자
d=0
e=[*$<]
e.pop.split.map{|f|f="L\003\003\007J\005\005\007O\007\007Z\007\013S\013\007I\003\003\003\003T\017\005"[/#{f[j=0]}(\W*)/,1].bytes.map{|z|?\0+?\0*f[1].hex+z.to_s(2).tr("01"," #")[1,9]}
k,f,i=i,[p]+f,e.zip(f).map{|l,m|l.bytes.zip(m.to_s.bytes).map{|n,o|j|=n&3&q=o||0;(n|q).chr}*""}until j>0
e=[]
e+=k.reject{|r|r.sum==544&&e<<r.tr(?#,?\s)&&d+=10}}
puts e,d
점을 유의 \000
(세 번째 줄에 널 바이트 포함) 이스케이프가 실제 인쇄 할 수없는 등가로 대체되어야한다.
샘플 입력 :
[ ]
[ ]
[ ]
[ ]
[ # # #]
[ ## ######]
[==========]
T2 Z6 I0 T7
용법:
ruby1.9 tetris.rb < input
또는
ruby1.9 tetris.rb input
답변
기음 , 727 […] 596 581 556 517 496 471 461 457 문자
이것은 내 첫 번째 코드 골프입니다. 문자 수가 훨씬 줄어들 수 있다고 생각 합니다. 숙련 된 골퍼가 힌트를 줄 수 있다면 좋을 것입니다.
현재 버전은 다른 차원의 플레이 필드도 처리 할 수 있습니다. 입력은 DOS / Windows 및 Unix 형식 모두에서 줄 바꿈을 가질 수 있습니다.
코드는 최적화 이전에 매우 간단했습니다. 테트로 미노는 (7 * 3) x4 비트 배열로 해석되는 4 개의 정수로 저장되고, 플레이 필드는있는 그대로 저장되고, 타일이 삭제되고 각 시작과 이후에 완전한 라인이 제거됩니다. 타일 드롭.
문자 수를 계산하는 방법을 몰랐기 때문에 불필요한 줄 바꿈을 모두 제거하고 코드의 파일 크기를 사용했습니다.
편집 596 => 581 : KitsuneYMG 덕분에 %ls
제안을 제외한 모든 것이 완벽하게 작동했으며, putch
대신 대신 putchar
사용할 수 있음 ( getch
어떻게 든 작동하지 않음)을 발견하고에서 모든 괄호를 제거했습니다 #define G
.
수정 581 => 556 : 나머지 루프 for
와 중첩 된 F
루프에 만족하지 않았 으므로 루프를 병합, 변경 및 제거하는 작업이 있었는데, 꽤 혼란 스럽지만 그만한 가치가 있습니다.
편집 556 => 517 : 마침내 만드는 방법을 찾았습니다 a
int 배열 . 일부 N;
는 c
더 break
이상와 병합 되지 않았습니다.
수정 496 => 471 : 이제 플레이 필드 너비 와 높이가 수정되었습니다.
편집 471 => 461 : 사소한 수정, putchar
putch
표준 기능이 아니므 로 다시 사용됩니다 .
편집 : 버그 수정, 후 대신 타일 드롭 전에 전체 줄이 제거 되었으므로 전체 줄이 끝에 남을 수 있습니다. 수정은 문자 수를 변경하지 않습니다.
#define N (c=getchar())
#define G T[j%4]&1<<t*3+j/4
#define X j%4*w+x+j/4
#define F(x,m) for(x=0;x<m;x++)
#define W while
T[]={916561,992849,217,1},C[99],c,i,j,s,t,x,A,a[99],w=13;
main(){F(j,7)C["IJLSTZO"[j]]=j;
F(j,91)a[j]=N;
W(N>w){t=C[c];x=N-86;
W(c){F(j,12)if(G&&X>1?a[X]-32:0)c=0;
F(j,12)if(G&&X>w&&!c)a[X-w]=35;x+=w;}N;
F(i,6){A=0;t=i*w;F(x,w)A|=(a[t+x]==32);
if(!A){s++;F(j,t)a[t+w-j]=a[t-j];
x=1;W(a[x]-93)a[x++]=32;}}}
F(i,91)putchar(a[i]);printf("%i0",s);}