Napisz najkrótszy program, aby przekształcić dowolną sztukę ASCII w animowaną scenę śnieżną, która zaczyna się formować z opadającego śniegu ( przykład niezakończonego golfa JavaScript ostatnio zaktualizowany 2011-12-19).
Specyfikacja wejściowa : Twój program musi akceptować dowolne kombinacje spacji, gwiazdek i znaków nowej linii. Dane wejściowe będą zawierać maksymalnie 23 wiersze i 80 znaków w wierszu. Nie będzie pustych linii, ale linie mogą składać się tylko z białych znaków. Pojedyncza nowa linia zostanie dołączona i należy ją zignorować.
Dane wyjściowe : wyprowadzaj znaki ASCII (spacje, gwiazdki) i kody sterujące (znaki powrotu karetki, znaki linii, kody specjalne ANSI itp.) Dla konsoli tekstowej systemu operacyjnego lub emulatora terminala, dopóki użytkownik ręcznie nie zakończy programu. Możesz założyć, że okno terminala ma 80x24 znaków, jeśli twój system operacyjny pozwala na to ustawienie.
Zasady :
- Animacja musi być płynna i szybka (preferowane 15 fps).
- Gęstość śniegu musi wynosić od 5% do 15%.
- Nie więcej niż jeden ekran śniegu może przewijać się na sekundę. (Oznacza to, że w ciągu jednej sekundy można dodać nie więcej niż 24 linie nowego śniegu).
- Śnieg nie może wykazywać żadnego widocznego wzoru, gdy wchodzi do górnej części ekranu; musi wyglądać losowo.
- Program musi jak najszybciej wypełnić wszystkie rzędy ekranu śniegiem; wstępne wypełnienie poszczególnych wierszy ekranu nie może być oczywiste dla widza.
- Lewy dolny róg wejściowej grafiki ASCII musi znajdować się w lewym dolnym rogu ekranu (rysunek 1 dla dalszego wyjaśnienia).
- Obszar wewnątrz lub pod grafiką ASCII nie może być na stałe wypełniony gwiazdkami. Jednak gwiazdki mogą (ale nie są wymagane) przewijać ten obszar.
- Śnieg nie może gromadzić się na dole ekranu lub na istniejącym śniegu, z wyjątkiem przypadków pokazanych na wejściu.
- Dolne spacje muszą być wypełnione przed górnymi, ponieważ wypełnianie spacji w odwrotnej kolejności powoduje, że animacja choinki wygląda zupełnie inaczej niż wynik mojego oryginalnego kodu. (dodano 2011-12-20)
Wesołych świąt!
Rysunek 1: oznaczone obszary ekranu 80x24
---------------------------New snow added on this line--------------------------
|
|
----------------------------------------------------------+ |
**** | |
Snow MUST fall Snow MAY fall ----------------> **** | |
through this through these **** **** | Snow MUST fall |
area. areas of a **** **** | through this |
completed \---------> **** ****| area. |
ASCII art scene. \ *** **** ****| |
area \ \ ******* **** ****| |
\ \ ******** *** ***| (ALL CAPS terms |
(located in \ \--> ********* *** | have standard |
lower left \ ******* ****** MAY | RFC 2119 |
corner of \ ************* ** fall | meanings.) |
screen) \ *********** here | |
*** +---> **** *** | |
*** | **************** *** | |
| Snow MUST fall *** | **************** *** | |
| through this *** +---> *** | |
| area. *** | **************** *** | |
--+---------------------+*** +---> ***+----+------------------+--
| Snow MUST NOT |****************************| Snow MUST NOT |
V accumulate here. |****************************| accumulate here. V
Przykładowe dane wejściowe
Kod Banner Golf
****** ******* ******** ******** ****** ******* ** ********
** ** ** ** ** ** ** ** ** ** ** ** **
** ** ** ** ** ** ** ** ** ** **
** ** ** ** ** ****** ** **** ** ** ** ******
** ** ** ** ** ** ** ** ** ** ** **
** ** ** ** ** ** ** ** ** ** ** ** **
****** ******* ******** ******** ****** ******* ******** **
Logo przepełnienia stosu
****
****
**** ****
**** ****
**** ****
*** **** ****
******* **** ****
******** *** ***
********* ***
******* ******
************* **
***********
*** **** ***
*** **************** ***
*** **************** ***
*** ***
*** **************** ***
*** ***
****************************
****************************
Choinki
*
*** *
* ***** ***
*** ******* * *****
***** ********* *** *
* *********** *****
* ************* *******
* *** *************** * *
*** ***** ***************** ***
***** ******* ******************* *****
******* * ********************* *******
********* * *********
* *
Odpowiedzi:
Perl, 196/239 znaków
To rozwiązanie różni się od twojego przykładu JS tym, że wzorzec jest wypełniany od góry do dołu, a nie od dołu do góry, ale zakładam, że jest OK, ponieważ nic nie powiedziałeś o tym w regułach.
Trywialną redukcję o 1 znak można uzyskać zastępując
\e
dosłowny znak ESC, ale znacznie utrudnia to czytanie i edycję kodu.Aktualizacja: I nie udało się wymyślić wersji, która wypełnia wzorzec z dołu do góry, a nie pozwala śnieg spadnie przez wypełnionymi częściami wzór, jak w przykładzie realizacji JS, kosztem 43 dodatkowych znaków:
Zastąpienie
($s[$_]&=~$f[$_])
po prostu$s[$_]
uratuje 11 znaków, pozwalając padającemu śniegowi przejść przez wypełnione części wzoru (co odpowiada specyfikacji, ale nie przykładowej implementacji).OK, ponieważ nadal wydaje mi się, że prowadzę wyścig po tygodniu, chyba powinienem wyjaśnić, jak działa moje rozwiązanie, aby zachęcić do większej konkurencji. (Uwaga: to wyjaśnienie dotyczy odgórnej wersji wypełniania o wielkości 196 znaków. Mogę ją zmienić, aby uwzględnić inną wersję później).
Po pierwsze, jedną wielką sztuczką, na której opiera się moje rozwiązanie, jest to, że ze względu na sposób ułożenia kodów znaków ASCII, 1-bit w kodzie ASCII dla spacji okazuje się być podzbiorem tych w kodzie dla gwiazdka.
Zatem prawdziwe są następujące wyrażenia:
" " & "*" eq " "
i" " | "*" eq "*"
. To pozwala mi używać bitowych operacji na łańcuchach do łączenia statycznych i ruchomych części sceny bez konieczności zapętlania poszczególnych znaków.Tak więc, nie wspominając o tym, przejdźmy do kodu. Oto jego wersja bez golfa:
Pierwszy wiersz ustawia tablice
@f
(dla „ustalonego”) i@p
(dla „wzoru”).@f
utworzy stałą część wyświetlacza i zacznie zawierać wyłącznie spacje, podczas gdy@p
, który nie jest pokazany bezpośrednio, zawiera wzorzec wejściowy; w miarę postępu animacji dodamy do niej coraz więcej gwiazdek,@f
aż w końcu będzie wyglądać tak samo@p
.W szczególności
@f = ($" x 80) x 23
ustawia@f
na 24 ciągi po 80 spacji. ($"
jest specjalną zmienną Perla, której domyślną wartością jest spacja.) Następnie bierzemy tę listę, dołączamy do niej wiersze wejściowe za pomocą operatora readline<>
, bierzemy ostatnie 24 wiersze tej połączonej listy i przypisujemy ją@p
: to jest kompaktowy sposób wypełniania@p
pustymi liniami, aby wzór pojawiał się tam, gdzie powinien. Na koniecchomp
wprowadzamy linie wejściowe,@p
aby usunąć końcowe znaki nowej linii, aby nie powodowały problemów później.Teraz spójrzmy na główną pętlę. Okazuje się, że
{...;redo}
jest to krótszy sposób na napisanie nieskończonej pętli niż,while(1){...}
a nawetfor(;;){...}
, zwłaszcza jeśli wcześniej pominiemy średnik,redo
ponieważ natychmiast następuje on poif
bloku.Pierwszy wiersz głównej pętli wprowadza tablicę
@s
(oczywiście dla „śniegu”), do której przygotowuje losowy ciąg 80 znaków zawierający 90% spacji i 10% gwiazdek przy każdej iteracji. (Aby zaoszczędzić kilka znaków, tak naprawdę nigdy nie usuwam dodatkowych wierszy poza końcem@s
tablicy, więc robi się to coraz dłuższe. W końcu zatrzyma to program, ponieważ tablica staje się zbyt długa, aby zmieścić się w pamięci, ale to zajmie to znacznie więcej czasu niż większość osób ogląda tę animację. Dodaniepop@s;
instrukcji przed niąselect
naprawiłoby to kosztem siedmiu znaków.)Reszta głównej pętli jest owinięta w
if
blok, dzięki czemu działa tylko wtedy, gdy@s
tablica zawiera co najmniej 24 linie. Jest to prosty sposób na dostosowanie się do specyfikacji, która od samego początku wymaga wypełnienia całego ekranu spadającym śniegiem, a także nieco upraszcza operacje bitowe.Następnie pojawia się
foreach
pętla, która w wersji golfowej jest tak naprawdę pojedynczą instrukcją zfor 0..23
modyfikatorem. Ponieważ zawartość pętli prawdopodobnie wymaga wyjaśnienia, rozpakuję ją nieco bardziej poniżej:Przede wszystkim
$_
jest domyślną zmienną licznika pętli w Perlu, chyba że zostanie określona inna zmienna. Tutaj biegnie od 0 do 23, tj. Ponad 24 liniami w ramce wyświetlacza.$foo[$_]
oznacza element indeksowany$_
w tablicy@foo
.W pierwszym wierszu pętli do gry w golfa wypisujemy albo nową linię (dogodnie uzyskaną ze
$/
specjalnej zmiennej), albo, gdy$_
jest równa 0, ciąg znaków"\e[H"
, gdzie\e
oznacza znak ESC. Jest to kod sterujący terminala ANSI, który przesuwa kursor do lewego górnego rogu ekranu. Technicznie rzecz biorąc, moglibyśmy pominąć ten fakt, gdybyśmy przyjęli określony rozmiar ekranu, ale zachowałem go w tej wersji, ponieważ oznacza to, że nie muszę zmieniać rozmiaru terminala, aby uruchomić animację.W
$t = $f[$_]
linii po prostu zapisujemy bieżącą wartość$f[$_]
zmiennej „tymczasowej” (stąd$t
) przed potencjalną zmianą w następnej linii, gdzie$s[$_] & $p[$_]
podaje przecięcie (bitowe AND) opadającego śniegu i wzorca wejściowego oraz|=
operator OR to do stałej linii wyjściowej$f[$_]
.W poniższym wierszu
$t ^ $f[$_]
podaje bitowy XOR poprzednich i bieżących wartości$f[$_]
, tj. Listę bitów, które zmieniliśmy w poprzednim wierszu, jeśli występują, i negując jeden z ciągów wejściowych z~
neguje wynik. Tak więc otrzymujemy maskę bitów ze wszystkimi bitami ustawionymi na 1 oprócz tych, które właśnie dodaliśmy do$f[$_]
poprzedniej linii. ORAZ ta maska$s[$_]
bitowa usuwa z niej te bity; w efekcie oznacza to, że gdy spadający płatek śniegu wypełnia otwór w ustalonym wzorze, jest usuwany z tablicy spadającego śniegu.Na koniec
print $f[$_] | $s[$_]
(który w wersji golfowej jest implementowany poprzez ORing dwóch poprzednich linii razem) po prostu drukuje połączenie (bitowe OR) stałych i ruchomych płatków śniegu na bieżącej linii.Jeszcze jedna rzecz do wyjaśnienia to
select '', '', '', 0.1
poniżej wewnętrznej pętli. Jest to po prostu świetny sposób na spanie 0,1 sekundy w Perlu; z jakiegoś głupiego historycznego powodu standardowesleep
polecenie Perla ma jednosekundową rozdzielczość, a importowanie lepszegosleep
zTime::HiRes
modułu zajmuje więcej znaków niż nadużywanie 4-argumentówselect
.źródło
say
), kosztem 2 dodatkowych znaków. Nie sądzę jednak, że mogę łatwo zmienić kolejność napełniania; moja implementacja jest z tym zasadniczo związana.HTML i JavaScript, 436 znaków
Dodaj go do wejścia:
Zobacz, jak działa dla każdego przykładu: kod golfa , logo Stack Overflow , choinki . Użytkownicy przeglądarki Internet Explorer muszą uruchomić wersję 9 i ustawić „Tryb dokumentu” na „standardy IE9” (przy użyciu narzędzi programistycznych F12), aby to przesłanie działało poprawnie.
źródło
Python, 299 znaków
Powinno to być zgodne z zasadami, zakładając, że nowa linia jest uwzględniona w limicie 80 znaków.
źródło
a
a tym samym zakłóca indeksowanie. Właśnie próbowałem, i wygląda na to, zastępując%e
z%e.rstrip()
na linii 6 rozwiązuje problem. (Oczywiście może być krótsza poprawka; nie jestem dobry w golfie w Python.)Java, 625 znaków
Proste rozwiązanie w Javie.
źródło
"\033[H"
powinno to zrobić).