¡Está lloviendo en mi terminal!

24

Descripción del desafío

Tienes que mostrar una simulación de lluvia en la terminal.

En el ejemplo que se muestra a continuación, se agregan 100 gotas de lluvia al azar (use la función aleatoria predeterminada que ofrece su idioma) coordenadas, esperando 0.2 segundos y luego volviendo a dibujar hasta que expire el tiempo dado. Cualquier personaje puede usarse para representar la gota de lluvia.

Parámetros

  • Tiempo de espera entre redibujos en segundos.
  • Hora en que la lluvia será visible. Esto es solo un número entero que representa el número de iteraciones. [Entonces, el tiempo neto por el cual la lluvia será visible es este número entero multiplicado por el tiempo de espera]
  • Mensaje que se mostrará cuando termine la lluvia. (Esto tiene que estar centrado)
  • Número de gotas de lluvia que se mostrarán en la pantalla.

Reglas

  • Se debe usar un solo byte para representar una gota de lluvia, y puede ser cualquier cosa, incluso gatos y perros.
  • No tiene que responder al tamaño del terminal, lo que significa que no tiene que manejar el error para tamaños de terminal variados. Puede especificar el ancho y la altura del terminal por su cuenta.
  • Se aplican las normas estándar de golf.

Muestra de código y salida

Esta es una versión sin golf escrita en Python 2.7 usando 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()

Salida -

ingrese la descripción de la imagen aquí

hashcode55
fuente
3
En el futuro, en lugar de publicar nuevamente, edite el original. Si la gente piensa que las especificaciones son claras, lo nominarán para su reapertura.
Wheat Wizard
66
¿El texto tiene que estar centrado? ¿Está lloviendo al azar? ¿Importa la posición inicial de las gotas? ¿Cómo estás midiendo el tiempo? ¿En milisegundos, segundos, minutos? ¿Qué son los "puntos extra"?
Magic Octopus Urn
1
Si usted, A. Especifique las unidades. B. Especifique el tamaño del terminal o tómelo como entrada. y C. Eliminar la parte sobre puntos extra; Este desafío estaría mejor definido.
Magic Octopus Urn
Cuando dices "aleatorio", ¿podemos suponer que eso significa "uniformemente aleatorio" ?
Trauma digital
3
1 día en la caja de arena a menudo no es suficiente. Recuerde que las personas están aquí de manera recreativa y de diversas zonas horarias; no se debe esperar una respuesta inmediata.
Trauma digital

Respuestas:

12

MATL , 52 bytes

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

Las entradas son, en este orden: pausa entre actualizaciones, número de caídas, mensaje, número de repeticiones. El monitor tiene un tamaño de 80 × 25 caracteres (codificado).

GIF o no sucedió! (Ejemplo con entradas 0.2, 100, 'THE END', 30)

ingrese la descripción de la imagen aquí

O pruébalo en MATL Online .

Explicación

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
fuente
1
Me gusta cómo termina en why:)
tkellehe
1
@tkellehe Me gusta la descripción en tu perfil :-)
Luis Mendo
1
gracias. Tu idioma es muy divertido de leer. (Sí, he estado acechando a sus MAT respuestas lol)
tkellehe
10

JavaScript (ES6), 268 261 bytes

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;

Al menos en mi navegador, la salida está diseñada para caber en el área del Fragmento de pila sin tener que ir a "Página completa", por lo que si solicita más de 702 gotas de lluvia, se bloqueará.

Editar: guardado 7 bytes usando un nodo de texto como mi área de salida.

Neil
fuente
Puede guardar algunos bytes pasando la función como una cadena a setInterval. Además, ¿por qué lo usas en textContentlugar de innerHTML?
Lucas
@ L.Serné Usar una función interna me permite referirme a las variables en la función externa.
Neil
Vaya, mi mal, no se dio cuenta de eso.
Lucas
8

R, 196192185 bytes

Solo una versión simulada que escribí basada en la descripción. Con suerte, es algo que OP estaba buscando.

Guardado algunos bytes gracias a @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="")}

Los argumentos:

  • w: Tiempo de espera entre cuadros
  • t: Número total de fotogramas
  • m: Mensaje personalizado
  • n: Número de gotas de lluvia

Ejemplo

¿Por qué parece que llueve hacia arriba?

Editar: Debo mencionar que esta es mi consola R-studio personalizada de 23x100 caracteres. Las dimensiones están codificadas en la función, pero en principio se podría utilizar getOption("width")para que sea flexible al tamaño de la consola.

ingrese la descripción de la imagen aquí

