Crea un simulatore di avvolgimento a bolle


23

Le bolle sono intrattenimento di massimo livello. Tutti possono essere d'accordo.

Ora, farai divertire anche i computer con le bolle.

Specifiche

Ti verranno dati due numeri interi, w, e h. (Ognuno è responsivamente larghezza e altezza)

Il programma dovrebbe generare tutte le fasi w * h in attesa di 1 secondo tra ciascuna e terminare.

Ogni avvolgimento a bolle inizia con tutte le celle piene.

Ad esempio, un avvolgimento a bolle 4 * 6 inizia come:

O_O_
_O_O
O_O_
_O_O
O_O_
_O_O

E ogni fase, viene spuntata una cella casuale non pop-up. Ad esempio,

O_O_
_O_O
O_X_
_O_O
O_O_
_O_O

Il programma dovrebbe terminare quando tutte le celle sono spuntate. aka.

X_X_
_X_X
X_X_
_X_X
X_X_
_X_X

Esempi

(4,6)
(5,5)
(6,2)
(10,10)
(7,9)

Possiamo usare 1e 0invece di Oe X?
Pavel

1
NEEDZ BUBBLEZ invia aiuto
Christopher

3
È accettabile che (1,1)a non abbia bolle (ad es. La "cella" in alto a sinistra è sempre un trattino basso)?
Jonathan Allan,

1
@JonathanAllan Sì.
Matthew Roh,

1
@KevinCruijssen Non deve essere un programma completo.
Matthew Roh,

Risposte:


7

C (Windows), 260 248 byte

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

inserisci qui la descrizione dell'immagine


Nota che c'è una funzione sleep nella libreria thread, inclusa in C ++ 11.
Matthew Roh,

@MatthewRoh Sì, ma questo è più breve, ed system("cls")è anche specifico di Windows, quindi il codice non sarebbe più portatile con la libreria di thread. E con C ++ avrei anche bisogno di includere iostreamo cstdio.
Steadybox

tra l'altro non è necessario ripristinare lo schermo. questo lo renderà più breve.
Matthew Roh,

5

Python 3 , 222 220 byte

Questa è la prima volta che rispondo, quindi per favore sii gentile (e fai notare gli errori che ho fatto).

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)

Provalo online!

Come funziona:

  1. Incatena molti "0" insieme
  2. Taglia in '0_0 _... \ n' e '_0_0 ... \ n' parti e concatena
  3. Genera indici casuali fino a quando il carattere nell'indice è '0'
  4. Creare una nuova stringa con il carattere nell'indice generato viene sostituito con una 'X' (Accidenti a Python per stringhe non modificabili!)
  5. Ripetere i r*c+r%2*c%2tempi: ci sono r*cbolle nel motivo, a meno che r e c siano entrambe dispari, nel qual caso ci sono r*c+1.

1
Benvenuti in PPCG!
AdmBorkBork,

1
Questo è piuttosto minore, ma la tua larghezza e altezza sono invertite. Ottima risposta però! (Basta cambiarlo in f(c,r)e starai bene).
rassar

@rassar Woops, grazie!
nilo,

4

MATL , 37 byte

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

L'angolo in alto a sinistra è sempre un carattere di sottolineatura (consentito dalla sfida).

Lo schermo viene cancellato tra le fasi. Potrei salvare un byte non cancellando lo schermo, ma in questo modo sembra migliore.

Il programma si chiude con un errore ( consentito per impostazione predefinita ) dopo aver visualizzato tutte le fasi.

Provalo su MATL Online! (Se non funziona dopo un paio di secondi, aggiorna la pagina e riprova).


4

Mathematica (145 byte)

Funzione anonima, accetta l'altezza e la larghezza come input (in questo ordine - se questo è un problema, sostituiscilo {##}con {#2,#}al centro del codice per altri 2 byte).

Codice:

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

