Faça um simulador de invólucro com bolhas de ar

23

Bubble-wraps são entretenimento de nível máximo. Todos podem concordar com isso.

Agora, você fará com que até os computadores desfrutem de envoltórios de bolhas.

Especificações

Você receberá dois números inteiros, w e h. (Cada um é responsivamente largura e altura)

Seu programa deve gerar todas as fases w * h aguardando 1 segundo entre cada uma e terminar.

Todo plástico bolha começa com todas as células cheias.

Por exemplo, um invólucro com bolhas de ar 4 * 6 começa como:

O_O_
_O_O
O_O_
_O_O
O_O_
_O_O

E a cada fase, uma célula aleatória não exibida é exibida. Por exemplo,

O_O_
_O_O
O_X_
_O_O
O_O_
_O_O

O programa deve terminar quando todas as células forem exibidas. aka.

X_X_
_X_X
X_X_
_X_X
X_X_
_X_X

Exemplos

(4,6)
(5,5)
(6,2)
(10,10)
(7,9)
Matthew Roh
fonte
Podemos usar 1e em 0vez de Oe X?
Pavel
1
Os pls de NEEDZ BUBBLEZ enviam ajuda
Christopher
3
É aceitável que um (1,1)não tenha bolhas (por exemplo, "célula" superior esquerda é sempre um sublinhado)?
Jonathan Allan
1
@JonathanAllan Sim.
Matthew Roh
1
@KevinCruijssen Não precisa ser um programa completo.
Matthew Roh

Respostas:

7

C (Windows), 260 248 bytes

#import<windows.h>
i,j,l,r;b(w,h){char*s=malloc(l=w*h+h);for(i=h;i--;*s++=10)for(j=w;j--;*s++=i%2^j%2?79:45);*(s-1)=0;s-=l;for(srand(time(0));j>system("cls")+puts(s)-2;j>-1?s[j]=88:0)for(Sleep(1000),r=rand(),j=-2,i=r+l*2;--i-r;j=s[i%l]==79?i%l:j);}

insira a descrição da imagem aqui

Steadybox
fonte
Observe que há uma função de suspensão na biblioteca de threads, incluída no C ++ 11.
Matthew Roh
@MatthewRoh Sim, mas isso é mais curto e system("cls")também é específico do Windows, então o código também não seria mais portátil com a biblioteca de threads. E com C ++ eu também precisaria incluir iostreamor cstdio.
Steadybox
btw você não precisa redefinir a tela. isso o tornará mais curto.
Matthew Roh
5

Python 3 , 222 220 bytes

Esta é a primeira vez que respondo, portanto, seja gentil (e indique os erros que cometi).

