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 +500
reputację, aby zwrócić uwagę na miłe wysiłki, które respondenci już podjęli (i być może nowe rozwiązania tego pytania) ...
źródło
Odpowiedzi:
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.
\10
należy zastąpić odpowiednim znakiem ASCII, aby program miał 181 znaków.Przykładowe I / O:
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 dlaI
kompresowanego 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 dlaI
jest 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 razie2
stanie 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).
źródło
Perl,
586523483472427407404386387356353znakó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).
Skomentowana wersja:
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
vec
do uzyskania danych tetromino. Skorzystaj z faktu, że boisko ma stałe wymiary.if
instrukcja =>if
modyfikator, 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
map
w jeden. Inteligentniejsze wyrażenie regularne. „Mądrzejszy”for
. Różne gry w golfa.Edycja 10: wbudowana tablica tetromino, dodano wersję z komentarzem.
źródło
Rubin -
427 408 398 369359źródło
Skrypt powłoki Bash (
301304 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
:Następnie w wierszu polecenia bash, najlepiej z
elvis
zamiastvim
instalowanym jakovi
:Jak to działa
Kod samorozpakowuje się, podobnie jak programy wykonywalne skompresowane przy użyciu
gzexe
skryptu. 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:
Oryginalny kod przed grą w golfa:
źródło
Python:
504519 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).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ć
L
i 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:
źródło
Ruby 1.9,
357355353339330310309 znakówZauważ, że
\000
znaki specjalne (w tym bajty zerowe w trzeciej linii) powinny zostać zastąpione ich rzeczywistymi niedrukowalnymi odpowiednikami.Przykładowe dane wejściowe:
Stosowanie:
lub
źródło
?\s
.C,
727 [...] 596 581 556 517 496 471 461457 znakówTo mój pierwszy golf kodowy, myślę, że liczba znaków może być
znacznieniż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
%ls
sugestii działało idealnie, dodatkowo zauważyłem, żeputch
zamiast tegoputchar
można użyć (getch
jakoś nie działa) i usunąłem wszystkie nawiasy w#define G
.EDYCJA 581 => 556: Nie był zadowolony z pozostałych
for
i zagnieżdżonychF
pę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
a
tablicy int. NiektórzyN;
połączyli się zc
,break
już nie .EDYCJA 496 => 471: Szerokość i wysokość boiska zostały naprawione.
EDYCJA 471 => 461: Drobne modyfikacje,
putchar
używane ponownie, ponieważputch
nie 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.
źródło
for
jako#define F(x,m) for(x=0;x++<m;)
? Działa na C # ...: PF(x,3){printf("%i",x}
Drukuje12
zamiast012
z tą zmianą. Można zmienić nafor(x=-1;x++<m;)
, ale to niczego nie zapisuje :)(c=getchar())
i usunąć wszystkie c = N linii, zapisując 6 znaków. O ile się nie mylę, powinieneś obniżyć t do 585Python 2.6+ -
334322316 znaków397368366 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
Znaki nowej linii muszą być w stylu uniksowym (tylko znaki nowej linii). Końcowy znak nowej linii w ostatniej linii jest opcjonalny.
Testować:
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)
bits
zmiennej opisywały bieżący kawałek.Zadanie
drop
okreś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.zip
Zwraca 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” wierszzip
, abyindex
uzyskać 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żywamybin
funkcji, aby przekształcić to w ciąg jedynek i zer.bin
Funkcja 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).bin
Funkcja 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
,0
i0
.bin(0xF)
jest'0b1111'
. Po zignorowaniu'0b'
mamy długość 4, co jest poprawne. Alebin(0x0)
jest0b0
. 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+3
w 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 bierzemymin
wynik, 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
for
pętla następująca po tych przypisaniach dodaje element do tablicy. Następniewhile
pę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.źródło
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.
Na przykładzie testowym
wyprowadza
PS. naprawiono błąd wskazany przez Nakilona kosztem +5
źródło
Golfscript 260 znaków
Jestem pewien, że można to poprawić, jestem trochę nowy w Golfscript.
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:
Zauważ, że w pliku wejściowym nie ma końca linii, koniec linii spowodowałby uszkodzenie skryptu.
źródło
O'Caml
809782 Charsźródło
Common Lisp
667 657645 znakówMoja 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.
Testowanie
źródło
Rubin
505 479 474 442 439426 znakówPierwsza próba. Zrobiłem to z IronRuby. Jestem pewien, że można to poprawić, ale naprawdę powinienem dziś popracować!
Testowanie
Edytuj teraz używając zwykłego rubinu. Mam wyjście ze ścian ...
źródło
Kolejny w Rubim,
: **573546 znakówTestowanie:
źródło
a.each{|x|s=a.max_by(&:size).size;x[s-=1]||=' 'while s>0}