W moim terminalu pada deszcz!

24

Opis wyzwania

Musisz pokazać symulację deszczu w terminalu.

W podanym poniżej przykładzie jego losowe dodanie 100 kropel deszczu (użyj domyślnej funkcji losowej, którą oferuje Twój język) współrzędnych, odczekaj 0,2 sekundy, a następnie przerysuj ponownie, aż upłynie określony czas. Każda postać może być używana do reprezentowania kropli deszczu.

Parametry

  • Czas oczekiwania między przerysowaniem w sekundach.
  • Czas, przez który będzie widoczny deszcz. To tylko liczba całkowita reprezentująca liczbę iteracji. [Czas netto, przez który będzie widoczny deszcz, to liczba całkowita pomnożona przez czas oczekiwania]
  • Komunikat wyświetlany po zakończeniu deszczu. (To musi być wyśrodkowane)
  • Liczba kropel deszczu wyświetlanych na ekranie.

Zasady

  • Jeden bajt powinien być używany do reprezentowania kropli deszczu i może to być wszystko, nawet koty i psy.
  • Nie musi reagować na wielkość terminala, co oznacza, że ​​nie musisz obsługiwać błędu dla różnych rozmiarów terminali. Możesz samodzielnie określić szerokość i wysokość terminala.
  • Obowiązują standardowe zasady gry w golfa.

Próbka i wyjście kodu

To jest wersja bez golfisty napisana w Pythonie 2.7 przy użyciu ncurses.

import curses
import random
import time

myscreen = curses.initscr()
curses.curs_set(0) # no cursor please 
HEIGHT, WIDTH = myscreen.getmaxyx() 
RAIN = '/' # this is what my rain drop looks like 
TIME = 10 

def make_it_rain(window, tot_time, msg, wait_time, num_drops):
    """
    window    :: curses window 
    time      :: Total time for which it rains
    msg       :: Message displayed when it stops raining
    wait_time :: Time between redrawing scene 
    num_drops :: Number of rain drops in the scene 
    """
    for _ in range(tot_time):
        for i in range(num_drops):
            x,y=random.randint(1, HEIGHT-2),random.randint(1,WIDTH-2)       
            window.addstr(x,y,RAIN)
        window.refresh()
        time.sleep(wait_time)
        window.erase()

    window.refresh()
    window.addstr(HEIGHT/2, int(WIDTH/2.7), msg)


if __name__ == '__main__':
    make_it_rain(myscreen, TIME, 'IT HAS STOPPED RAINING!', 0.2, 100)
    myscreen.getch()
    curses.endwin()

Wyjście -

wprowadź opis zdjęcia tutaj

hashcode55
źródło
3
W przyszłości zamiast ponownie publikować, edytuj oryginał. Jeśli ludzie uważają, że specyfikacje są jasne, nominują je do ponownego otwarcia.
Wheat Wizard
6
Czy tekst musi być wyśrodkowany? Czy przypadkowo pada deszcz, czy początkowa pozycja kropel ma znaczenie? Jak mierzysz czas? W milisekundach, sekundach, minutach? Co to są „dodatkowe punkty”?
Magic Octopus Urn
1
Jeśli ty: A. Określ jednostki. B. Określ rozmiar terminala lub weź go jako dane wejściowe. i C. Usuń część dotyczącą dodatkowych punktów; wyzwanie to byłoby lepiej zdefiniowane.
Magic Octopus Urn
Kiedy mówisz „losowo”, czy możemy założyć, że oznacza to „jednolicie losowe” ?
Cyfrowa trauma
3
1 dzień w piaskownicy często nie wystarcza. Pamiętaj, że ludzie są tutaj rekreacyjnie i z różnych stref czasowych - nie należy oczekiwać natychmiastowej informacji zwrotnej.
Cyfrowa trauma

Odpowiedzi:

12

MATL , 52 bajty

xxx:"1GY.Xx2e3Z@25eHG>~47*cD]Xx12:~c!3G80yn-H/kZ"why

Dane wejściowe są w następującej kolejności: przerwa między aktualizacjami, liczba zrzutów, komunikat, liczba powtórzeń. Monitor ma rozmiar 80 × 25 znaków (na stałe).

GIF lub tak się nie stało! (Przykład z wejściami 0.2, 100, 'THE END', 30)

wprowadź opis zdjęcia tutaj

Lub spróbuj w MATL Online .

Wyjaśnienie

xxx      % Take first three inputs implicitly and delete them (but they get
         % copied into clipboard G)