import time,random as t
def f(c,r):
 p=print;a='0_'*c;d=((a[:c]+'\n'+a[1:c+1]+'\n')*r)[:-~c*r]
 for i in[1]*((r*c+r%2*c%2)//2):
  p(d);k=1
  while d[k]!='0':k=t.randrange(len(d))
  d=d[:k]+'X'+d[k+1:];time.sleep(1)
 p(d)

Experimente online!

Como funciona:

  1. Encadear muitos '0 _' juntos
  2. Pique em partes '0_0 _... \ n' e '_0_0 ... \ n' e concatene
  3. Gere índices aleatórios até que o caractere no índice seja um '0'
  4. Criar uma nova string com o caractere no índice gerado é substituído por um 'X' (Maldito seja, o python para strings não mutáveis!)
  5. r*c+r%2*c%2Tempos de repetição : Existem r*cbolhas no padrão, a menos que r e c sejam ímpares; nesse caso, existem r*c+1.
Nilo
fonte
1
Bem-vindo ao PPCG!
AdmBorkBork
1
Isso é bastante pequeno, mas sua largura e altura são invertidas. Ótima resposta! (Apenas mude para f(c,r)e você ficará bem).
Rassar # 13/17
@rassar Woops, obrigado!
Nilo
4

MATL , 37 bytes

:!i:+o`T&Xxt3:q'_OX'XEcD2y1=ft&v1Zr(T

O canto superior esquerdo é sempre um sublinhado (permitido pelo desafio).

A tela é limpa entre as fases. Eu poderia salvar um byte não limpando a tela, mas fica melhor assim.

O programa sai com um erro ( permitido por padrão ) após exibir todas as fases.

Experimente no MATL Online! (Se não funcionar após alguns segundos, atualize a página e tente novamente).

Luis Mendo
fonte
4

Mathematica (145 bytes)

Função anônima, usa altura e largura como entrada (nessa ordem - se houver um problema, substitua {##}por {#2,#}no meio do código por 2 bytes adicionais).

Código:

Monitor[Do[Pause@1,{i,NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,""<>Riffle["_"["O"][[Mod[#+#2,2]]]&~Array~{##},"
"],Floor[##/2]]}],i]&

Explicação:

  • ""<>Riffle[Array["_"["O"][[Mod[#+#2,2]]]&,{##}],"\n"] cria o invólucro com bolhas de ar inicial, não populado, criando uma matriz de "_" se "O" se, em seguida, StringJoining entre as novas linhas.
  • NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,..., Floor[##/2]]escolhe repetidamente um dos "O" s para substituir por um "X", quantas vezes houver "O" s (que é Piso [largura * altura / 2]) - obrigado a @ JonathanAllan pela idéia de colocar "_ "em vez de" O "no canto superior esquerdo, caso contrário, seria o Ceilingcontrário e, portanto, mais 2 bytes).
  • Monitor[Do[Pause@1,{i,...}],i]faz ipegar os valores da lista que acabamos de calcular, por 1 segundo cada, e imprimir dinamicamente i.

Exemplo de saída:

GIF de Mathematica estourando bolhas de ar

Não é uma árvore
fonte
3

Geléia , 30 29 bytes

=”OTX
+þ⁹++µị⁾_OYµṄœS1”XǦµÐL

Exemplo de execução

Chama o link como díade com os argumentos do programa e fecha com uma mensagem (cujo código é çṛ“\'=ṙMḋḌẓ(ėo»)

Nuance: a "célula" inferior direita sempre será uma bolha (em vez da parte superior esquerda, como no exemplo da pergunta), para garantir que, quando todas as bolhas forem acionadas, a escolha aleatória retorne 0, que será "X"o final da lista - substituindo o que não faz alteração no valor e interrompe o loop.

Nota: não limpa a tela (não foi especificada e não sei como fazê-lo).

Quão?

=”OTX - Link 1, choose a random O index or 0: string   e.g. "_O_\nX_O"
 ”O   - "O"
=     - equals (vectorises over the string)            e.g. [0,1,0,0,0,0,1]
   T  - truthy indexes                                 e.g. [2,7]
    X - random choice (if empty this returns 0)

+þ⁹++µị⁾_OYµṄœS1”XǦµÐL - Main link: w, h              e.g. 3, 2
                        - left argument (implicit), w  e.g. 3
  ⁹                     - right argument, h            e.g. 2
 þ                      - outer product with
+                       -     addition                 e.g. [[2,3,4],[3,4,5]]
                        - left argument (implicit), w  e.g. 3
   +                    - add                          e.g. [[5,6,7],[6,7,8]]
                        - right argument (implicit), h e.g. 2
    +                   - add                          e.g. [[7,8,9],[8,9,10]]
     µ                  - monadic chain separation
       ⁾_O              - "_O"
      ị                 - index into (1-based & mod)   e.g. [['_','O','_'],['O','_','O']]
                        -     note: the additions above assure the last entry is an 'O'.
          Y             - join with line feeds         e.g. ['_','O','_','\n','O','_','O']
           µ        µ   - monadic chain separations
                     ÐL - loop until the results are no longer unique:
            Ṅ           -     print with a trailing line feed and yield
             œS1        -     sleep for 1 second and yield
                   ¦    -     apply to index
                  Ç     -         given by calling the last link (1) as a monad 
                        -                 (a random O index or 0 if none exists)
                ”X      -         an "X"  (      ... which will be an X already)
Jonathan Allan
fonte
@ ГригорийПерельман escreveu.
Jonathan Allan
2

Scala , 764 bytes

object B{
  def main(a: Array[String]):Unit={
    val v=false
    val (m,l,k,r,n)=(()=>print("\033[H\033[2J\n"),a(0)toInt,a(1)toInt,scala.util.Random,print _)
    val e=Seq.fill(k, l)(v)
    m()
    (0 to (l*k)/2-(l*k+1)%2).foldLeft(e){(q,_)=>
      val a=q.zipWithIndex.map(r => r._1.zipWithIndex.filter(c=>
        if(((r._2 % 2) + c._2)%2==0)!c._1 else v)).zipWithIndex.filter(_._1.length > 0)
      val f=r.nextInt(a.length)
      val s=r.nextInt(a(f)._1.length)
      val i=(a(f)._2,a(f)._1(s)._2)
      Thread.sleep(1000)
      m()
      val b=q.updated(i._1, q(i._1).updated(i._2, !v))
      b.zipWithIndex.map{r=>
        r._1.zipWithIndex.map(c=>if(c._1)n("X")else if(((r._2 % 2)+c._2)%2==0)n("O")else n("_"))
        n("\n")
      }
      b
    }
  }
}

Como funciona

O algoritmo preenche primeiro uma sequência 2D com valores falsos. Ele determina quantas iterações (caixas abertas) existem com base nos argumentos da linha de comando inseridos. Ele cria uma dobra com esse valor como limite superior. O valor inteiro da dobra é usado apenas implicitamente como uma maneira de contar quantas iterações o algoritmo deve executar. A sequência preenchida que criamos anteriormente é a sequência inicial da dobra. Isso é usado na geração de uma nova sequência 2D de valores falsos com suas indecisões de resposta correspondente.

Por exemplo,

[[false, true],
 [true, false],
 [true, true]]

Será transformado em

[[(false, 0)], [(false, 1)]]

Observe que todas as listas que são completamente verdadeiras (têm um comprimento de 0) são omitidas da lista de resultados. O algoritmo pega essa lista e escolhe uma lista aleatória na lista mais externa. A lista aleatória é escolhida para ser a linha aleatória que escolhemos. A partir dessa linha aleatória, encontramos novamente um número aleatório, um índice de coluna. Depois de encontrarmos esses dois índices aleatórios, adormecemos o segmento em que estamos por 1000 milissegundos.

Depois que terminamos de dormir, limpamos a tela e criamos um novo quadro com um truevalor atualizado nos índices aleatórios que criamos.

Para imprimir isso corretamente, usamos mape compactamos com o índice do mapa, para que o tenhamos em nosso contexto. Usamos o valor verdadeiro da sequência para determinar se devemos imprimir um Xou um Oou _. Para escolher o último, usamos o valor do índice como nosso guia.

Coisas interessantes a serem observadas

Para descobrir se deve imprimir um Oou um _, ((r._2 % 2) + c._2) % 2 == 0é utilizado o condicional . r._2refere-se ao índice de linha atual, enquanto c._2refere-se à coluna atual. Se um estiver em uma linha ímpar, r._2 % 2será 1, compensando, portanto c._2, um na condicional. Isso garante que, nas linhas ímpares, as colunas sejam movidas por 1 como pretendido.

A impressão da string "\033[H\033[2J\n", de acordo com algumas respostas do Stackoverflow que li, limpa a tela. Está escrevendo bytes no terminal e fazendo algumas coisas descoladas que eu realmente não entendo. Mas eu achei a maneira mais fácil de fazer isso. Porém, ele não funciona no emulador de console do Intellij IDEA. Você terá que executá-lo usando um terminal regular.

Outra equação pode ser estranha de se ver quando se olha pela primeira vez para esse código (l * k) / 2 - (l * k + 1) % 2. Primeiro, vamos desmistificar os nomes das variáveis. lrefere-se aos primeiros argumentos passados ​​para o programa enquanto krefere-se ao segundo. Para traduzir (first * second) / 2 - (first * second + 1) % 2,. O objetivo dessa equação é criar a quantidade exata de iterações necessárias para obter uma sequência de todos os Xs. A primeira vez que fiz isso, fiz (first * second) / 2como fazia sentido. Para todos os nelementos de cada sub-lista, existem n / 2bolhas que podemos abrir. No entanto, isso é interrompido ao lidar com entradas como(11 13). Precisamos calcular o produto dos dois números, torná-lo ímpar, se for par, e mesmo se for ímpar, e então pegar o mod disso em 2. Isso funciona porque as linhas e colunas ímpares exigirão uma iteração a menos para chegar ao resultado final.

mapé usado em vez de a forEachporque possui menos caracteres.

Coisas que provavelmente podem ser melhoradas

Uma coisa que realmente me incomoda nessa solução é o uso frequente de zipWithIndex. Está ocupando tantos personagens. Tentei fazer isso para que eu pudesse definir minha própria função de um caractere que apenas executaria zipWithIndexcom o valor passado. Mas acontece que Scala não permite que uma função anônima tenha parâmetros de tipo. Provavelmente existe outra maneira de fazer o que estou fazendo sem usar, zipWithIndexmas não pensei muito em uma maneira inteligente de fazer isso.

Atualmente, o código é executado em duas passagens. O primeiro gera uma nova placa enquanto a segunda passagem a imprime. Eu acho que se alguém combinasse essas duas passagens em uma, isso economizaria alguns bytes.

Este é o primeiro código de golfe que eu fiz, então tenho certeza de que há muito espaço para melhorias. Se você gostaria de ver o código antes de eu otimizar o máximo possível de bytes, aqui está ele.

Stefan Aleksić
fonte
1

JavaScript (ES6), 246 229 bytes

document.write(`<pre id=o></pre>`)
setInterval(_=>{(a=o.innerHTML.split(/(O)/))[1]?a[Math.random()*~-a.length|1]=`X`:0;o.innerHTML=a.join``},1e3)
f=(w,h)=>o.innerHTML=[...Array(h)].map((_,i)=>`O_`.repeat(w+h).substr(i,w)).join`
`
<div oninput=f(+w.value,+h.value)><input id=w type=number min=1><input id=h type=number min=1>

Neil
fonte
A largura não era em termos de células, mas incluía espaços em branco (sublinhados).
Matthew Roh
@ MatthewRoh Desculpe, lembrei de corrigi-lo para a altura, mas esqueci de verificar a largura.
314 Neil
Hmm .. não pode esta parte: de `${`_O`.repeat(w).slice(w)} ${`O_`.repeat(w).slice(w)}alguma forma ser combinada? Talvez um sinalizador booleano para primeiro determinar _Oou O_e depois fazer o .repeat(w).slice(w)?
Kevin Cruijssen 13/03/19
1
@KevinCruijssen Eu tinha perdido 16 bytes por causa de uma rápida correção de bug que eu não tinha tido tempo para jogar golfe na época. Eu já tomado um outro olhar e chegar a uma economia de 17 byte,
Neil
1

Python - 290 bytes

Eu nunca fiz um desses antes - então qualquer crítica construtiva seria apreciada :)

