Chr*_*heD 83 language-agnostic code-golf rosetta-stone
考虑以下tetrominoes和空洞的比赛场地:
0123456789 I O Z T L S J [ ] [ ] # ## ## ### # ## # [ ] # ## ## # # ## # [ ] # ## ## [ ] # [ ] [==========]
比赛场地的尺寸是固定的.顶部的数字仅用于表示列号(也可参见输入).
1.您将获得一个特定的游戏区域(基于上述内容),该区域已经部分填充了四联蛋白(这可以在单独的文件中或通过标准输入提供).
样本输入:
[ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========]
2.您将获得一个字符串,该字符串描述(以空格分隔)哪个tetromino插入(和下拉)哪一列.Tetrominoes不需要旋转.输入可以从stdin读取.
样本输入:
T2 Z6 I0 T7
Run Code Online (Sandbox Code Playgroud)
您可以假设输入是"格式良好的"(或者当它不是时会产生未定义的行为).
渲染结果字段("完整"行必须消失)并打印分数计数(每个丢弃的行占10个点).
基于上面的示例输入的示例输出:
[ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10
最短的解决方案(按代码字符计数).用法示例很好.打高尔夫球吧!
编辑:增加了+500
声誉,以吸引更多关注回答者已经做出的努力(可能还有一些新的解决方案)......
Nab*_*abb 27
新线不是必需的.输出是标准输出,尽管stderr中存在一些错误.
\10
应该由程序的相应ASCII字符替换为181个字符.
{):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*
Run Code Online (Sandbox Code Playgroud)
样本I/O:
$ cat inp
[ ]
[ ]
[ ]
[ ]
[ # # #]
[ ## ######]
[==========]
T2 Z6 I0 T7
$ cat inp|golfscript tetris.gs 2>/dev/null
[ ]
[ ]
[ ]
[# ###]
[# ### ]
[##### ####]
[==========]
10
Run Code Online (Sandbox Code Playgroud)
Tetromino压缩:
碎片存储为三个基本8位数字.这是一个简单的二进制表示,例如T=[7,2,0], S=[6,3,0], J=[2,2,3]
.[1]
用于I
压缩的片段,但明确设置为[1,1,1,1]
稍后(即4*
代码中).所有这些数组都连接成一个数组,然后转换为一个整数,然后是一个字符串(基数为126,最小化不可打印的字符,长度,而不是遇到utf8).这个字符串很短:"R@1(XBc_"
.
然后减压很简单.我们首先进行基础126转换,然后进行基础8转换("~\10"{base}/
即迭代通过"~\10"
并对每个元素进行基本转换).生成的数组被分成3组,数组for I
fixed(3/~4*
).然后我们将每个元素转换为base 2并且(在删除零之后)将每个二进制数字替换为字符串中该索引的字符" #"
(2base{" #"=}%...-1%
注意我们需要反转数组,否则2
将"# "
代替" #"
).
板/片格式,丢弃
板块板只是一个字符串数组,每行一个.最初没有工作,所以我们可以n/(
在输入上生成它.片段也是字符串数组,在X位置用左边的空格填充,但没有尾随空格.通过预先添加到阵列来丢弃碎片,并连续测试是否存在碰撞.
通过迭代片中的所有字符并与电路板上相同位置的字符进行比较来完成碰撞测试.我们想把#
+ =
和#
+ #
视为碰撞,所以我们测试((piecechar&3)&boardchar)是否非零.在进行此迭代时,我们还使用((piecechar&3)| boardchar)更新(副本)板,它正确设置了对#
+ ,
+
#
,+
[
.如果在将该部件向下移动后发生碰撞,我们将使用此更新的板.
删除已填充的行非常简单.我们删除所有"= "&
返回false的行.填充的行将不包含=
或, so the conjunction will be a blank string, which equates to false. Then we count the number of rows that have been removed, add the count to the score and prepend that many
"[ ... ]"
s.我们通过取第一行网格并替换#
为紧凑来生成它.
奖金
因为我们计算了当棋子落下时棋盘在每个位置看起来的样子,我们可以将它们保留在堆叠上而不是删除它们!对于总共三个以上的字符,我们可以输出所有这些位置(如果我们有单个间隔的电路板状态,则输出两个字符).
{):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*
Run Code Online (Sandbox Code Playgroud)
nin*_*alj 26
(需要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,$/
Run Code Online (Sandbox Code Playgroud)
评论版:
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,$/
Run Code Online (Sandbox Code Playgroud)
编辑1:一些严肃的高尔夫球,修复输出错误.
编辑2:一些内联,将两个循环合并为一个用于净节省(鼓滚...)3个字符,misc打高尔夫球.
编辑3:一些常见的子表达式消除,一点点不断合并和调整一个正则表达式.
编辑4:将四联骨牌的表示改为打包位向量,错误打高尔夫球.
编辑5:从tetromino字母到数组索引的更直接的翻译,使用不可打印的字符,misc打高尔夫球.
编辑6:固定的bug清理顶线,在Nakilon发现的r3(编辑2)中引入.使用更多不可打印的字符.
编辑7:vec
用于获取tetromino数据.利用游戏场具有固定尺寸的事实.if
statement =>if
修饰符,编辑2循环的合并开始得到回报.使用//
了0得分情况.
编辑8:修复了由Nakilon发现的r6(编辑5)中引入的另一个错误.
编辑9:清除行时不要创建新的引用,只需通过数组切片移动引用.将两个合并map
为一个.更聪明的正则表达式."更聪明" for
.杂项高尔夫球.
编辑10:内联tetromino数组,添加注释版本.
Nak*_*lon 24
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
Run Code Online (Sandbox Code Playgroud)
Ple*_*and 17
更新:修复了涉及延伸到顶行的碎片的错误.此外,输出现在发送到标准输出,作为奖励,可以再次运行脚本继续玩游戏(在这种情况下,您必须自己累加总分).
这包括不可打印的字符,所以我提供了一个十六进制转储.保存为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....
Run Code Online (Sandbox Code Playgroud)
然后,在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
Run Code Online (Sandbox Code Playgroud)
代码自我提取自身类似于使用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
Run Code Online (Sandbox Code Playgroud)
打高尔夫球之前的原始代码:
#!/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
Run Code Online (Sandbox Code Playgroud)
pok*_*oke 13
(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')
Run Code Online (Sandbox Code Playgroud)
不确定我是否可以在那里节省更多.转换到位域时会丢失很多字符,但与使用字符串相比,可以节省更多字符.另外我不确定我是否可以在那里删除更多的空格,但我会稍后再尝试.
将无法再减少它; 在使用基于位域的解决方案之后,我转换回字符串,因为我找到了一种压缩它的方法(在位域上保存了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] ) )
Run Code Online (Sandbox Code Playgroud)
Ven*_*ero 13
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
Run Code Online (Sandbox Code Playgroud)
请注意,\000
转义(包括第三行的空字节)应替换为它们的实际非打印等效项.
样本输入:
[ ]
[ ]
[ ]
[ ]
[ # # #]
[ ## ######]
[==========]
T2 Z6 I0 T7
Run Code Online (Sandbox Code Playgroud)
用法:
ruby1.9 tetris.rb < input
Run Code Online (Sandbox Code Playgroud)
要么
ruby1.9 tetris.rb input
Run Code Online (Sandbox Code Playgroud)
sch*_*der 12
这是我的第一个代码高尔夫,我觉得字符数可以得到多低,将是不错的,如果有经验的球手可以给我一些提示.
当前版本也可以处理具有不同尺寸的运动场.输入可以有DOS/Windows和Unix格式的换行符.
在优化之前,代码非常简单,四联体存储在4个整数中,这些整数被解释为(7*3)x4位数组,游戏区域按原样存储,图块被删除,完整的行在开始时和之后被删除瓦片下降.
我不确定如何计算字符,所以我使用了代码的文件大小,删除了所有不必要的换行符.
编辑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);}
Run Code Online (Sandbox Code Playgroud)
#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')
Run Code Online (Sandbox Code Playgroud)
单个换行是必需的,我把它算作一个字符.
浏览器代码页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()))
Run Code Online (Sandbox Code Playgroud)
intetris
[ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] 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
Run Code Online (Sandbox Code Playgroud)
需要换行符,每行换一个字符.
不要试图阅读此代码.随机搜索变量名称以寻找最高压缩(使用不同的变量名称,压缩后我看到多达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
Run Code Online (Sandbox Code Playgroud)
关键在于我说的三条神秘的线条.
四联骨牌的形状在那里以十六进制数编码.每个tetronimo被认为占用3x4网格的单元格,其中每个单元格是空白(空格)或完整(数字符号).然后用3个十六进制数字对每个部分进行编码,每个数字描述一个4单元列.最低有效数字描述最左侧的列,每个数字中的最低有效位描述每列中最顶部的单元格.如果位为0,则该单元格为空,否则为"#".例如,I tetronimo被编码为00F
,最低有效数字的四位被设置为编码最左列中的四个数字符号,并且T是131
,顶部位设置在左侧和右侧,顶部两位设置在中间.
然后整个十六进制数向左移一位(乘以2).这将允许我们忽略最底部的位.我会在一分钟内解释原因.
因此,给定输入中的当前片段,我们找到该十六进制数的索引,其中描述它的形状的12位开始,然后向下移动,使得bits
变量的位1-12(跳过位0)描述当前片段.
用于drop
确定在落在其他片段上之前片段将从网格顶部开出多少行的分配.第一行找到游戏区域每列顶部有多少个空单元格,而第二行找到该块的每列中最低的占用单元格.该zip
函数返回元组列表,其中每个元组由输入列表中每个项目的第n 个单元格组成.因此,使用示例输入板,zip(board[:6] + [full])
将返回:
[
('[', '[', '[', '[', '[', '[', '['),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', ' ', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', ' ', '#', '#'),
(' ', ' ', ' ', ' ', '#', '#', '#'),
(']', ']', ']', ']', ']', ']', ']')
]
Run Code Online (Sandbox Code Playgroud)
我们从该列表中选择对应于相应列的元组,并找到列中第一个的索引'#'
.这就是为什么我们在调用之前附加了一个"完整"行zip
,这样index
当列是空白时,它将有一个合理的返回(而不是抛出异常).
然后,为了找到'#'
每一列中的最低点,我们移动并屏蔽描述该列的四个位,然后使用该bin
函数将其转换为一个1和0的字符串.该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
循环将删除完整行,将其替换为顶部的空行,并计算得分.最后,将板和分数打印到输出.
... and does not even use code-zipping chicanery.
import os
r=os.read
b='[%11c\n'%']'*99+r(0,91)
for k,v in r(0,99).split():
t=map(ord,' -:G!.:; -:; !-.!"-. !". !./')['IJLOSTZ'.find(k)*4:][:4];v=int(v)-31
while'!'>max(b[v+j+13]for j in t):v+=13
for j in t:b=b[:v+j]+'#'+b[v+j+1:]
b=b.replace('[##########]\n','')
print b[-91:],1060-10*len(b)/13
Run Code Online (Sandbox Code Playgroud)
On the test example
[ ]
[ ]
[ ]
[ ]
[ # # #]
[ ## ######]
[==========]
T2 Z6 I0 T7
Run Code Online (Sandbox Code Playgroud)
it outputs
[ ]
[ ]
[ ]
[# ###]
[# ### ]
[##### ####]
[==========]
10
Run Code Online (Sandbox Code Playgroud)
PS. fixed a bug pointed out by Nakilon at cost of +5
小智 5
我相信这可以改进,我对Golfscript有点新意.
[39 26.2/0:$14{.(}:?~1?15?1?14 2??27?13.!14?2?27?14 1]4/:t;n/)\n*:|;' '/-1%.,:c;~{)18+:&;'XIOZTLSJX'\%~;,1-t\={{.&+.90>{;.}*|\=32=!{&13-:&;}*}%}6*{&+}/|{\.@<'#'+\)|>+}4*{'['\10*']'++}:
;n/0\~n+:|;0\{.'#'
={;)}{n+|+:|;}if\.}do;' '
n+\.@*|+\$+:$;.,1-<:|;}c*|n?$*
Run Code Online (Sandbox Code Playgroud)
行尾是相关的(最后不应该有一行).无论如何,这里是我使用的一些测试用例:
> cat init.txt [ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] T2 Z6 I0 T7> cat init.txt | ruby golfscript.rb tetris.gsc [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10 > cat init.txt [ ] [ ] [ ] [ ] [ # # #] [ ## ##### ] [==========] I0 O7 Z1 S4> cat init.txt | ruby golfscript.rb tetris.gsc [ ] [ ] [ ] [# ] [### #### ] [### ##### ] [==========] 10 > cat init.txt [ ] [ ] [ ] [ ## ### ] [ # # ] [ ## ######] [==========] T7 I0 I3> cat init.txt | ruby golfscript.rb tetris.gsc [ ] [ ] [ ] [ ] [# # ] [## # # # ] [==========] 20
请注意,输入文件中没有行尾,行尾会破坏脚本.