Код Гольф: Игра В Тетрис
основы:
рассмотрим следующие тетромино и пустое игровое поле:
0123456789
I O Z T L S J [ ]
[ ]
# ## ## ### # ## # [ ]
# ## ## # # ## # [ ]
# ## ## [ ]
# [ ]
[==========]
размеры игрового поля фиксируются. Цифры наверху только здесь чтобы указать номер столбца (Также см. ввод).
вход:
1. Вам дается определенное игровое поле (на основе вышеизложенного), которое уже может быть заполнено частично с тетромино (это может быть в отдельном файле или обеспеченные через стандартный ввод.)
пример ввода:
[ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========]
2. Вам дается строка, которая описывает (разделенные пробелами), какие тетромино вставить (и drop down) в какой колонке. Тетромино не нужно вращать. Входу можно прочитать из stdin.
пример ввода:
T2 Z6 I0 T7
вы можете предположить, что вход "хорошо сформирован" (или производить неопределенное поведение, когда это не.)
выход
отобразите полученное поле ("полные" строки должны исчезнуть) и распечатайте количество баллов (каждая отброшенная строка составляет 10 баллов).
выход образца основанный на входном сигнале образца выше:
[ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10
победитель:
самое короткое решение (по количеству символов кода). Примеры использования хороши. Удачи в гольф!
Edit: добавлена щедрость +500 репутация, чтобы нарисовать еще немного внимание к хорошим усилиям, которые уже сделали ответчики (и, возможно, некоторые новые решения этого вопроса)...
14 ответов:
GolfScript - 181 символов
новые строки не нужны. Выход находится в стандартном выходе, хотя некоторые ошибки присутствуют в stderr.
должен быть заменен соответствующим символом 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_""~"{base}:B/3/~4*"nIOZTLSJR " ";:"*~;n%)n*~ 10R*+n*Образец Ввода/Вывода:
$ cat inp [ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] T2 Z6 I0 T7 $ cat inp|golfscript tetris.gs 2>/dev/null [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10сжатие тетрамино:
Части хранятся в виде трех базовых 8 цифр. Это простое двоичное представление, например,T=[7,2,0], S=[6,3,0], J=[2,2,3].[1]is используется дляIкусок в сжатии, но это явно установлено в[1,1,1,1]позже (т. е.4*в коде). Все эти массивы объединяются в один массив, который преобразуется в целое число, а затем в строку (база 126 для минимизации непечатаемых символов, длины и не встречается с utf8). Эта строка очень короткая:"R@1(XBc_".декомпрессия тогда проста. Сначала мы делаем базовое 126 преобразование, а затем базовое 8 преобразование (
"~"{base}/, т. е. перебираем"~"и сделать базовое преобразование для каждого элемента). Результирующий массив разбивается на группы по 3, массив дляIисправлена (3/~4*). Затем мы преобразуем каждый элемент в базу 2 и (после удаления нулей) заменяем каждую двоичную цифру символом этого индекса в строке" #"(2base{" #"=}%...-1%- обратите внимание, что нам нужно отменить массив в противном случае2станет"# "вместо" #").формат доски / части, падая части
Совет-это просто массив строк, по одной для каждой линии. Изначально над этим не делается никакой работы, поэтому мы можем сгенерировать его с помощьюn/(на входе. Части также представляют собой массивы строк, дополненные пробелами слева для их позиции X, но без конечных пробелов. Части отбрасываются путем добавления к массиву и непрерывного тестирования наличия столкновение.тестирование столкновений выполняется путем перебора всех символов в фигуре и сравнения с символом той же позиции на доске. Мы хотим рассмотреть
#+=и#+#как столкновения, поэтому мы проверяем, является ли ((piecechar&3)&boardchar) ненулевым. При выполнении этой итерации мы также обновляем (копию) платы с помощью ((piecechar&3) / boardchar), который правильно устанавливает значение для пар#+,+#,+[. Мы используем эта обновленная Доска, если есть столкновение после перемещения фигуры вниз по другой строке.удаление заполненных строк довольно просто. Мы удаляем все строки, для которых
"= "&return 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_""~"{base}:B/3/~4*"nIOZTLSJR " ";:"*~;n%)n*~ ]{n*n.}/10R*
Perl,
586 523 483 472 427 407 404 386 387 356353 символов(требуется 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,$/Edit 1: некоторые серьезные гольф, исправить ошибку вывода.
Edit 2: Некоторые встраивания, объединили две петли в одну для чистого сохранения (барабанная дробь...) 3 символа, разное гольф.
Edit 3: некоторое общее исключение подвыражения, небольшое постоянное слияние и настройка регулярного выражения.
Редактирование 4: изменено представление тетромино в упакованный битовый вектор, смешанная гольф.
Edit 5: более прямой перевод с буквы тетромино на индекс массива, использование непечатаемых символов, разное гольф.
Изменить 6: Исправлена ошибка очистки верхняя линия, введена в R3 (редактирование 2), замечена Nakilon. Используйте больше непечатаемых символов.
Редактировать 7: Используйтеvecдля получения данных тетрамино. Воспользоваться тем, что игровое поле имеет фиксированные размеры.ifутверждение =>ifмодификатор, слияние циклов редактирования 2 начинает окупаться. Используйте//для случая 0 баллов.
Изменить 8: исправлена еще одна ошибка, введен в Р6 (изменение 5), замечена Nakilon.
Изменить 9: Не создавайте новые ссылки при очистке строк, просто перемещение ссылок с помощью среза массива. Слияние двухmap'ы в один. Умнее регулярное выражение. "Умнее"for. Разное гольф.
Изменить 10: встроенный массив тетромино, добавлена прокомментированная версия.
Ruby -
427 408 398 369359t=[*$<] 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 shell script (
301304 символов)
обновление: Исправлена ошибка, связанная с частями, которые простираются в верхнюю строку. Кроме того, вывод теперь отправляется в standard out, и в качестве бонуса можно снова запустить скрипт, чтобы продолжить игру (в этом случае вы должны сами добавить общий балл).это включает непечатаемые символы, поэтому я предоставил дамп. Сохраните его как
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скрипт делать. Части тетромино представлены в виде последовательностей команд редактора 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 '#' < | wc -c } droppiece() { for y in `seq 1 5`; do echo -n $y | cat - | 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
Python:
504519 символов(решение 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,
357355353339330310309 символовd=0 e=[*$<] e.pop.split.map{|f|f="L337J557O77Z73S37I3333T75"[/#{f[j=0]}(\W*)/,1].bytes.map{|z|?+?*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отметим, что
0escapes (включая нулевые байты в третьей строке) должны быть заменены их фактическим непечатаемым эквивалентом.пример ввода:
[ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] T2 Z6 I0 T7использование:
ruby1.9 tetris.rb < inputили
ruby1.9 tetris.rb input
C,
727 [...] 596 581 556 517 496 471 461457 символовэто мой первый код гольф, я думаю, что количество символов может получить
многониже, было бы неплохо, если опытные игроки в гольф могут дать мне некоторые подсказки.
текущая версия также может обрабатывать игровые поля с различными размерами.вход может иметь разрывы строк как в формате DOS / Windows, так и в формате Unix.код был довольно прост перед оптимизация, тетромино хранятся в 4 целых числах, которые интерпретируются как (7*3)x4 битный массив, игровое поле хранится как есть, плитки отбрасываются и полные строки удаляются в начале и после каждого падения плитки.
я не был уверен, как считать символы, поэтому я использовал размер файла кода со всеми ненужными разрывами строк удалены.
EDIT 596= > 581: благодаря KitsuneYMG, все, кроме
%lsпредложение работало отлично, кроме того, я заметилputchвместоputcharможно использовать (getchкак-то не работает) и убрал все скобки в#define G.EDIT 581= > 556: не был удовлетворен оставшимся
forи вложенный элементFпетли, так что было некоторое слияние, изменение и удаление петель, довольно запутанным, но определенно стоит того.EDIT 556= > 517: наконец-то нашел способ сделать
aмассив int. НекоторыеN;слил сc, нет
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')требуется одна новая строка, и я посчитал ее как один символ.
кодовая страница браузера 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()))
тестирование
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переводы строк требуется, и по одному символу каждый.
не пытайтесь прочитать этот код. Имена переменных буквально выбираются случайным образом в поисках самого высокого сжатия (с разными именами переменных я видел целых 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суть в трех загадочных строках, которые я сказал, что объясню.
форма тетромино закодирована в шестнадцатеричном числе там. Каждый tetronimo это считается, что он занимает сетку ячеек 3x4, где каждая ячейка либо пуста (пробел), либо полна (знак числа). Каждая часть затем кодируется 3 шестнадцатеричными цифрами, каждая цифра описывает один 4-клеточный столбец. Наименьшие значащие цифры описывают самые левые столбцы, а наименьший значащий бит в каждой цифре описывает самую верхнюю ячейку в каждом столбце. Если бит равен 0, то эта ячейка пуста, иначе это '#'. Например,я tetronimo кодируется как
00F, С четыре бита наименее значащей цифры, установленной для кодирования четырех знаков числа в крайнем левом столбце, и T и131, С верхним битом, установленным слева и справа, и двумя верхними битами, установленными посередине.затем все шестнадцатеричное число сдвигается на один бит влево (умножается на два). Это позволит нам игнорировать самый нижний бит. Я объясню почему через минуту.
Итак, учитывая текущую часть от входа, мы находим индексируйте в это шестнадцатеричное число, где начинаются 12 бит, описывающие его форму, а затем сдвиньте это вниз, чтобы биты 1-12 (пропуская бит 0)
bitsпеременная описывает текущую часть.задание
dropопределяет, сколько строк из верхней части сетки кусок упадет перед посадкой на другие фрагменты куска. Первая строка определяет, сколько пустых ячеек находится в верхней части каждого столбца игрового поля, а вторая - самая низкая занятая ячейка в каждой колонке пьесы. Элементzipфункция возвращает список кортежей, где каждый кортеж состоит из nе ячейка из каждого элемента во входном списке. Итак, используя образец входной платы,zip(board[:6] + [full])вернутся:[ ('[', '[', '[', '[', '[', '[', '['), (' ', ' ', ' ', ' ', ' ', ' ', '#'), (' ', ' ', ' ', ' ', '#', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', ' ', ' ', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', '#', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', ' ', '#', '#'), (' ', ' ', ' ', ' ', '#', '#', '#'), (']', ']', ']', ']', ']', ']', ']') ]мы выбираем кортеж из этого списка, соответствующий соответствующему столбцу, и находим индекс первого
'#'в столбце. Вот почему мы добавили "полную" строку перед вызовомzip, так чтоindexбудет иметь разумный возврат (вместо того, чтобы выбрасывать исключение), когда столбец в противном случае пуст.тогда найти самый низкий
'#'в каждом столбце части мы сдвигаем и маскируем четыре бита, которые описывают этот столбец, а затем используемbinфункция, чтобы превратить это в строку единиц и нулей. Элементbinфункция возвращает только значащие биты, поэтому нам нужно только вычислить длину этой строки, чтобы найти самую низкую занятую ячейку (самый значительный бит набора). Этот
Python, 298 символов
бьет всех не -эзотерика язык решения до сих пор (Perl, Ruby, C, bash...)
... и даже не использует хитрость с кодовым замком.
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на тестовом примере
[ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] T2 Z6 I0 T7выводит
[ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10PS. Исправлена ошибка, указанная Nakilon по стоимости +5
Golfscript 260 символов
Я уверен, что это может быть улучшено, я вроде как новичок в Golfscript.
[39 26.2/0:{.(}:?~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*{'['*']'++}: ;n/0\~n+:|;0\{.'#' ={;)}{n+|+:|;}if\.}do;' ' n+\.@*|+$+:$;.,1-<:|;}c*|n?$*конец строк релевантны (там не должно быть одного в конце). Во всяком случае, вот некоторые из тестовых случаев, которые я использовал:
> 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обратите внимание, что во входном файле нет конца строки, конец строки нарушит сценарий как есть.
О'Caml
809782 символовopen String let w=length let c s=let x=ref 0in iter(fun k->if k='#'then incr x)s;!x open List let(@),g,s,p,q=nth,ref[],ref 0,(0,1),(0,2)let l=length let u=Printf.printf let rec o x i j=let a=map(fun s->copy s)!g in if snd(fold_left(fun(r,k)(p,l)->let z=c(a@r)in blit(make l '#')0(a@r)(i+p)l;if c(a@r)=z+l then r+1,k else r,false)(j-l x+1,true)x)then g:=a else o x i(j-1)and f x=let s=read_line()in if s.[1]='='then g:=rev x else f(sub s 1 10::x)let z=f [];read_line();;for i=0to w z/3 do o(assoc z.[i*3]['I',[p;p;p;p];'O',[q;q];'Z',[q;1,2];'T',[0,3;1,1];'L',[p;p;q];'S',[1,2;q];'J',[1,1;1,1;q]])(Char.code z.[i*3+1]-48)(l!g-1);let h=l!g in g:=filter(fun s->c s<>w s)!g;for i=1to h-(l!g)do incr s;g:=make 10' '::!g done;done;iter(fun r->u"[%s]\n"r)!g;u"[==========]\n";u"%d\n"(!s*10)
Common Lisp
667 657645 символовмоя первая попытка кодового гольфа, так что, вероятно, есть много трюков, которые я еще не знаю. Я оставил там несколько новых строк, чтобы сохранить некоторую остаточную "читаемость" (я посчитал новые строки как 2 байта, поэтому удаление 6 ненужных новых строк получает еще 12 символов).
в input сначала поместите фигуры, а затем поле.
(let(b(s 0)m(e'(0 1 2 3 4 5 6 7 8 9))) (labels((o(p i)(mapcar(lambda(j)(+ i j))p))(w(p r)(o p(* 13 r)))(f(i)(find i b)) (a(&aux(i(position(read-char)"IOZTLSJ")))(when i(push(o(nth i'((0 13 26 39)(0 1 13 14)(0 1 14 15)(0 1 2 14)(0 13 26 27)(1 2 13 14)(1 14 26 27)))(read))m)(a)))) (a)(dotimes(i 90)(if(find(read-char)"#=")(push i b)))(dolist(p(reverse m)) (setf b`(,@b,@(w p(1-(position-if(lambda(i)(some #'f(w p i)))e))))) (dotimes(i 6)(when(every #'f(w e i))(setf s(1+ s)b(mapcar(lambda(k)(+(if(>(* 13 i)k)13(if(<=(* 13(1+ i))k)0 78))k))b))))) (dotimes(i 6)(format t"[~{~:[ ~;#~]~}] "(mapcar #'f(w e i))))(format t"[==========] ~a0"s)))тестирование
T2 Z6 I0 T7 [ ] [ ] [ ] [ ] [ # # #] [ ## ######] [==========] [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10 NIL
Рубин
505 479 474 442 439426 символовпервая попытка. Сделали это с IronRuby. Я уверен, что это может быть улучшено, но я действительно должен получить некоторую работу сегодня!
p,q,r,s=(0..9),(0..2),(0..6),0 t=[*$<] f=p.map{|a|g=0;r.map{|b|g+=2**b if t[6-b][a+1]==?#};g} t.pop.split.map{|x|w,y=[15,51,306,562,23,561,113]["IOZTLSJ"=~/#{x[0]}/],x[1].to_i l=q.map{|d|r.inject{|b,c|f[d+y]&(w>>(d*4)&15-c+1)>0?c:b}}.max q.map{|b|f[b+y]|=w>>(b*4)&15-l} r.map{i=f.inject{|a,b|a&b};f.map!{|a|b=i^(i-1);a=((a&~b)>>1)+(a&(b>>1))};s+=i>0?10:0}} p.map{|a|r.map{|b|t[6-b][a+1]=f[a]&2**b>0??#:' '}} puts t,sтестирование
cat test.txt | ruby tetris.rb [ ] [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10Edit Теперь с помощью обычного Рубина. Получил выход на стены..
еще один в Руби,
:**573546 символовZ={I:?#*4,J:'#,###',L:'###,#',O:'##,##',S:'#,##, #',Z:' #,##,#',T:' #,##, #'} t=[*$<] R=->s{s.reverse} T=->m{m.transpose} a = T[R[t].join.scan /.#{'(\D)'*10}.$/] t.pop.split.each{|z| t,o=Z[z[0].to_sym].split(',').map{|x|x.split //},z[1].to_i r=0..t.size-1 y=r.map{|u|1+a[o+u].rindex(?#).to_i-t[u].count(' ')}.max (0..3).each{|i|r.each{|j|t[j][i]==?#&&a[o+j][y+i]=t[j][i]}}} s=0 a.each{|x|s=a.max_by(&:size).size;x[s-=1]||=' 'while s>0} a=R[T[a].reject{|x|x*''=~/[#]{10}/&&s+=10}.map{|x|?[+x*''+?]}[0..6]] puts (0..8-a.size).map{?[+' '*10+?]},a,sтестирование:
cat test.txt | ruby 3858384_tetris.rb [ ] [ ] [ ] [ ] [# ###] [# ### ] [##### ####] [==========] 10