O principal truque aqui é apenas uma compreensão de lista irritantemente aninhada. Eu poderia salvar alguns caracteres por não ter uma nova linha entre os pops, mas isso parece feio.

r=range
q=print
import random as n,time
def f(H,W):
    def p(b):
        q("\n".join(["".join(["O"if(i,j)in b else"X"if(i,j)in X else"_"for j in r(H)])for i in r(W)]));time.sleep(1);q()
    b=[(i,h)for h in r(H)for i in r(h%2,W,2)];n.shuffle(b);X=[]
    while len(b)>0:
        p(b);X+=[b.pop()]
    p(b)
Arya
fonte
Olá, seja bem-vindo ao PPCG! O desafio era pegar o we hcomo entrada (através do STDIN, como uma entrada de função ou algo semelhante), em vez de ter um código fixo H=4 W=6. Além disso, embora nunca tenha programado em Python, acho que você pode jogar alguns espaços no seu código atual. Dicas para jogar golfe em Python também podem ser interessantes para ler, para que você tenha idéias sobre como jogar golfe ainda mais. Aproveite sua estadia! :)
Kevin Cruijssen 13/03/19
Além disso, em relação ao seu comentário: " Eu poderia salvar alguns caracteres por não ter uma nova linha entre os pops, mas isso parece feio. " Não importa o quão feio ou não feito na programação da vida real, o codegolf é sobre salvar como bytes quanto possível. Quanto mais curto e mais feio, melhor. ;)
Kevin Cruijssen 13/03/19
@KevinCruijssen o Python3 acima de mim apenas o tem em função de w, h, isso é permitido?
Arya
1
Sim, por padrão , ambas as funções com os parâmetros esperados e programas completos são permitidos , a menos que a pergunta indique o contrário.
Kevin Cruijssen 13/03/19
1
Ok - eu fiz isso uma função de H e W agora.
Arya #
1

