Code Golf: Granie w Tetrisa

83

Podstawy:

Rozważ następujące tetromino i puste pole gry:

                                            0123456789
    IOZTLSJ []
                                           []
    # ## ## ### # ## # []
    # ## ## # # ## # []
    # ## ## []
    # []
                                           [==========]

Wymiary boiska są stałe. Liczby na górze są tutaj, aby wskazać numer kolumny (patrz także wejście).

Wejście:

1 . Otrzymujesz określone pole gry (na podstawie powyższego), które może być już częściowo wypełnione tetromino (może to być oddzielny plik lub dostarczone przez stdin).

Przykładowe dane wejściowe:

[]
[]
[]
[]
[# # #]
[## ######]
[==========]

2 . Otrzymujesz ciąg, który opisuje (oddzielony spacjami), w której kolumnie tetromino należy wstawić (i upuścić). Tetromino nie trzeba obracać. Dane wejściowe można odczytać ze standardowego wejścia.

Przykładowe dane wejściowe:

T2 Z6 I0 T7

Możesz założyć, że dane wejściowe są „dobrze sformułowane” (lub wytworzyć niezdefiniowane zachowanie, jeśli nie jest).

Wynik

Wyrenderuj wynikowe pole („pełne” wiersze muszą zniknąć) i wydrukuj liczbę punktów (każda opuszczona linia daje 10 punktów).

Przykładowe dane wyjściowe na podstawie przykładowego wejścia powyżej:

[]
[]
[]
[# ###]
[# ###]
[##### ####]
[==========]
10

Zwycięzca:

Najkrótsze rozwiązanie (według liczby znaków kodu). Przykłady użycia są fajne. Miłej gry w golfa!

Edycja : dodano nagrodę za +500reputację, aby zwrócić uwagę na miłe wysiłki, które respondenci już podjęli (i być może nowe rozwiązania tego pytania) ...

ChristopheD
źródło
5
@omouse: check meta.stackoverflow.com - golf code jest ogólnie dozwolony (w formie wiki społeczności)
ChristopheD
18
@omouse: Po to jest głosowanie za zamknięciem. Przeciągnięcie moderatorów tutaj przez oznaczenie pytania prawdopodobnie nie sprawi, że będziesz tak popularny, biorąc pod uwagę, że społeczność (niechętnie) zezwala na istnienie golfa kodowego (zobacz tag code-golf i meta dyskusje; to nic nowego) .
Mark Peters
8
@omouse: Off-topic! = spam. Nawet jeśli nie możesz zagłosować za zamknięciem, ta flaga spamu nie była wymagana.
BoltClock
3
Czekam na sportowca APL! Założę się, że da radę za 3,5 symbole
n8wrl
3
Wymiary mają być stałe, ale przykładowe dane wejściowe i puste pole mają różne wysokości. Jaka powinna być wysokość?
Nabb

Odpowiedzi:

27

GolfScript - 181 znaków

Nowe linie nie są konieczne. Dane wyjściowe są na standardowym wyjściu, chociaż w stderr występują pewne błędy.
\10należy zastąpić odpowiednim znakiem ASCII, aby program miał 181 znaków.

{):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*

Przykładowe I / O:

$ cat inp
[          ]
[          ]
[          ]
[          ]
[ #    #  #]
[ ## ######]
[==========]
T2 Z6 I0 T7
$ cat inp|golfscript tetris.gs 2>/dev/null
[          ]
[          ]
[          ]
[#      ###]
[#     ### ]
[##### ####]
[==========]
10

Kompresja Tetromino:
Kawałki są przechowywane jako trzy podstawowe cyfry 8. To jest prosta reprezentacja binarna, np T=[7,2,0], S=[6,3,0], J=[2,2,3]. [1]jest używany dla Ikompresowanego fragmentu, ale jest to jawnie ustawione na [1,1,1,1]później (tj. 4*w kodzie). Wszystkie te tablice są łączone w jedną tablicę, która jest konwertowana na liczbę całkowitą, a następnie ciąg (podstawa 126, aby zminimalizować niedrukowalne znaki, długość i brak napotkania utf8). Ciąg ten jest bardzo krótki: "R@1(XBc_".

Wtedy dekompresja jest prosta. Najpierw wykonujemy konwersję podstawową 126, a następnie konwersję podstawową 8 ( "~\10"{base}/tj. Iterujemy "~\10"i wykonujemy konwersję podstawową dla każdego elementu). Otrzymana tablica jest podzielona na grupy po 3, a tablica dla Ijest ustalona ( 3/~4*). Następnie konwertujemy każdy element na podstawę 2 i (po usunięciu zer) zastępujemy każdą cyfrę binarną znakiem tego indeksu w ciągu " #"( 2base{" #"=}%...-1%- pamiętaj, że musimy odwrócić tablicę, w przeciwnym razie 2stanie się "# "zamiast " #").

Format
tablicy / figury, upuszczanie kawałków Tablica to po prostu tablica ciągów, po jednym dla każdej linii. Na początku nie jest wykonywana żadna praca nad tym, więc możemy wygenerować go n/(na wejściu. Kawałki są również tablicami ciągów, wypełnionych spacjami po lewej stronie dla ich pozycji X, ale bez spacji końcowych. Fragmenty są upuszczane przez dołączanie do macierzy i ciągłe testowanie, czy nie ma kolizji.

Testowanie kolizji odbywa się poprzez iterację wszystkich postaci w figurze i porównanie z postacią na tej samej pozycji na planszy. Chcemy traktować #+ =i #+ #jako kolizje, więc sprawdzamy, czy ((piecechar & 3) & boardchar) jest niezerowe. Wykonując tę ​​iterację, aktualizujemy również (kopię) tablicę za pomocą ((piecechar & 3) | boardchar), co poprawnie ustawia wartość dla par #+ , + #, + [. Używamy tej zaktualizowanej planszy, jeśli nastąpi kolizja po przesunięciu elementu w dół o kolejny rząd.

Usuwanie wypełnionych rzędów jest dość proste. Usuwamy wszystkie wiersze, dla których "= "&zwraca wartość false. Wypełniony wiersz nie będzie miał żadnego =lub , więc koniunkcja będzie pustym ciągiem, co równa się fałszowi. Następnie liczymy liczbę usuniętych wierszy, dodajemy liczbę do wyniku i dodajemy tyle "[ ... ]"s. Generujemy to zwięźle, biorąc pierwszy rząd siatki i zastępując #go .

Bonus
Ponieważ obliczamy, jak będzie wyglądać szachownica w każdej pozycji spadającego pionka, możemy zachować je na stosie zamiast je usuwać! W sumie o trzy znaki więcej, możemy wyświetlić wszystkie te pozycje (lub dwa znaki, jeśli mamy stany tablicy z pojedynczymi odstępami).

{):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*
Nabb
źródło
Trochę ekstremalnego golfa w kodowaniu, które ma miejsce tutaj (nie sądziłem, że można to zrobić w mniej niż 200 znakach). Dobra robota!
ChristopheD
8
Niesamowity. Żałuję, że nie rozumiem GolfScript. Czekaj ... nie, nie mam.
P Daddy,
26

Perl, 586523483472427407404386387356353 znaków

(Potrzebuje Perl 5.10 dla //operatora zdefiniowanego lub ).

Pobiera wszystkie dane wejściowe ze standardowego wejścia. Nadal potrzebuje poważnego golfa.
Zauważ, że ^ Q reprezentuje ASCII 17 (DC1 / XON), ^ C reprezentuje ASCII 3, a ^ @ reprezentuje 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,$/

Skomentowana wersja:

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,$/

Edycja 1: poważna gra w golfa, napraw błąd wyjścia.
Edycja 2: trochę inlining, połączono dwie pętle w jedną, aby zaoszczędzić netto (rolka perkusyjna ...) 3 znaków, misc golfing.
Edycja 3: niektóre typowe eliminacje podwyrażeń, trochę ciągłe scalanie i modyfikacja wyrażenia regularnego.
Edycja 4: zmieniono reprezentację tetromino na upakowany wektor bitowy, misc golfing.
Edycja 5: bardziej bezpośrednie tłumaczenie z litery tetromino na indeks tablicy, używanie niedrukowalnych znaków, różne gry w golfa.
Edycja 6: naprawiono błąd czyszczenia górnej linii, wprowadzony w r3 (edycja 2), zauważony przez Nakilon. Użyj więcej znaków niedrukowalnych.
Edycja 7: użyj vecdo uzyskania danych tetromino. Skorzystaj z faktu, że boisko ma stałe wymiary. ifinstrukcja =>ifmodyfikator, scalanie pętli edycji 2 zaczyna przynosić efekty. Użyj //dla przypadku z wynikiem 0.
Edycja 8: naprawiono inny błąd, wprowadzony w r6 (edycja 5), ​​zauważony przez Nakilona.
Edycja 9: nie twórz nowych odniesień podczas czyszczenia linii, po prostu przesuwaj odniesienia poprzez cięcie tablic. Połącz dwa mapw jeden. Inteligentniejsze wyrażenie regularne. „Mądrzejszy” for. Różne gry w golfa.
Edycja 10: wbudowana tablica tetromino, dodano wersję z komentarzem.

Ninjalj
źródło
Działa bardzo przyjemnie (i już przy niezłej liczbie znaków jak na ten nietrywialny problem). Jedną małą osobliwością jest to, że mój perl (perl, v5.10.0 zbudowany dla darwin-thread-multi-2level) wydaje się drukować wynik dwukrotnie (wejście potokowe).
ChristopheD
@ChristopheD: naprawiono zduplikowane wyjście, drukowałem wewnątrz mojej głównej pętli, ale tylko dla linii bez pola gry. Prawdopodobnie miałeś za dużo nowej linii :)
ninjalj
4 więcej znaków, aby pokonać Pythona !!
Vivin Paliath
1
Jeszcze się nie poddałem perl! xD (chociaż chciałbym teraz zobaczyć też inne rozwiązania ..)
poke
@Nakilon: Dobry chwyt! Masz tam ładny przypadek testowy.
ninjalj
24

Rubin - 427 408 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
Nakilon
źródło
Bardzo fajne rozwiązanie! Będę musiał przyjrzeć się, jak dokładnie zakodowałeś formy teromino (wygląda to bardzo zwięźle).
ChristopheD
3
Naprawdę chciałbym zobaczyć rozszerzone wyjaśnienie tego kodu. Wygląda tak chory… Nie mogę tego obejść.
Nils Riedemann
1
@Nils Riedemann, piszę wyjaśnienie w tej chwili, ale myślę o opublikowaniu go teraz lub po ogłoszeniu zwycięzcy) W każdym razie raz napiszę i odpowiem na wszystkie pytania, ponieważ jest to wiki społeczności z głównym pomysłem, aby być przydatnym)
Nakilon
W przypadku Debiana Ruby 1.9.2dev (2010-07-30) nie udaje się to w przypadku Twojego przypadku testowego pod adresem paste.org.ru/?6ep1on. Poza tym zawsze rozszerza pole gry do dziesięciu linii?
ninjalj
@ninjalj, ruby ​​1.9.2p0 (2010-08-18) [i386-mingw32] paste.org.ru/?1qnjhj Wygląda dobrze. Przypuszczam, że szerokość 10 to standard Tetrisa.
Nakilon
17

Skrypt powłoki Bash ( 301 304 znaków)


AKTUALIZACJA: Naprawiono błąd związany z elementami wystającymi do górnego rzędu. Ponadto wynik jest teraz wysyłany do standardowego wyjścia, a jako bonus można ponownie uruchomić skrypt, aby kontynuować grę (w takim przypadku należy samodzielnie zsumować całkowity wynik).

Obejmuje to znaki niedrukowalne, więc przygotowałem zrzut szesnastkowy. Zapisz jako 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....

Następnie w wierszu polecenia bash, najlepiej z elviszamiast viminstalowanym jako 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

Jak to działa

Kod samorozpakowuje się, podobnie jak programy wykonywalne skompresowane przy użyciu gzexeskryptu. Kawałki Tetromino są reprezentowane jako sekwencje poleceń edytora vi. Liczenie znaków służy do wykrywania kolizji, a liczenie wierszy służy do obliczania wyniku.

Rozpakowany kod:

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

Oryginalny kod przed grą w golfa:

#!/bin/bash

mkpieces() {
    pieces=('[email protected].' '2r@jh.' '2r@j.' '3r@jh1.' '[email protected].' 'l2r@j2h.' '[email protected].')
    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
PleaseStand
źródło
1
Plik bash, dekompresujący i uruchamiający vi .. nie jestem pewien co do legalności takiej obrzydliwości ... ale robi wrażenie, +1. brawo dla pana.
Michael Anderson
Zajmuje absurdalnie długi czas, aby zakończyć, a następnie generuje nieprawidłowe wyjście dla przypadku testowego "T2 Z6 I0 T7 T2 Z6 T2 I5 I1 I0 T4 O8 T1 T6 T3 Z0 I9 I6 O7 T3 I2 O0 J8 L6 O7 O4 I3 J8 S6 O1 I0 O4 "(ta sama karta jak przykładowe wejście). Co więcej, tysiące linii śmieci zostaną wyłączone podczas przesyłania, a wynik działania tablicy prawdopodobnie powinien tam trafić.
Nabb
Byłoby znacznie szybciej, gdyby zamiast Vima jako vi zainstalowano Elvisa.
wstać
2
@Nabb: Właśnie naprawiłem wszystkie te problemy kosztem tylko trzech znaków.
odstawić
Łał. To całkiem imponujące nadużycie basha.
P Daddy,
13

Python: 504 519 znaków

(Rozwiązanie Python 3) Obecnie wymaga ustawienia wejścia w formacie pokazanym na górze (kod wejściowy nie jest liczony). Rozszerzę później, aby czytać z pliku lub stdin. Teraz działa z podpowiedzią, po prostu wklej dane wejściowe (łącznie 8 linii).

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')

Nie jestem pewien, czy mogę tam zaoszczędzić znacznie więcej. Dość wiele znaków jest traconych podczas transformacji do pól bitowych, ale to oszczędza dużo więcej znaków niż praca z ciągami. Nie jestem też pewien, czy mogę tam usunąć więcej białych znaków, ale spróbuję później.
Nie będzie w stanie go bardziej zredukować; po rozwiązaniu opartym na polu bitowym wróciłem do łańcuchów, ponieważ znalazłem sposób na bardziej skompresowanie (zapisanie 8 znaków na polu bitowym!). Ale biorąc pod uwagę, że zapomniałem dołączyć Li miałem błąd z punktami w środku, liczba moich znaków tylko rośnie, westchnienie ... Może znajdę później coś, co skompresuje to trochę bardziej, ale myślę, że jestem blisko końca. Aby zapoznać się z oryginalnym i skomentowanym kodem, zobacz poniżej:

Orginalna wersja:

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] ) )
poke
źródło
Myślę, że to nie jest poprawne. Nie ma reguły mówiącej, że tylko dolna linia może zniknąć, ale sądząc po twoich komentarzach, sprawdzasz tylko tę linię.
Michael Madsen
Proszę, wprowadź dane jak w zadaniu. Mam na myśli wejście z pliku lub STDIN.
Nakilon
6
Czy nie podoba ci się, że nawet zminimalizowany kod Pythona jest nadal dość czytelny?
EMP
@Evgeny, tylko w porównaniu z Perlem lub Malbolge)
Nakilon
Cóż, miałem na myśli „czytelny” w stosunku do innych odpowiedzi kodowych!
EMP,
13

Ruby 1.9, 357 355 353 339 330 310 309 znaków

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

Zauważ, że \000znaki specjalne (w tym bajty zerowe w trzeciej linii) powinny zostać zastąpione ich rzeczywistymi niedrukowalnymi odpowiednikami.

Przykładowe dane wejściowe:

[          ]
[          ]
[          ]
[          ]
[ #    #  #]
[ ## ######]
[==========]
T2 Z6 I0 T7

Stosowanie:

ruby1.9 tetris.rb < input

lub

ruby1.9 tetris.rb input
Ventero
źródło
Kolejny sposób na upuszczenie tetrominos i trzymanie całego szkła w szyku, nawet z obramowaniami ... fajnie. Teraz będziesz liderem Ruby / Perl. PS: Nie wiedziałem o tym ?\s.
Nakilon
12

C, 727 [...] 596 581 556 517 496 471 461 457 znaków

To mój pierwszy golf kodowy, myślę, że liczba znaków może być znacznie niższa, byłoby miło, gdyby doświadczeni golfiści mogli mi dać kilka wskazówek.

Obecna wersja radzi sobie również z boiskami o innych wymiarach. Wejście może mieć podziały wierszy zarówno w formacie DOS / Windows, jak i Unix.

Kod był dość prosty przed optymalizacją, tetromino są przechowywane w 4 liczbach całkowitych, które są interpretowane jako (7 * 3) x4-bitowa tablica, pole gry jest przechowywane tak, jak jest, płytki są upuszczane, a całe linie są usuwane na początku i po każdym spadek płytek.

Nie byłem pewien, jak liczyć znaki, więc użyłem rozmiaru pliku kodu z usuniętymi wszystkimi niepotrzebnymi podziałami wierszy.

EDYCJA 596 => 581: Dzięki KitsuneYMG wszystko oprócz %lssugestii działało idealnie, dodatkowo zauważyłem, że putchzamiast tego putcharmożna użyć ( getchjakoś nie działa) i usunąłem wszystkie nawiasy w #define G.

EDYCJA 581 => 556: Nie był zadowolony z pozostałych fori zagnieżdżonych Fpętli, więc nastąpiło pewne scalanie, zmienianie i usuwanie pętli, dość zagmatwane, ale zdecydowanie warto.

EDYCJA 556 => 517: Wreszcie znalazłem sposób na utworzenie atablicy int. Niektórzy N;połączyli się z c, breakjuż nie .

EDYCJA 496 => 471: Szerokość i wysokość boiska zostały naprawione.

EDYCJA 471 => 461: Drobne modyfikacje, putcharużywane ponownie, ponieważ putchnie jest to funkcja standardowa.

EDYCJA: Naprawiono błąd, kompletne linie zostały usunięte przed upuszczeniem płytek zamiast po , więc kompletne linie można było pozostawić na końcu. Poprawka nie zmienia liczby znaków.

#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);}
sznaadera
źródło
1
Nie możesz zdefiniować forjako #define F(x,m) for(x=0;x++<m;)? Działa na C # ...: P
BrunoLM
@BrunoLM: Dzięki, ale to nie zadziała, np. F(x,3){printf("%i",x}Drukuje 12zamiast 012z tą zmianą. Można zmienić na for(x=-1;x++<m;), ale to niczego nie zapisuje :)
schnaader
1
Jeśli napisałeś kod poprawnie, jeśli kompilujesz jako C, nie musisz dołączać stdio.h (chyba że coś przeoczyłem?). Zapisz kilka znaków :)
1
Możesz zamienić swoją definicję N na (c=getchar())i usunąć wszystkie c = N linii, zapisując 6 znaków. O ile się nie mylę, powinieneś obniżyć t do 585
KitsuneYMG
1
type domyślnie int także dla zmiennych, przynajmniej dla C89.
ninjalj
8

Python 2.6+ - 334 322 316 znaków

397 368 366 nieskompresowanych znaków

#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')

Wymagany jest pojedynczy znak nowej linii, a policzyłem go jako jeden znak.

Mumbo jumbo strony kodowej przeglądarki może uniemożliwić pomyślne skopiowanie i wklejenie tego kodu, więc możesz opcjonalnie wygenerować plik z tego kodu:

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()))

Testowanie

intetris

[]
[]
[]
[]
[# # #]
[## ######]
[==========]
T2 Z6 I0 T7

Znaki nowej linii muszą być w stylu uniksowym (tylko znaki nowej linii). Końcowy znak nowej linii w ostatniej linii jest opcjonalny.

Testować:

> python golftris.py <intetris
[]
[]
[]
[# ###]
[# ###]
[##### ####]
[==========]
10

Ten kod rozpakowuje oryginalny kod i wykonuje go za pomocą exec. Ten zdekompresowany kod waży 366 znaków i wygląda następująco:

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

Nowe linie są wymagane, a każda z nich ma jeden znak.

Nie próbuj czytać tego kodu. Nazwy zmiennych są dosłownie wybierane losowo w poszukiwaniu największej kompresji (przy różnych nazwach zmiennych widziałem aż 342 znaki po kompresji). Bardziej zrozumiała wersja jest następująca:

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

Sedno tkwi w trzech zagadkowych liniach, które powiedziałem, że wyjaśnię.

Kształt tetromino jest tam zakodowany w liczbie szesnastkowej. Uważa się, że każde tetronimo zajmuje siatkę komórek 3x4, gdzie każda komórka jest pusta (spacja) lub pełna (znak liczby). Każdy element jest następnie kodowany za pomocą 3 cyfr szesnastkowych, przy czym każda cyfra opisuje jedną kolumnę 4-komórkową. Najmniej znaczące cyfry opisują skrajne lewe kolumny, a najmniej znaczący bit w każdej cyfrze opisuje najwyższą komórkę w każdej kolumnie. Jeśli bit jest równy 0, to ta komórka jest pusta, w przeciwnym razie jest to „#”. Na przykład I tetronimo jest zakodowane jako 00F, z czterema bitami najmniej znaczącej cyfry ustawionymi do kodowania czterech znaków liczbowych w skrajnej lewej kolumnie, a T jest131, z górnym bitem ustawionym po lewej i prawej stronie, a dwa górne bity ustawione w środku.

Cała liczba szesnastkowa jest następnie przesuwana o jeden bit w lewo (pomnożona przez dwa). To pozwoli nam zignorować najniższy bit. Za minutę wyjaśnię dlaczego.

Więc biorąc pod uwagę bieżący fragment z wejścia, znajdujemy indeks w tej liczbie szesnastkowej, w której zaczyna się 12 bitów opisujących jego kształt, a następnie przesuwamy go w dół, tak aby bity 1–12 (przeskakując bit 0) bitszmiennej opisywały bieżący kawałek.

Zadanie dropokreśla, ile rzędów od góry siatki kawałek spadnie przed wylądowaniem na innych fragmentach kawałka. W pierwszym wierszu znajduje się liczba pustych komórek na górze każdej kolumny pola gry, a w drugim najniżej zajętej komórce w każdej kolumnie elementu. zipZwraca listę krotki, gdzie każdy krotkę składającą się z n -tego komórki z każdej pozycji z listy wejściowego. Tak więc, używając przykładowej karty wejściowej, zip(board[:6] + [full])zwróci:

[
 ('[', '[', '[', '[', '[', '[', '['),
 (' ', ' ', ' ', ' ', ' ', ' ', '#'),
 (' ', ' ', ' ', ' ', '#', '#', '#'),
 (' ', ' ', ' ', ' ', ' ', '#', '#'),
 (' ', ' ', ' ', ' ', ' ', ' ', '#'),
 (' ', ' ', ' ', ' ', ' ', '#', '#'),
 (' ', ' ', ' ', ' ', ' ', '#', '#'),
 (' ', ' ', ' ', ' ', '#', '#', '#'),
 (' ', ' ', ' ', ' ', ' ', '#', '#'),
 (' ', ' ', ' ', ' ', ' ', '#', '#'),
 (' ', ' ', ' ', ' ', '#', '#', '#'),
 (']', ']', ']', ']', ']', ']', ']')
]

Z tej listy wybieramy krotkę odpowiadającą odpowiedniej kolumnie i znajdujemy indeks pierwszej '#'w kolumnie. Dlatego przed wywołaniem dodaliśmy „pełny” wiersz zip, aby indexuzyskać sensowny zwrot (zamiast rzucać wyjątek), gdy kolumna jest pusta.

Następnie, aby znaleźć najniższą '#'w każdej kolumnie elementu, przesuwamy i maskujemy cztery bity opisujące tę kolumnę, a następnie używamy binfunkcji, aby przekształcić to w ciąg jedynek i zer. binFunkcja zwraca tylko znaczących bitów, więc potrzebujemy tylko obliczyć długość tego łańcucha, aby znaleźć najniższe zajętej komórki (najbardziej znaczący bit set). binFunkcja poprzedza również '0b', więc musimy odjąć to. Ignorujemy również najmniej znaczący fragment. Dlatego liczba szesnastkowa jest przesuwana o jeden bit w lewo. Ma to na celu uwzględnienie pustych kolumn, których reprezentacje łańcuchowe miałyby taką samą długość jak kolumna z pełną tylko górną komórką (na przykład element T ).

Na przykład, kolumny I Tetromino, jak wspomniano wcześniej, są F, 0i 0. bin(0xF)jest '0b1111'. Po zignorowaniu '0b'mamy długość 4, co jest poprawne. Ale bin(0x0)jest 0b0. Po zignorowaniu '0b'nadal mamy długość '1, co jest niepoprawne. Aby to uwzględnić, dodaliśmy na końcu dodatkowy fragment, abyśmy mogli zignorować ten nieznaczący fragment. Stąd +3w kodzie jest tam, aby uwzględnić dodatkową długość zajmowaną przez '0b'początek i nieznaczny bit na końcu.

Wszystko to dzieje się w wyrażeniu generatora dla trzech kolumn ( (0,1,2)), a my bierzemy minwynik, aby znaleźć maksymalną liczbę wierszy, które może upuścić element, zanim dotknie dowolnej z trzech kolumn.

Reszta powinna być dość łatwa do zrozumienia, czytając kod, ale forpętla następująca po tych przypisaniach dodaje element do tablicy. Następnie whilepętla usuwa pełne wiersze, zastępując je pustymi wierszami u góry i podlicza wynik. Na koniec plansza i punktacja są drukowane na wyjściu.

P Tatusiu
źródło
6

Python, 298 znaków

Pokonuje wszystkie dotychczas nie- ezoteryczne rozwiązania językowe (Perl, Ruby, C, bash ...)


... i nawet nie używa szykanowania związanego z kompresowaniem kodu.

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

Na przykładzie testowym

[          ]
[          ]
[          ]
[          ]
[ #    #  #]
[ ## ######]
[==========]
T2 Z6 I0 T7

wyprowadza

[          ]
[          ]
[          ]
[#      ###]
[#     ### ]
[##### ####]
[==========]
10

PS. naprawiono błąd wskazany przez Nakilona kosztem +5

Nas Banov
źródło
To całkiem imponujący kod. Naprawienie tego zajmie 14 znaków więcej ( ideone.com/zeuYB ), chyba że istnieje lepszy sposób, ale mimo to pokonuje wszystko oprócz GolfScript i Bash. To z pewnością sprytne rozwiązanie.
P Daddy
Tak, absolutnie bardzo dobre rozwiązanie!
ChristopheD
@Nakilon: dzięki, oczywiście to przegapiłem. fixed @ cost 293-> 298
Nas Banov
@P Tatusiu, dzięki - znalazłem sposób na wprowadzenie poprawki w bash & toolchain, aby zachować szczerość mówiąc „wszystko nie-ezoteryczne” :)
Nas Banov
@Nabb: aby kod był krótszy, został napisany z uwzględnieniem pewnych ograniczeń. coś jak 33 tetrominos max i 99 line drop max. Można go łatwo przedłużyć w cenie +3. Albo za niską cenę :), ograniczenia można całkowicie znieść. BTW, to jest świetny przykład tego, jak posiadanie zestawu testowego mogłoby wyjaśnić specyfikację (co nękałem ChristopheraD w komentarzach)
Nas Banov
5

Golfscript 260 znaków

Jestem pewien, że można to poprawić, jestem trochę nowy w 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?$*

Końcówki wierszy są istotne (nie powinno ich być na końcu). W każdym razie, oto kilka przypadków testowych, z których korzystałem:

> 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

Zauważ, że w pliku wejściowym nie ma końca linii, koniec linii spowodowałby uszkodzenie skryptu.

coderaj
źródło
2
/ me uważa, że ​​GolfScript nie jest prawdziwym językiem konkursowym ... To tylko biblioteka, ukształtowana prosto do zadań golfowych ... Rozmiar tej biblioteki można dodać do rozmiaru kodu golfscript ...
Nakilon
4
@Nakilon - Czy nie możesz powiedzieć czegoś podobnego o czymś, co nie jest napisane w surowym języku maszynowym? :) Interpreter Pythona to tylko biblioteka, dodaj jej rozmiar do swojego wpisu. </sarcasm>
bta,
2
@Nakilon: to tylko tłumacz. Można to napisać w jakimkolwiek innym języku; czy nadal powiedziałbyś, że Golfscript nie jest prawdziwym językiem?
Michael Foukarakis
1
@Nabb: Dzięki, doszedłem do wniosku, że brakuje mi kilku sztuczek ... Nie czuj się źle, nie zawracałem sobie głowy zrozumieniem mojego kodu :).
coderaj
1
@Michael Foukarakis, mogę w ciągu 1 minuty napisać własnego tłumacza, który rozwiąże to zadanie jednym znakiem, więc co z tego?
Nakilon
4

O'Caml 809 782 Chars

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)
Jessicah
źródło
4

Common Lisp 667 657 645 znaków

Moja pierwsza próba gry w code-golfa, więc prawdopodobnie istnieje wiele sztuczek, których jeszcze nie znam. Zostawiłem tam kilka nowych linii, aby zachować resztkową "czytelność" (liczyłem nowe linie jako 2 bajty, więc usunięcie 6 niepotrzebnych nowych linii daje 12 dodatkowych znaków).

W danych wejściowych najpierw umieść kształty, a następnie pole.

(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)))

Testowanie

T2 Z6 I0 T7
[          ]
[          ]
[          ]
[          ]
[ #    #  #]
[ ## ######]
[==========]
[          ]
[          ]
[          ]
[#      ###]
[#     ### ]
[##### ####]
[==========]
10
NIL
lpetru
źródło
Nie za krótko, ale +1 za brzydotę! Wyobrażam sobie, że tak wyglądałaby zupa alfabetyczna, gdyby była umieszczona w nawiasach.
P Daddy,
@P Daddy: Dzięki. Tak, pewnie tak by to wyglądało :).
lpetru
2

Rubin 505 479 474 442 439 426 znaków

Pierwsza próba. Zrobiłem to z IronRuby. Jestem pewien, że można to poprawić, ale naprawdę powinienem dziś popracować!

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

Testowanie

cat test.txt | ruby tetris.rb
[          ]
[          ]
[          ]
[          ]
[#      ###]
[#     ### ]
[##### ####]
[==========]
10

Edytuj teraz używając zwykłego rubinu. Mam wyjście ze ścian ...

Mongus Pong
źródło
Jeszcze jeden Rubista, fajnie! Ale zrób szklankę wokół cegieł.
Nakilon
1

Kolejny w Rubim, 573 546 znaków

: **

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

Testowanie:

cat test.txt | ruby 3858384_tetris.rb
[          ]
[          ]
[          ]
[          ]
[#      ###]
[#     ### ]
[##### ####]
[==========]
10
glebm
źródło
Naprawionoa.each{|x|s=a.max_by(&:size).size;x[s-=1]||=' 'while s>0}
glebm