Haz un simulador de envoltura de burbujas

23

Las envolturas de burbujas son entretenimiento de máximo nivel. Todos pueden estar de acuerdo con eso.

Ahora, incluso las computadoras disfrutarán de envolturas de burbujas.

Especificaciones

Se le darán dos enteros, w, y h. (Cada uno responde de ancho y alto)

Su programa debe generar todas las fases w * h esperando 1 segundo entre cada una y finalizar.

Cada envoltura de burbujas comienza con todas las celdas llenas.

Por ejemplo, una envoltura de burbuja de 4 * 6 comienza como:

O_O_
_O_O
O_O_
_O_O
O_O_
_O_O

Y en cada fase, se abre una celda aleatoria no reventada. Por ejemplo,

O_O_
_O_O
O_X_
_O_O
O_O_
_O_O

El programa debe finalizar cuando todas las celdas se abren. aka.

X_X_
_X_X
X_X_
_X_X
X_X_
_X_X

Ejemplos

(4,6)
(5,5)
(6,2)
(10,10)
(7,9)
Matthew Roh
fuente
¿Podemos usar 1y en 0lugar de Oy X?
Pavel
1
NEEDZ BUBBLEZ por favor envíe ayuda
Christopher
3
¿Es aceptable que un (1,1)no tenga burbujas (por ejemplo, la "celda" superior izquierda siempre es un guión bajo)?
Jonathan Allan
1
@JonathanAllan Sí.
Matthew Roh
1
@KevinCruijssen No tiene que ser un programa completo.
Matthew Roh

Respuestas:

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

ingrese la descripción de la imagen aquí

Steadybox
fuente
Tenga en cuenta que hay una función de suspensión en la biblioteca de subprocesos, que se incluye en C ++ 11.
Matthew Roh
@MatthewRoh Sí, pero esto es más corto y system("cls")también es específico de Windows, por lo que el código tampoco sería más portátil con la biblioteca de hilos. Y con C ++ también necesitaría incluir iostreamo cstdio.
Steadybox el
Por cierto, no es necesario restablecer la pantalla. eso lo hará más corto.
Matthew Roh
5

Python 3 , 222 220 bytes

Esta es la primera vez que respondo, así que sea amable (y señale los errores que he cometido).

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)

Pruébalo en línea!

Cómo funciona:

  1. Encadena muchos '0 _' 'juntos
  2. Pica las partes '0_0 _... \ n' y '_0_0 ... \ n' y concatena
  3. Genere índices aleatorios hasta que el carácter en el índice sea un '0'
  4. Crear una nueva cadena con el carácter en el índice generado se reemplaza con una 'X' (¡Maldita sea, Python por cadenas no mutables!)
  5. Repetir r*c+r%2*c%2tiempos: hay r*cburbujas en el patrón, a menos que r y c sean impares, en cuyo caso las hay r*c+1.
Nilo
fuente
1
Bienvenido a PPCG!
AdmBorkBork
1
Esto es bastante menor, pero su ancho y alto se invierten. Gran respuesta sin embargo! (Solo cámbialo f(c,r)y estarás bien).
rassar
@rassar Woops, gracias!
nilo
4

MATL , 37 bytes

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

La esquina superior izquierda siempre es un guión bajo (permitido por el desafío).

La pantalla se borra entre fases. Podría guardar un byte al no borrar la pantalla, pero se ve mejor de esta manera.

El programa sale con un error ( permitido por defecto ) después de mostrar todas las fases.

¡Pruébalo en MATL Online! (Si no funciona después de un par de segundos, actualice la página e intente nuevamente).

Luis Mendo
fuente
4

Mathematica (145 bytes)