Carvão , 49 46 39 bytes (não competitivo)

UONNO_¶_OAKAαA№αOβHWψβ«A§α§⌕AαO‽βXA№αOβ

Verbose

Oblong(InputNumber(), InputNumber(), "O_\n_O")
Assign(PeekAll(), a)
Assign(Count(a, "O"), b)
RefreshWhile (k, b) {
    AssignAtIndex(a, AtIndex(FindAll(a, "O"), Random(b)), "X")
    Assign(Count(a, "O"), b)
}
Somente ASCII
fonte
1

APL (Dyalog) , 61 59 bytes

⎕←m'O_'[2|-/¨⍳⎕]
(b/,m)[?+/b'O'=,m]←'X'
DL 1
2/⍨'O'∊⎕←m

⎕← saída
m←m , onde m é
'O_'[] esses caracteres indexados por…
2| a divisão-restante-quando-dividido-por-dois da
-/¨ diferença entre cada uma das
 coordenadas (índices) em uma matriz de
 entrada numérica de forma (o número de linhas e colunas )

(... )[... ]←'X' atribuir o carácter X para um dos ...
b/ filtrou-a-passo b (a ser definido)
,m elementos de m, especificamente ... raveled
? um elemento aleatório (número lit.) na uma gama para
+/ a soma de
b←b , onde b é
'O'= booleano para onde a letra iguais
,mm raveled