:"       % Take fourth input implicitly. Repeat that many times
  1G     %   Push first input (pause time)
  Y.     %   Pause that many seconds
  Xx     %   Clear screen
  2e3    %   Push 2000 (number of chars in the monitor, 80*25)
  Z@     %   Push random permutation of the integers from 1 to 2000
  25e    %   Reshape as a 25×80 matrix, which contains the numbers from 1 to 2000
         %   in random positions
  HG     %   Push second input (number of drops)
  >~     %   Set numbers that are <= second input to 1, and the rest to 0
  47*c   %   Multiply by 47 (ASCII for '/') and convert to char. Char 0 will
         %   be displayed as a space
  D      %   Display
]        % End
Xx       % Clear screen
12:~     % Push row vector of twelve zeros
c!       % Convert to char and transpose. This will produce 12 lines containing
         % a space, to vertically center the message in the 25-row monitor
3G       % Push third input (message string)
80       % Push 80
yn       % Duplicate message string and push its length
-        % Subtract
H/k      % Divide by 2 and round down
Z"       % Push string of that many spaces, to horizontally center the message 
         % in the 80-column monitor
w        % Swap
h        % Concatenate horizontally
y        % Duplicate the column vector of 12 spaces to fill the monitor
         % Implicitly display
Luis Mendo
źródło
1
Podoba mi się, jak to się kończy why:)
tkellehe
1
@tkellehe Podoba mi się opis w twoim profilu :-)
Luis Mendo
1
Dziękuję Ci. Twój język jest świetną zabawą do czytania. (Tak, śledziłem twoje odpowiedzi MATL lol)
tk
10

JavaScript (ES6), 268 261 bajtów

t=
(o,f,d,r,m,g=(r,_,x=Math.random()*78|0,y=Math.random()*9|0)=>r?g(r-(d[y][x]<`/`),d[y][x]=`/`):d.map(a=>a.join``).join`
`)=>i=setInterval(_=>o.data=f--?g(r,d=[...Array(9)].map(_=>[...` `.repeat(78)])):`



`+` `.repeat(40-m.length/2,clearInterval(i))+m,d*1e3)
<input id=f size=10 placeholder="# of frames"><input id=d placeholder="Interval between frames"><input id=r size=10 placeholder="# of raindrops"><input id=m placeholder="End message"><input type=button value=Go onclick=t(o.firstChild,+f.value,+d.value,+r.value,m.value)><pre id=o>&nbsp;

Przynajmniej w mojej przeglądarce dane wyjściowe są zaprojektowane tak, aby pasowały do ​​obszaru fragmentu stosu bez konieczności przechodzenia do „Pełnej strony”, więc jeśli poprosisz o więcej niż 702 kropli deszczu, nastąpi awaria.

Edycja: Zapisano 7 bajtów, używając węzła tekstowego jako mojego obszaru wyjściowego.

Neil
źródło
Możesz zapisać kilka bajtów, przekazując funkcję jako ciąg znaków do setInterval. Ponadto, dlaczego używasz textContentzamiast innerHTML?
Łukasz
@ L.Serné Użycie funkcji wewnętrznej pozwala mi odwoływać się do zmiennych w funkcji zewnętrznej.
Neil
Ups, mój zły, nie zauważyłem tego.
Łukasz
8

R 196 192 185 bajtów

Tylko próbna wersja, którą napisałem na podstawie opisu. Mam nadzieję, że nieco tego szukał OP.

Zapisano kilka bajtów dzięki @plannapus.

f=function(w,t,m,n){for(i in 1:t){x=matrix(" ",100,23);x[sample(2300,n)]="/";cat("\f",rbind(x,"\n"),sep="");Sys.sleep(w)};cat("\f",g<-rep("\n",11),rep(" ",(100-nchar(m))/2),m,g,sep="")}

Argumenty:

  • w: Czas oczekiwania między ramkami
  • t: Całkowita liczba ramek
  • m: Niestandardowy komunikat
  • n: Liczba kropel deszczu

Przykład

Dlaczego wygląda na to, że pada w górę?

Edycja: Powinienem wspomnieć, że jest to moja niestandardowa konsola R-studio 23x100 znaków. Wymiary są zakodowane na stałe w funkcji, ale można w zasadzie użyć, getOption("width")aby uczynić ją elastyczną w stosunku do wielkości konsoli.

wprowadź opis zdjęcia tutaj

Nie golfił i wyjaśnił

