Está chovendo no meu terminal!

24

Descrição do Desafio

Você tem que mostrar uma simulação de chuva no terminal.

No exemplo abaixo, ele adiciona 100 gotas de chuva aleatoriamente (use a função aleatória padrão oferecida pelo seu idioma) coordenadas, aguardando 0,2 segundos e redesenhando novamente até o tempo determinado expirar. Qualquer caractere pode ser usado para representar a gota de chuva.

Parâmetros

  • Tempo de espera entre o redesenho em segundos.
  • Hora em que a chuva será visível. Este é apenas um número inteiro que representa o número de iterações. [Então, o tempo líquido pelo qual a chuva ficará visível é esse número inteiro multiplicado pelo tempo de espera]
  • Mensagem a ser exibida quando a chuva terminar. (Isso deve ser centralizado)
  • Número de gotas de chuva a serem exibidas na tela.

Regras

  • Um único byte deve ser usado para representar uma gota de chuva e pode ser qualquer coisa, até mesmo cães e gatos.
  • Ele não precisa responder ao tamanho do terminal, o que significa que você não precisa lidar com o bug para tamanhos variados de terminais. Você pode especificar a largura e a altura do terminal por conta própria.
  • Aplicam-se regras padrão de golfe.

Amostra de código e saída

Esta é uma versão não-escrita escrita em 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()

Saída -

insira a descrição da imagem aqui

hashcode55
fonte
3
No futuro, em vez de publicar novamente, edite o original. Se as pessoas acharem que as especificações são claras, indicarão para reabertura.
Assistente de trigo
6
O texto precisa estar centralizado? Está chovendo aleatoriamente, a posição inicial das gotículas é importante? Como você está medindo o tempo? Em milissegundos, segundos, minutos? O que é "Pontos extras"?
Magic Octopus Urn
11
Se você, A. Especifique as unidades. B. Especifique o tamanho do terminal ou aceite-o como entrada. e C. Remova a peça sobre pontos extras; esse desafio seria melhor definido.
Magic Octopus Urn
Quando você diz "aleatório", podemos assumir que significa "uniformemente aleatório" ?
Digital Trauma
3
Um dia na caixa de areia geralmente não é suficiente. Lembre-se de que as pessoas estão aqui de forma recreativa e de diversos fusos horários - não se deve esperar feedback imediato.
Digital Trauma

Respostas:

12

MATL , 52 bytes

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

As entradas são, nesta ordem: pausa entre atualizações, número de descargas, mensagem, número de repetições. O monitor possui caracteres de tamanho 80 × 25 (codificado).

GIF ou não aconteceu! (Exemplo com entradas 0.2, 100, 'THE END', 30)

insira a descrição da imagem aqui

Ou tente no MATL Online .

Explicação

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
fonte
11
Eu gosto de como termina why :)
tkellehe
11
@tkellehe Gostei da descrição do seu perfil :-)
Luis Mendo
11
obrigado. Seu idioma é muito divertido de ler. (Sim, eu tenho perseguido suas respostas MATL 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;

Pelo menos no meu navegador, a saída foi projetada para caber na área de snippet de pilha sem ter que ir para "Página inteira"; portanto, se você pedir mais de 702 gotas de chuva, ela travará.

Editar: salvou 7 bytes usando um nó de texto como minha área de saída.

Neil
fonte
Você pode salvar alguns bytes passando a função como uma string para setInterval. Além disso, por que você usa em textContentvez de innerHTML?
Luke
@ L.Serné A utilização de uma função interna permite-me consultar as variáveis ​​na função externa.
Neil
Opa, meu mal, não percebeu isso.
Luke
8

R, 19619218 bytes

Apenas uma versão simulada que escrevi com base na descrição. Espero que seja um pouco o que o OP estava procurando.

Economizei alguns bytes graças 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="")}

Os argumentos:

  • w: Tempo de espera entre os quadros
  • t: Número total de quadros
  • m: Mensagem personalizada
  • n: Número de gotas de chuva

Exemplo

Por que parece que está chovendo para cima?

Editar: devo mencionar que este é o meu console R-studio personalizado de 23x100 caracteres. As dimensões são codificadas na função, mas, em princípio, pode-se usar getOption("width")para torná-la flexível ao tamanho do console.

insira a descrição da imagem aqui