Desengañado y explicado

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
fuente
¡Esto se ve perfectamente bien! 1 y no creo que su va hacia arriba es sólo su percepción lol
hashcode55
@plannapus. Se dio cuenta rep()automáticamente del timesargumento, por lo que tampoco es necesario. ¡Salvó otros 7 bytes!
Billywob
Muy buena solución. Puede guardar un byte presionando el tamaño de la consola para que funcione los argumentos (si está permitido); puede guardar otro byte utilizando en runiflugar de samplerellenar aleatoriamente la matriz. De este modo: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 bytes

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

Versión sin golf:

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 en mi terminal

v - 5 seconds
d - 100 drops
w - 1 second wait time
s - "Raining Blood" :)
Abel Tom
fuente
4

R, 163 caracteres

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="")}

Con sangrías y nuevas líneas:

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="")
}

Está adaptado a un tamaño de terminal de 24 líneas por 80 columnas. wes el tiempo de espera, tel número de cuadros, nel número de gotas de lluvia y mel mensaje final.

Se diferencia de la respuesta de @ billywob en el uso diferente de sample: si se omite el tamaño de salida, sampleda una permutación del vector de entrada (aquí un vector que contiene el número necesario de gotas de lluvia y el número correspondiente de espacios, gracias al hecho de que el argumento timesde La función repestá vectorizada). Como el tamaño del vector corresponde exactamente al tamaño de la pantalla, no es necesario agregar nuevas líneas ni forzarlo a una matriz.

GIF de salida

plannapus
fuente
3

Nodo JS: 691 158 148 Bytes

Editar

Según lo solicitado, características adicionales eliminadas y golf'd.

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)

Las reglas especifican el desprecio por el tamaño, pero esta versión incluye una falla en los primeros fotogramas. Tiene 129 bytes.

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)

Respuesta anterior

Quizás no sea el mejor golf, pero me dejé llevar un poco. Tiene dirección del viento y factor de lluvia opcionales.

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)

Ver webm trabajando aquí

M3D
fuente
2

Noodel , 44 bytes no competitivos

Tenía un texto centrado en mi lista de cosas que hacer desde que hice el idioma ... Pero, era vago y no agregué hasta después de este desafío. Entonces, aquí no estoy compitiendo, pero me divertí con el desafío :)

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

El tamaño de la consola está codificado a 25x50, lo que no se ve bien en el editor en línea, pero sí para el fragmento.

Intentalo:)


Cómo funciona

Ø                                            # 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
fuente
1
Ah, ese es un lenguaje genial para tener en mi caja de herramientas ¡jaja! De todos modos, me alegro de que te haya gustado el desafío :) +1
hashcode55
2

Ruby + GNU Core Utils, 169 bytes

Los parámetros de la función son el tiempo de espera, el número de iteraciones, el mensaje y el número de gotas de lluvia, en ese orden. Nuevas líneas de legibilidad.

Se necesitaban Core Utils para tputy 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}
Tinta de valor
fuente
1

Python 2.7, 254 251 bytes

Este es mi propio intento sin usar 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

Gracias a @ErikTheOutgolfer por corregir y guardarme bytes.

hashcode55
fuente
No puede poner un forbucle en una línea (como lo ha hecho 40)];for i in u(). También necesitas un ESC ESC '[2J'creo. Además, había un espacio extra en u(n): r[y. Sin embargo, no sé cómo contabas 249. Todos los problemas que encontré se solucionaron aquí .
Erik the Outgolfer
El código que publiqué funciona para mí. Y sí, en realidad lo conté mal, no conté el espacio blanco sangrado, no lo sabía. Gracias por el enlace! Lo editaré
hashcode55
@EriktheOutgolfer Ah, y sí, con respecto a ese ESC ESC, no se necesita una secuencia de escape. Simplemente imprime 'ESC [2J' de manera efectiva, que es una secuencia de escape ansi para limpiar la pantalla. Sin embargo, no restablece la posición del cursor.
hashcode55
Puedes jugarlo aún más :) Pero debes agregar una nota debajo de tu código que especifique que <esc>denota un byte ESC 0x1B literal. El recuento de bytes es 242 , no 246.
Erik the Outgolfer
@EriktheOutgolfer ¡Oh, gracias!
hashcode55
1

SmileBASIC, 114 bytes

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$

El tamaño de la consola es siempre 50 * 30.

12Me21
fuente
1

Perl 5, 156 bytes

154 bytes código + 2 para -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

Utiliza un tamaño fijo de 160x50.

¡Véalo en línea!


Perl 5, 203 bytes

Código de 201 bytes + 2 para -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

Usos tputpara determinar el tamaño de la terminal.

Dom Hastings
fuente