f=function(w,t,m,n){
    for(i in 1:t){
        x=matrix(" ",100,23);             # Initialize matrix of console size
        x[sample(2300,n)]="/";            # Insert t randomly sampled "/"
        cat("\f",rbind(x,"\n"),sep="");   # Add newlines and print one frame
        Sys.sleep(w)                      # Sleep 
    };
    cat("\f",g<-rep("\n",11),rep(" ",(100-nchar(m))/2),m,g,sep="")  # Print centered msg
}
Billywob
źródło
To wygląda idealnie w porządku! +1 i nie sądzę, że idzie w górę, to tylko twoje postrzeganie lol
hashcode55
@plannapus. Zrealizowany rep()automatycznie wyrzuca timesargument na argument, więc też nie ma takiej potrzeby. Zapisano kolejne 7 bajtów!
Billywob
Bardzo fajne rozwiązanie. Możesz zapisać jeden bajt, przesuwając rozmiar konsoli do argumentów funkcji (jeśli jest to dozwolone); możesz zapisać kolejny bajt, runifzamiast samplelosowo zapełniać macierz. Tak jak:f=function(w,t,m,n,x,y){for(i in 1:t){r=matrix(" ",x,y);r[runif(n)*x*y]="/";cat("\f",rbind(r,"\n"),sep="");Sys.sleep(w)};cat("\f",g<-rep("\n",y/2),rep(" ",(x-nchar(m))/2),m,g,sep="")}
rturnbull
5

C 160 bajtów

f(v,d,w,char *s){i,j;char c='/';for(i=0;i<v;i++){for(j=0;j<d;j++)printf("%*c",(rand()%100),c);fflush(stdout);sleep(w);}system("clear");printf("%*s\n",1000,s);}

v-Time the raindrops are visible in seconds.
d-Number of drops per iteration
w-Wait time in seconds, before the next iteration
s-String to be passed on once its done

Wersja bez golfa:

void f(int v, int d, int w,char *s)
{ 

   char c='/';
   for(int i=0;i<v;i++)
   { 
      for(int j=0;j<d;j++)
         printf("%*c",(rand()%100),c);

      fflush(stdout);
      sleep(w); 
   }   
   system("clear");
   printf("%*s\n", 1000,s);
}

Testcase na moim terminalu

v - 5 seconds
d - 100 drops
w - 1 second wait time
s - "Raining Blood" :)
Abel Tom
źródło
4

R, 163 znaki

f=function(w,t,n,m){for(i in 1:t){cat("\f",sample(rep(c("/"," "),c(n,1920-n))),sep="");Sys.sleep(w)};cat("\f",g<-rep("\n",12),rep(" ",(80-nchar(m))/2),m,g,sep="")}

Z wcięciami i znakami nowej linii:

f=function(w,t,n,m){
    for(i in 1:t){
        cat("\f",sample(rep(c("/"," "),c(n,1920-n))),sep="")
        Sys.sleep(w)
    }
    cat("\f",g<-rep("\n",12),rep(" ",(80-nchar(m))/2),m,g,sep="")
}

Jest dostosowany do rozmiaru terminala 24 linii na 80 kolumn. wto czas oczekiwania, tliczba ramek, nliczba kropel deszczu i mkońcowa wiadomość.

Różni się on od @ odpowiedź billywob jest w innym użycia sample: jeśli wielkość wyjściowa jest pominięty, sampledaje permutacji wektora wejściowego (tutaj wektor zawierający wymaganą liczbę kropel oraz odpowiadająca jej liczba miejsc, dzięki temu, że argument timesz funkcja repjest wektoryzowana). Ponieważ rozmiar wektora odpowiada dokładnie rozmiarowi ekranu, nie ma potrzeby dodawania nowych linii ani wymuszania kształtu w matrycy.

Gif produkcji

plannapus
źródło
3

NodeJS: 691 158 148 bajtów

Edytować

Zgodnie z życzeniem usunięto dodatkowe funkcje i wprowadzono grę w golfa.

s=[];setInterval(()=>{s=s.slice(L='',9);for(;!L[30];)L+=' |'[Math.random()*10&1];s.unshift(L);console.log("\u001b[2J\u001b[0;0H"+s.join('\n'))},99)

Reguły określają ignorowanie wielkości, ale ta wersja zawiera usterkę dla kilku pierwszych ramek. Ma 129 bajtów.

s='';setInterval(()=>{for(s='\n'+s.slice(0,290);!s[300];)s=' |'[Math.random()*10&1]+s;console.log("\u001b[2J\u001b[0;0H"+s)},99)

Poprzednia odpowiedź

Być może nie najlepsza gra w golfa, ale trochę mnie poniosło. Ma opcjonalny kierunek wiatru i współczynnik deszczu.

node rain.js 0 0.3