⎕DL 1D e L ay um segundo

→2 Vá para a linha 2
/⍨ se (lit. filtrado por)
'O'∊ se a letra é um membro do
⎕←m valor emitido, em que o valor emitido é m

Experimente online!


A partir da versão 16.0, será mais curto:

{0::→⋄'X'@(⊂(?∘≢⊃⊢)⍸'O'=⍵⊣⎕DL 1)⊢⎕←⍵}⍣≡'O_'[2|-/¨⍳⎕]

Adão
fonte
1

Python 3, 195 188 bytes

import time,random
def f(w,h):
 a=bytearray(b'0-'*w*h);b=[*range(0,w*h,2)];random.shuffle(b);
 while 1:print(*(a.decode()[w*i:w*i+w]for i in range(h)),sep='\n');a[b.pop()]=88;time.sleep(1)

Usar bytearraye decodeparece ser mais curto do que cortar e remontar uma corda a la a[:i]+'X'+a[i+1:].

import time,random
def f(w,h):
 x=[*range(1,h*w,2)];random.shuffle(x)
 while 1:
  for i in range(w*h):
   print('-X0'[(i%w%2!=i//w%2)+(i in x)],end='\n'[i%w<w-1:])
  print();time.sleep(1);x.pop()
RootTwo
fonte
0

Java 7, 317 bytes

void c(int w,int h)throws Exception{String r="";int x=0,j=0,i;for(;j++<h;x^=1,r+="\n")for(i=0;i<w;r+=(i+++x)%2<1?"_":"O");for(System.out.println(r);r.contains("O");System.out.println(r=r.substring(0,x)+'X'+r.substring(x+1))){Thread.sleep(1000);for(x=0;r.charAt(x)!='O';x=new java.util.Random().nextInt(r.length()));}}

Explicação:

void c(int w, int h) throws Exception{                     // Method with two integer parameters (throws Exception is required for the Thread.sleep)
  String r = "";                                           //  String we build to print
  int x=0, j=0, i;                                         //  Some temp values and indexes we use
  for(; j++<h;                                             //  Loop over the height 
      x^=1,                                                //    After every iteration change the flag `x` every iteration from 0 to 1, or vice-versa
      r += "\n")                                           //    And append the String with a new-line
    for(i=0; i<w;                                          //   Inner loop over the width
        r += (i++ + x)%2 < 1 ? "_" : "O")                  //    Append the String with either '_' or 'O' based on the row and flag-integer
    ;                                                      //   End inner width-loop (implicit / no body)
                                                           //  End height-loop (implicit / single-line body)
  for(                                                     //  Loop
    System.out.println(r);                                 //   Start by printing the starting wrap
    r.contains("O");                                       //   Continue loop as long as the String contains an 'O'
    System.out.println(r=                                  //   Print the changed String after every iteration
        r.substring(0,x)+'X'+r.substring(x+1))){           //    After we've replaced a random 'O' with 'X'
      Thread.sleep(1000);                                  //   Wait 1 second
      for(x=0; r.charAt(x) != 'O';                         //   Loop until we've found a random index containing still containing an 'O'
          x = new java.util.Random().nextInt(r.length()))  //    Select a random index in the String
      ;                                                    //   End loop that determines random index containing 'O' (implicit / no body)
  }                                                        //  End loop
}                                                          // End method

Teste gif (4,6)

insira a descrição da imagem aqui

Kevin Cruijssen
fonte
0

Perl, 148 bytes

146 bytes de código + -plsinalizadores.

$_=O x($x=$_+1);s/O\K./_/g;for$i(1..($y=<>)){$b.=($i%2?$_:_.s/.$//r).$/}}print$_="\e[H$b";while(/O/){$r=0|rand$y*$x+3;s/.{$r}\KO/X/s||redo;sleep 1

Para executá-lo:

perl -ple '$_=O x($x=$_+1);s/O\K./_/g;for$i(1..($y=<>)){$b.=($i%2?$_:_.s/.$//r).$/}}print$_="\e[H$b";while(/O/){$r=0|rand$y*$x+3;s/.{$r}\KO/X/s||redo;sleep 1' <<< "6
4"
dada
fonte
0

MATLAB (R2016b), 172 bytes

Código:

x=input('');m=[eye(x(2),x(1)) ''];m(:)='O';m(1:2:end,2:2:end)='_';m(2:2:end,1:2:end)='_';o=find(m=='O');r=o(randperm(nnz(o)));disp(m);for i=r';pause(1);m(i)='X';disp(m);end

Recomendações são sempre bem-vindas! Experimente online!

Saída do Programa:

insira a descrição da imagem aqui

Explicação:

x = input( '' );                    % Input
m = [ eye( x( 2 ), x( 1 ) ) '' ];   % Character Matrix
m( : ) = 'O';                       % Fill Matrix with "Bubbles"

m( 1:2:end, 2:2:end ) = '_';        % Alternate Spaces Between Bubbles (Part 1)
m( 2:2:end, 1:2:end ) = '_';        % Alternate Spaces Between Bubbles (Part 2)

o = find( m == 'O' );               % Index Bubble Locations
r = o( randperm( nnz( o ) ) );      % Randomize Bubble Locations

disp( m );                          % Display Initial Bubble Wrap Phase

for i = r'
    pause( 1 );                     % Pause for 1 Second
    m( i ) = 'X';                   % Pop Bubble
    disp( m );                      % Display Subsequent Bubble Wrap Phase
end
Grant Miller
fonte