Función anónima, toma la altura y el ancho como entrada (en ese orden; si eso es un problema, reemplácelo {##}con{#2,#} en el medio del código para un extra de 2 bytes).

Código:

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

Explicación:

  • ""<>Riffle[Array["_"["O"][[Mod[#+#2,2]]]&,{##}],"\n"] crea la envoltura de burbuja inicial, sin reventar, haciendo una matriz de "_" sy "O" y luego uniendo Cadena entre líneas nuevas.
  • NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,..., Floor[##/2]] elige repetidamente una de las "O" para reemplazar con una "X", tantas veces como haya "O" (que es Floor [width * height / 2] - gracias a @JonathanAllan por la idea de poner "_ "en lugar de" O "en la esquina superior izquierda, de lo contrario esto sería Ceiling lugar y, por lo tanto, 2 bytes más).
  • Monitor[Do[Pause@1,{i,...}],i]marcas itoman los valores de la lista que acabamos de calcular, durante 1 segundo cada uno, de forma dinámica y grabados i.

Salida de ejemplo:

GIF del envoltorio de burbujas emergente de Mathematica

No un arbol
fuente
3

Jalea , 30 29 bytes

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

Ejecución de ejemplo

Llama al enlace como una diada con los argumentos del programa y luego se cierra con un mensaje (cuyo código es çṛ“\'=ṙMḋḌẓ(ėo» )

Matiz: la "celda" inferior derecha siempre será una burbuja (en lugar de la superior izquierda como el ejemplo de la pregunta), esto es para garantizar que cuando se reventan todas las burbujas, la opción aleatoria devuelve 0, que será "X"el final de la lista: reemplazar eso no cambia el valor y rompe el ciclo.

Nota: no borra la pantalla (no se especificó, y no estoy seguro de cómo hacerlo).

¿Cómo?

=”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
fuente
@ ГригорийПерельман lo escribió.
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
    }
  }
}

Cómo funciona

El algoritmo primero llena una secuencia 2D con valores falsos. Determina cuántas iteraciones (cuadros abiertos) existen en función de los argumentos de la línea de comando introducidos. Crea un pliegue con este valor como límite superior. El valor entero del pliegue solo se usa implícitamente como una forma de contar cuántas iteraciones debe ejecutar el algoritmo. La secuencia rellena que creamos anteriormente es la secuencia de inicio para el pliegue. Esto se utiliza en la generación de una nueva secuencia 2D de valores falsos con sus indecisiones de co-respuesta.

Por ejemplo,

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

Se convertirá en

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

Tenga en cuenta que todas las listas que son completamente verdaderas (tienen una longitud de 0) se omiten de la lista de resultados. El algoritmo luego toma esta lista y elige una lista aleatoria en la lista más externa. La lista aleatoria se elige como la fila aleatoria que elegimos. Desde esa fila aleatoria, nuevamente encontramos un número aleatorio, un índice de columna. Una vez que encontramos estos dos índices aleatorios, dormimos el hilo en el que estamos durante 1000 milisegundos.

Una vez que terminamos de dormir, limpiamos la pantalla y creamos un nuevo tablero con un truevalor actualizado en los índices aleatorios que hemos creado.

Para imprimir esto correctamente, lo usamos mapy lo comprimimos con el índice del mapa para tenerlo en nuestro contexto. Usamos el valor de verdad de la secuencia en cuanto a si debemos imprimir una Xo una Oo_ . Para elegir este último, utilizamos el valor del índice como nuestra guía.

Cosas interesantes a tener en cuenta

Para determinar si debe imprimir una Oo una _, ((r._2 % 2) + c._2) % 2 == 0se usa el condicional . r._2se refiere al índice de fila actual mientras que se c._2refiere a la columna actual. Si uno está en una fila impar, r._2 % 2será 1, por lo tanto, compensado c._2por uno en el condicional. Esto asegura que en filas impares, las columnas se muevan en 1 según lo previsto.

Imprimir la cadena "\033[H\033[2J\n", de acuerdo con alguna respuesta de Stackoverflow que leí, borra la pantalla. Está escribiendo bytes en la terminal y haciendo algunas cosas funky que realmente no entiendo. Pero he descubierto que es la forma más fácil de hacerlo. Sin embargo, no funciona en el emulador de consola de Intellij IDEA. Tendrás que ejecutarlo usando una terminal regular.

Otra ecuación que uno puede encontrar extraño al ver este código por primera vez es (l * k) / 2 - (l * k + 1) % 2. Primero, desmitifiquemos los nombres de las variables. lse refiere a los primeros argumentos pasados ​​al programa mientras que se krefiere al segundo. Para traducirlo, (first * second) / 2 - (first * second + 1) % 2. El objetivo de esta ecuación es llegar a la cantidad exacta de iteraciones necesarias para obtener una secuencia de todas las X. La primera vez que hice esto, hice lo (first * second) / 2que tenía sentido. Para cada nelemento en cada sublista, hayn / 2 burbujas que podemos reventar. Sin embargo, esto se rompe cuando se trata de entradas como(11 13). Necesitamos calcular el producto de los dos números, hacerlo impar si es par, e incluso si es impar, y luego tomar el mod de eso por 2. Esto funciona porque las filas y columnas que son impares requerirán una iteración menos para llegar al resultado final.

mapse usa en lugar de a forEachporque tiene menos caracteres.

Cosas que probablemente puedan mejorarse

Una cosa que realmente me molesta de esta solución es el uso frecuente de zipWithIndex. Está tomando tantos personajes. Traté de hacerlo para poder definir mi propia función de un solo carácter que solo funcionaría zipWithIndexcon el valor pasado. Pero resulta que Scala no permite que una función anónima tenga parámetros de tipo. Probablemente haya otra forma de hacer lo que estoy haciendo sin usar, zipWithIndexpero no he pensado demasiado en una forma inteligente de hacerlo.

Actualmente, el código se ejecuta en dos pases. El primero genera un nuevo tablero mientras que el segundo pase lo imprime. Creo que si uno combinara estos dos pases en uno solo, ahorraría un par de bytes.

Este es el primer código de golf que he hecho, así que estoy seguro de que hay mucho margen de mejora. Si desea ver el código antes de que optimice los bytes tanto como sea posible, aquí está.

Stefan Aleksić
fuente
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
fuente
El ancho no estaba en términos de celdas, sino que incluía espacios en blanco (subrayados).
Matthew Roh
@MatthewRoh Lo siento, me acordé de arreglarlo para la altura, pero olvidé verificar el ancho.
Neil
Hmm ... no puede esta parte: `${`_O`.repeat(w).slice(w)} ${`O_`.repeat(w).slice(w)}¿combinarse de alguna manera? Tal vez una bandera booleana para determinar primero _Oo O_, y luego hacer el .repeat(w).slice(w)?
Kevin Cruijssen
1
@KevinCruijssen Había perdido 16 bytes debido a una corrección rápida de errores que no había tenido tiempo de jugar en ese momento. Desde entonces he echado otro vistazo y obtuve un ahorro de 17 bytes,
Neil
1

Python - 290 bytes

Nunca he hecho uno de estos antes, por lo que cualquier crítica constructiva sería apreciada :)

El truco principal aquí es solo comprensiones de listas molestamente anidadas. Podría salvar algunos personajes al no tener una nueva línea entre los pops, pero eso se ve feo.

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)
Aria
fuente
Hola, bienvenido a PPCG! El desafío era tomar el wy hcomo entrada (a través de STDIN, como una entrada de función, o algo similar), en lugar de tener un código rígido H=4 W=6. Además, aunque nunca programé en Python, creo que puedes jugar algunos espacios en tu código actual. Los consejos para jugar golf en Python también pueden ser interesantes de leer para darle ideas sobre cómo jugar más golf. ¡Disfruta tu estancia! :)
Kevin Cruijssen
Además, con respecto a su comentario: " Podría salvar algunos caracteres al no tener una nueva línea entre los pops, pero eso se ve feo " . No importa cuán feo o no hecho esté en la programación de la vida real, codegolf se trata de guardar tantos bytes como sea posible. Cuanto más corto y feo, mejor. ;)
Kevin Cruijssen
@KevinCruijssen, el Python3 que está encima de mí solo lo tiene en función de w, h, ¿está permitido?
Arya
1
Ok, ahora lo he convertido en una función de H y W.
Arya
1

Carbón , 49 46 39 bytes (sin competencia)

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

Verboso

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)
}
Solo ASCII
fuente
1

APL (Dyalog) , 61 59 bytes

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

⎕← salida
m←m , donde m es
'O_'[... ] estos caracteres indexados por ...
2| la división-resto-cuando-dividido-por-dos de
-/¨ la diferencia entre cada una de
 todas las coordenadas (índices) en una matriz de
 entrada numérica de forma (el número de filas y columnas )

(... )[... ]←'X' asigne el carácter X a uno de los ...  elementos desglosados
b/ filtrados por b (por definir)
,mde m, específicamente ...
? un elemento aleatorio (número iluminado) en el rango uno a
+/ la suma de
b←b , donde b es
'O'= booleano para donde la letra es igual a
,mm raveled

⎕DL 1D e l ay un segundo

→2 Vaya a la línea 2
/⍨ si (literalmente, filtrado por)
'O'∊ si la letra es un miembro del
⎕←m valor de salida, donde el valor de salida es m

Pruébalo en línea!


A partir de la versión 16.0 será más corto:

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

Adán
fuente
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)

Usando bytearrayy decodeparece ser más corto que cortar y volver a ensamblar una cuerda 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
fuente
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()));}}

Explicación:

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

Prueba gif (4,6)

ingrese la descripción de la imagen aquí

Kevin Cruijssen
fuente
0

Perl, 148 bytes

146 bytes de código + -plbanderas.

$_=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 ejecutarlo:

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
fuente
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

¡Las recomendaciones son siempre bienvenidas! Pruébalo en línea!

Salida del programa:

ingrese la descripción de la imagen aquí

Explicación:

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
fuente