Ungolfed e explicou

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
fonte
Isso parece perfeitamente bem! +1 e eu não acho que a sua vai para cima apenas sua percepção lol
hashcode55
@plannapus. Realizado rep()automaticamente pavimenta o timesargumento, portanto não há necessidade disso. Economizou mais 7 bytes!
precisa saber é o seguinte
Solução muito boa. Você pode salvar um byte pressionando o tamanho do console para funcionar com argumentos (se for permitido); você pode salvar outro byte usando, em runifvez de samplepreencher aleatoriamente a matriz. Assim: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 21/01
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

Versão não destruída:

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);
}

Caixa de teste no meu terminal

v - 5 seconds
d - 100 drops
w - 1 second wait time
s - "Raining Blood" :)
Abel Tom
fonte
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="")}

Com recuos e novas linhas:

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

É adaptado para um tamanho de terminal de 24 linhas por 80 colunas. wé o tempo de espera, to número de quadros, no número de gotas de chuva e ma mensagem final.

Difere da resposta de @ billywob no uso diferente de sample: se o tamanho da saída for omitido, samplepermite uma permutação do vetor de entrada (aqui, um vetor contendo o número necessário de gotas de chuva e o número correspondente de espaços, graças ao argumento timesde função repé vetorizada). Como o tamanho do vetor corresponde exatamente ao tamanho da tela, não há necessidade de adicionar novas linhas ou forçá-lo a formar uma matriz.

Gif de saída

plannapus
fonte
3

NodeJS: 691 158 148 bytes

Editar

Conforme solicitado, recursos adicionais removidos e 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)

As regras especificam desconsiderar o tamanho, mas esta versão inclui uma falha nos primeiros quadros. São 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)

Resposta anterior

Talvez não seja o melhor jogador de golfe, mas fiquei um pouco empolgado. Possui direção opcional do vento e fator de chuva.

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)

Veja aqui trabalhando aqui

M3D
fonte
2

Noodel , não- concorrente 44 bytes

Eu tinha um texto centralizado na minha lista de coisas para fazer desde que criei o idioma ... Mas eu era preguiçoso e não o adicionei até depois desse desafio. Então, aqui não estou competindo, mas me diverti com o desafio :)

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

O tamanho do console é codificado para 25x50, o que não parece bom no editor on-line, mas sim no snippet.

Tente:)


Como 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
fonte
11
Ah, essa é uma linguagem legal de se ter na minha caixa de ferramentas haha! De qualquer forma, fico feliz que tenha gostado do desafio :) +1
hashcode55
2

Ruby + GNU Core Utils, 169 bytes

Os parâmetros para a função são tempo de espera, número de iterações, mensagem e número de gotas de chuva, nessa ordem. Novas linhas de legibilidade.

Utilitários principais eram necessários para tpute 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}
Value Ink
fonte
1

Python 2.7, 254 251 bytes

Esta é minha própria tentativa sem 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

Obrigado a @ErikTheOutgolfer por me corrigir e salvar bytes.

hashcode55
fonte
Você não pode colocar um forloop em uma linha (como você inseriu 40)];for i in u(). Você também precisa de um caractere ESC, '[2J'eu acho. Além disso, havia um espaço extra no u(n): r[y. Eu não sei como você contou 249 embora. Todos os problemas encontrados foram corrigidos aqui .
Erik the Outgolfer
O código que publiquei está funcionando para mim. E sim, eu realmente contei errado, não contei o espaço branco recuado, não sabia. Obrigado pelo link! Eu vou editar.
precisa saber é o seguinte
@EriktheOutgolfer Ah, sim, em relação ao caractere ESC, nenhuma sequência de escape é necessária. Ele apenas imprime 'ESC [2J' efetivamente, que é a sequência de escape ansi para limpar a tela. Porém, ela não redefine a posição do cursor.
precisa saber é o seguinte
Você pode jogar golfe ainda mais :) Mas você precisa adicionar uma nota abaixo do seu código especificando que <esc>denota um byte ESC 0x1B literal. Contagem de bytes é 242 , não 246.
Erik o Outgolfer
@EriktheOutgolfer Oh thanks!
precisa saber é o seguinte
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$

O tamanho do console é sempre 50 * 30.

12Me21
fonte
1

Perl 5, 156 bytes

Código de 154 bytes + 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

Usa um tamanho fixo de 160x50.

Veja online!


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

Usa tputpara determinar o tamanho do terminal.

Dom Hastings
fonte