var H=process.stdout.rows-2, W=process.stdout.columns,wnd=(arg=process.argv)[2]||0, rf=arg[3]||0.3, s=[];
let clr=()=>{ console.log("\u001b[2J\u001b[0;0H") }
let nc=()=>{ return ~~(Math.random()*1+rf) }
let nl=()=>{ L=[];for(i=0;i<W;i++)L.push(nc()); return L}
let itrl=(l)=>{ for(w=0;w<wnd;w++){l.pop();l.unshift(nc())}for(w=0;w>wnd;w--){l.shift();l.push(nc())};return l }
let itrs=()=>{ if(s.length>H)s.pop();s.unshift(nl());s.map(v=>itrl(v)) }
let d=(c,i)=>{if(!c)return ' ';if(i==H)return '*';if(wnd<0)return '/';if(wnd>0)return '\\';return '|'}
let drw=(s)=>{ console.log(s.map((v,i)=>{ return v.map(  c=>d(c,i)  ).join('') }).join('\r\n')) }
setInterval(()=>{itrs();clr();drw(s)},100)

Zobacz, jak działa webm tutaj

M3D
źródło
2

Noodel , niekonkurencyjne 44 bajty

Miałem centralny tekst na mojej liście rzeczy do zrobienia, odkąd stworzyłem ten język ... Ale byłem leniwy i nie dodałem go po tym wyzwaniu. Tutaj nie konkuruję, ale dobrze się bawię z tym wyzwaniem :)

ØGQÆ×Øæ3/×Æ3I_ȥ⁻¤×⁺Æ1Ḷḋŀ÷25¶İÇæḍ€Æ1uụC¶×12⁺ß

Rozmiar konsoli jest zakodowany na stałe na 25 x 50, co nie wygląda dobrze w edytorze online, ale działa w przypadku fragmentu kodu.

Spróbuj:)


Jak to działa

Ø                                            # Pushes all of the inputs from the stack directly back into the stdin since it is the first token.

 GQÆ×Ø                                       # Turns the seconds into milliseconds since can only delay by milliseconds.
 GQ                                          # Pushes on the string "GQ" onto the top of the stack.
   Æ                                         # Consumes from stdin the value in the front and pushes it onto the stack which is the number of seconds to delay.
    ×                                        # Multiplies the two items on top of the stack.
                                             # Since the top of the stack is a number, the second parameter will be converted into a number. But, this will fail for the string "GQ" therein treated as a base 98 number producing 1000.
     Ø                                       # Pops off the new value, and pushes it into the front of stdin.

      æ3/×Æ3I_ȥ⁻¤×⁺                          # Creates the correct amount of rain drops and spaces to be displayed in a 50x25 console.
      æ3                                     # Copies the forth parameter (the number of rain drops).
        /                                    # Pushes the character "/" as the rain drop character.
         ×                                   # Repeats the rain drop character the specified number of times provided.
          Æ3                                 # Consumes the number of rain drops from stdin.
            I_                               # Pushes the string "I_" onto the stack.
              ȥ                              # Converts the string into a number as if it were a base 98 number producing 25 * 50 = 1250.
               ⁻                             # Subtract 1250 - [number rain drops] to get the number of spaces.
                ¤                            # Pushes on the string "¤" which for Noodel is a space.
                 ×                           # Replicate the "¤" that number of times.
                  ⁺                          # Concatenate the spaces with the rain drops.

                   Æ1Ḷḋŀ÷25¬İÇæḍ€            # Handles the animation of the rain drops.
                   Æ1                        # Consumes and pushes on the number of times to loop the animation.
                     Ḷ                       # Pops off the number of times to loop and loops the following code that many times.
                      ḋ                      # Duplicate the string with the rain drops and spaces.
                       ŀ                     # Shuffle the string using Fisher-Yates algorithm.
                        ÷25                  # Divide it into 25 equal parts and push on an array containing those parts.
                           ¶                 # Pushes on the string "¶" which is a new line.
                            İ                # Join the array by the given character.
                             Ç               # Clear the screen and display the rain.
                              æ              # Copy what is on the front of stdin onto the stack which is the number of milliseconds to delay.
                               ḍ             # Delay for the specified number of milliseconds.
                                €            # End of the loop.

                                 Æ1uụC¶×12⁺ß # Creates the centered text that is displayed at the end.
                                 Æ1          # Pushes on the final output string.
                                   u         # Pushes on the string "u" onto the top.
                                    ụC       # Convert the string on the top of the stack to an integer (which will fail and default to base 98 which is 50) then center the input string based off of that width.
                                      ¶      # Push on a the string "¶" which is a new line.
                                       ×12   # Repeat it 12 times.
                                          ⁺  # Append the input string that has been centered to the new lines.
                                           ß # Clear the screen.
                                             # Implicitly push on what is on the top of the stack which is the final output.