Spiegazione:

  • ""<>Riffle[Array["_"["O"][[Mod[#+#2,2]]]&,{##}],"\n"] crea l'involucro di bolle iniziale, non intatto, creando una matrice di "_" se "O" e quindi StringJining congiungendoli tra le nuove linee.
  • NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,..., Floor[##/2]]sceglie ripetutamente una delle "O" per sostituirla con una "X", tante volte quante sono le "O" (che è Floor [larghezza * altezza / 2] - grazie a @JonathanAllan per l'idea di mettere "_ "anziché" O "nell'angolo in alto a sinistra, altrimenti sarebbe Ceilinginvece e quindi 2 byte in più).
  • Monitor[Do[Pause@1,{i,...}],i]fa iprendere i valori nell'elenco che abbiamo appena calcolato, per 1 secondo ciascuno, e stampa dinamicamente i.

Esempio di output:

GIF di Mathematica popping bubble-wrap


3

Gelatina , 30 29 byte

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

Esempio di esecuzione

Chiama il collegamento come diade con gli argomenti del programma e quindi si chiude con un messaggio (il cui codice è çṛ“\'=ṙMḋḌẓ(ėo»)

Nuance: la "cella" in basso a destra sarà sempre una bolla (anziché quella in alto a sinistra come nell'esempio nella domanda), questo per garantire che quando tutte le bolle vengono saltate la scelta casuale restituisce 0 che sarà "X"il fine dell'elenco: la sostituzione non modifica il valore e interrompe il ciclo.

Nota: non cancella lo schermo (non è stato specificato e non sono sicuro di come).

Come?

=”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)

@ ГригорийПерельман lo ha scritto.
Jonathan Allan,

2

Scala , 764 byte

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

Come funziona

L'algoritmo riempie prima una sequenza 2D con valori falsi. Determina quante iterazioni (caselle aperte) esistono in base agli argomenti della riga di comando inseriti. Crea una piega con questo valore come limite superiore. Il valore intero della piega viene utilizzato implicitamente solo come modo per contare il numero di iterazioni per cui dovrebbe essere eseguito l'algoritmo. La sequenza riempita che abbiamo creato in precedenza è la sequenza iniziale per la piega. Questo è usato per generare una nuova sequenza 2D di valori falsi con le loro indecie rispondenti alle risposte.

Per esempio,

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

Sarà trasformato in

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

Si noti che tutti gli elenchi che sono completamente veri (hanno una lunghezza di 0) vengono omessi dall'elenco dei risultati. L'algoritmo quindi prende questo elenco e seleziona un elenco casuale nell'elenco più esterno. L'elenco casuale viene scelto per essere la riga casuale che scegliamo. Da quella riga casuale, troviamo di nuovo un numero casuale, un indice di colonna. Una volta trovati questi due indici casuali, dormiamo il thread su cui ci troviamo per 1000 milisecondi.

Dopo aver finito di dormire, cancelliamo lo schermo e creiamo una nuova scheda con un truevalore aggiornato negli indici casuali che abbiamo creato.

Per stamparlo correttamente, lo utilizziamo mape lo comprimiamo con l'indice della mappa in modo da tenerlo nel nostro contesto. Usiamo il valore di verità della sequenza sul fatto se dovremmo stampare un Xo o un Oo _. Per scegliere quest'ultimo, utilizziamo il valore dell'indice come nostra guida.

Cose interessanti da notare

Per capire se dovrebbe stampare un Oo un _, ((r._2 % 2) + c._2) % 2 == 0viene utilizzato il condizionale . r._2si riferisce all'indice di riga corrente mentre si c._2riferisce alla colonna corrente. Se uno è su una riga dispari, r._2 % 2sarà 1, quindi compensato c._2da uno nel condizionale. Ciò garantisce che sulle righe dispari, le colonne vengano spostate di 1 come previsto.

La stampa della stringa "\033[H\033[2J\n", secondo alcune risposte StackOverflow che ho letto, cancella lo schermo. Scrive byte sul terminale e fa cose funky che non capisco davvero. Ma l'ho trovato il modo più semplice per farlo. Tuttavia, non funziona sull'emulatore di console di Intellij IDEA. Dovrai eseguirlo usando un terminale normale.

Un'altra equazione che potresti trovare strana da vedere quando si guarda questo codice per la prima volta (l * k) / 2 - (l * k + 1) % 2. Innanzitutto, demistificare i nomi delle variabili. lfa riferimento ai primi argomenti passati nel programma mentre kfa riferimento al secondo. Per tradurlo, (first * second) / 2 - (first * second + 1) % 2. L'obiettivo di questa equazione è trovare l'esatta quantità di iterazioni necessarie per ottenere una sequenza di tutte le X. La prima volta che l'ho fatto, ho fatto semplicemente (first * second) / 2quello che aveva senso. Per ogni nelemento in ciascun elenco secondario, ci sono n / 2bolle che possiamo far scoppiare. Tuttavia, ciò si interrompe quando si tratta di input come(11 13). Dobbiamo calcolare il prodotto dei due numeri, renderlo dispari se è pari e anche se è dispari, quindi prendere la mod di quello per 2. Funziona perché le righe e le colonne che sono dispari richiedono una iterazione in meno per arrivare al risultato finale.

mapè usato al posto di a forEachperché ha meno caratteri.

Cose che probabilmente possono essere migliorate

Una cosa che mi infastidisce davvero di questa soluzione è l'uso frequente di zipWithIndex. Sta prendendo così tanti personaggi. Ho provato a farlo in modo da poter definire la mia funzione di un carattere che si limiterebbe a eseguire zipWithIndexcon il valore passato. Ma si scopre che Scala non consente a una funzione anonima di avere parametri di tipo. C'è probabilmente un altro modo di fare quello che sto facendo senza usare, zipWithIndexma non ho pensato troppo a un modo intelligente per farlo.

Attualmente, il codice viene eseguito in due passaggi. Il primo genera una nuova scheda mentre il secondo passaggio la stampa. Penso che se si combinassero questi due passaggi in un unico passaggio, si risparmierebbero un paio di byte.

Questo è il primo codice golf che ho fatto, quindi sono sicuro che ci sia molto spazio per miglioramenti. Se desideri vedere il codice prima che io abbia ottimizzato il più possibile i byte, eccolo qui.


1

JavaScript (ES6), 246 229 byte

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>


La larghezza non era in termini di celle, ma includeva spazi vuoti (sottolinea).
Matthew Roh,

@MatthewRoh Mi dispiace, mi sono ricordato di aggiustarlo per l'altezza ma ho dimenticato di controllare la larghezza.
Neil,

Hmm .. questa parte non può `${`_O`.repeat(w).slice(w)} ${`O_`.repeat(w).slice(w)}essere combinata in qualche modo? Forse una bandiera booleana per determinare prima _Oo O_, e poi fare il .repeat(w).slice(w)?
Kevin Cruijssen,

1
@KevinCruijssen Avevo perso 16 byte a causa di una rapida correzione di bug che non avevo avuto il tempo di giocare a golf in quel momento. Da allora ho dato un'altra occhiata e ho trovato un risparmio di 17 byte,
Neil

1

Python - 290 byte

Non ho mai fatto uno di questi prima - quindi ogni critica costruttiva sarebbe apprezzata :)

Il trucco principale qui è solo la comprensione dell'elenco fastidiosamente annidata. Potrei salvare alcuni personaggi non avendo una nuova riga tra i pop ma sembra brutto.

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)

Ciao, benvenuto in PPCG! La sfida era prendere we hcome input (tramite STDIN, come input di funzione o qualcosa di simile), invece di avere un hardcoded H=4 W=6. Inoltre, anche se non ho mai programmato in Python, penso che tu possa golf alcuni spazi nel tuo codice attuale. Suggerimenti per giocare a golf in Python potrebbero anche essere interessanti da leggere per darti idee su come giocare ulteriormente. Goditi la permanenza! :)
Kevin Cruijssen,

Inoltre, per quanto riguarda il tuo commento: " Potrei salvare alcuni personaggi non avendo una nuova riga tra i pop ma questo sembra brutto. " Non importa quanto brutto o quanto non lo sia nella programmazione nella vita reale, codegolf riguarda il salvataggio come più byte possibile. Più corto e brutto, meglio è. ;)
Kevin Cruijssen,

@KevinCruijssen il Python3 sopra di me lo ha solo in funzione di w, h, è permesso?
Arya,


1
Ok - L'ho reso una funzione di H e W ora.
Arya,

1

Carbone di legna , 49 46 39 byte (non competitivo)

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

1

APL (Dyalog) , 61 59 byte

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

⎕← output
m←m , dove m è
'O_'[... ] questi caratteri indicizzati da ...
2| la divisione-resto-quando-divisa-per-due della
-/¨ differenza tra ciascuna di
 tutte le coordinate (indici) in una matrice di
 input numerico di forma (il numero di righe e colonne )

(... )[... ]←'X' assegna il carattere X a uno degli ... elementi
b/ filtrati di b filtrati da b (da definire)
,m di m, in particolare ...
? un elemento casuale (lit. numero) nell'intervallo uno alla
+/ somma di
b←b , dove b è
'O'= booleano per dove la lettera è uguale a
,mm sfilacciato

⎕DL 1D e l ay uno seconda

→2 Vai alla riga 2
/⍨ se (illuminato. Filtrato da)
'O'∊ se la lettera è un membro del
⎕←m valore emesso, dove il valore emesso è m

Provalo online!


Dalla versione 16.0 sarà più breve:

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


1

Python 3, 195 188 byte

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)

Usare bytearraye decodesembra essere più breve dell'affettare e riassemblare una corda alla volta 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()

0

Java 7, 317 byte

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

Spiegazione:

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

Test gif (4,6)

inserisci qui la descrizione dell'immagine


0

Perl, 148 byte

146 byte di codice + -plflag.

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

Per eseguirlo:

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"

0

MATLAB (R2016b), 172 byte

Codice:

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

I consigli sono sempre ben accetti! Provalo online!

Uscita del programma:

inserisci qui la descrizione dell'immagine

Spiegazione:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.