<div id="noodel" code="ØGQÆ×Øæ3/×Æ3I_ȥ⁻¤×⁺Æ1Ḷḋŀ÷25¶İÇæḍ€Æ1uụC¶×12⁺ß" input='0.2, 50, "Game Over", 30' cols="50" rows="25"></div>

<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

tkellehe
źródło
1
Ach, to fajny język w moim zestawie narzędzi haha! Tak czy inaczej, cieszę się, że spodobało Ci się wyzwanie :) +1
hashcode55
2

Ruby + GNU Core Utils, 169 bajtów

Parametry funkcji to czas oczekiwania, liczba iteracji, komunikat i liczba kropel deszczu w tej kolejności. Nowe linie dla czytelności.

Potrzebne były podstawowe narzędzia tputi clear.

->w,t,m,n{x=`tput cols`.to_i;z=x*h=`tput lines`.to_i
t.times{s=' '*z;[*0...z].sample(n).map{|i|s[i]=?/};puts`clear`+s;sleep w}
puts`clear`+$/*(h/2),' '*(x/2-m.size/2)+m}
Wartość tuszu
źródło
1

Python 2.7, 254 251 bajtów

To moja własna próba bez użycia ncurses.

from time import*;from random import*;u=range;y=randint
def m(t,m,w,n):
    for _ in u(t):
        r=[[' 'for _ in u(40)]for _ in u(40)]
        for i in u(n):r[y(0,39)][y(0,39)]='/'
        print'\n'.join(map(lambda k:' '.join(k),r));sleep(w);print '<esc>[2J'
    print' '*33+m

Dziękuję @ErikTheOutgolfer za poprawienie i zapisanie mi bajtów.

hashcode55
źródło
Nie możesz umieścić forpętli w jednej linii (tak jak masz w 40)];for i in u(). '[2J'Myślę, że potrzebujesz również znaku ESC . Ponadto było w nim dodatkowe miejsce u(n): r[y. Nie wiem jednak, jak policzyłeś 249. Wszystkie znalezione przeze mnie problemy zostały naprawione tutaj .
Erik the Outgolfer
Kod, który opublikowałem, działa dla mnie. I tak, właściwie to źle policzyłem, nie liczyłem białej wciętej przestrzeni, nie wiedziałem o tym. Dzięki za link! Zmienię to.
hashcode55
@EriktheOutgolfer No i tak, jeśli chodzi o ten znak ESC, nie jest potrzebna sekwencja ucieczki. Po prostu skutecznie drukuje „ESC [2J”, czyli sekwencję ucieczki ansi do czyszczenia ekranu. Nie resetuje jednak pozycji kursora.
hashcode55
Możesz<esc> zagrać w golfa jeszcze bardziej :) Ale musisz dodać notatkę poniżej swojego kodu, określającą dosłowny bajt 0x1B ESC. Liczba bajtów to 242 , a nie 246.
Erik the Outgolfer
@EriktheOutgolfer O dzięki!
hashcode55
1

SmileBASIC, 114 bajtów

INPUT W,T,M$,N
FOR I=1TO T
VSYNC W*60CLS
FOR J=1TO N
LOCATE RND(50),RND(30)?7;
NEXT
NEXT
LOCATE 25-LEN(M$)/2,15?M$

Rozmiar konsoli wynosi zawsze 50 * 30.

12Me21
źródło
1

Perl 5, 156 bajtów

Kod 154 bajtów + 2 dla -pl.

$M=$_;$W=<>;$I=<>;$R=<>;$_=$"x8e3;{eval'$-=rand 8e3;s!.{$-}\K !/!;'x$R;print;select$a,$a,$a,$W;y!/! !;--$I&&redo}$-=3920-($l=length$M)/2;s;.{$-}\K.{$l};$M

Używa stałego rozmiaru 160 x 50.

Zobacz online!


Perl 5, 203 bajtów

Kod 201 bajtów + 2 dla -pl.

$M=$_;$W=<>;$I=<>;$R=<>;$_=$"x($z=($x=`tput cols`)*($y=`tput lines`));{eval'$-=rand$z;s!.{$-}\K !/!;'x$R;print;select$a,$a,$a,$W;y!/! !;--$I&&redo}$-=$x*($y+!($y%2))/2-($l=length$M)/2;s;.{$-}\K.{$l};$M

Wykorzystuje się tputdo określenia rozmiaru terminala.

Dom Hastings
źródło