Una macchina per fagioli magra e cattiva


26

Un classico esempio per introdurre le persone al concetto di distribuzione discreta delle probabilità è la macchina da fagioli . Questa macchina ha una grande quantità di biglie che cadono da uno stretto passaggio nella parte superiore, dopo di che colpiscono file di perni intrecciati, dove ad ogni perno il marmo colpisce potrebbe cadere a sinistra o a destra del perno. Infine, i perni sono raccolti in bidoni verticali nella parte inferiore della macchina. Un semplice diagramma di questa macchina è simile al seguente:

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |
|_|_|_|_|_|_|

In questo diagramma, Oindica la posizione da cui cadono i marmi. Ciascuno ^è un perno in corrispondenza del quale il marmo ha una probabilità del 50% di spostarsi sul quadrato a sinistra o a destra del perno. I marmi si raccolgono quindi sui contenitori nella parte inferiore del dispositivo e, per un numero sufficiente di marmi, l'altezza delle pile di marmo nei contenitori assomiglierà a una distribuzione binomiale discreta.

Sfida

Per questa sfida, calcolerai la distribuzione di probabilità risultante delle macchine bean in base a diagrammi come quello sopra. I diagrammi sono interpretati come un "programma" bidimensionale attraverso il quale passano i marmi, verso campi laterali o sotto il campo corrente. Quando i marmi raggiungono il fondo della macchina vengono contati per la distribuzione di probabilità. Per mantenerlo interessante, questi diagrammi conterranno alcuni campi in più rispetto alla semplice sorgente e ai pin. Un diagramma di esempio è:

|     O     |
|     ^     |
|    ^ /    |
|   ^ | ^   |
|  <^- =  v |
| ^ ^ ^ ^ ^ |

Inoltre, i marmi ora hanno ciascuno una direzione di rotazione. Questa direzione è impostata da alcuni campi e determina in quale campo successivo il marmo si sposta in molti altri campi.

Sono definiti i seguenti campi:

  • O: Fonte. Genera marmi direttamente sotto di esso. La direzione di questi marmi è del 50% a sinistra, del 50% a destra. Ogni fonte produce la stessa quantità di marmi.
  • U: Lavello. Tutti i marmi che accedono a questo campo vengono rimossi dalla macchina bean.
  • : Spazio vuoto. Se un marmo arriva in questo campo, si sposterà nel campo sottostante.
  • -: Pavimento. Se un marmo arriva in questo campo, si sposterà sul campo a sinistra o sul campo a destra, a seconda della sua direzione corrente.
  • ^: Splitter. Se un marmo arriva in questo campo, ha il 50% di spostarsi sul campo a destra o sul campo a sinistra dello splitter. Questo determina anche la direzione del marmo.
  • v: Aderire. Se un marmo arriva in questo campo, si sposterà nel campo sottostante.
  • /: Pad inclinato. Se un marmo arriva in questo campo, si sposterà nel campo a sinistra del pad, impostando la direzione del marmo.
  • \: Uguale al precedente, ma a destra.
  • |: Riflettore. Se un marmo arriva in questo campo, invertirà la direzione del marmo e lo sposterà nel campo a destra oa sinistra, in base a questa direzione invertita.
  • =: Cannone. Se un marmo arriva in questo campo, lo sposta a destra o a sinistra nella direzione corrente, fino a quando il marmo incontra un campo che non lo è , -o O.
  • <: Uguale al precedente, ma imposta sempre la direzione e si sposta verso sinistra.
  • >: Uguale al precedente, ma a destra.

Le seguenti garanzie sono fornite per quanto riguarda il diagramma.

  • Ogni riga di input avrà esattamente la stessa lunghezza nei campi.
  • Il campo più a sinistra e più a destra di ogni riga sarà sempre a |.
  • Il diagramma non conterrà alcun percorso possibile attraverso il quale i marmi possono rimanere bloccati nella macchina per una quantità indeterminata di iterazioni, come \/o ^^.
  • Il diagramma conterrà solo i campi sopra menzionati.
  • Ci sono una o più fonti

Risultato

Il tuo compito sarà quello di generare un grafico a barre ASCII alto 16 righe della distribuzione di probabilità in cui i marmi escono dal lato inferiore del grafico, ridimensionato in modo che la probabilità più grande copra tutti i 16 caratteri. Quindi per il seguente problema:

|     O     |
|     ^     |
|    ^ ^    |
|   ^ ^ ^   |
|  ^ ^ ^ ^  |
| ^ ^ ^ ^ ^ |

Il tuo programma dovrebbe produrre la seguente soluzione (nota che dovrebbe avere la stessa larghezza del programma di input, compresi i tubi a lato:

     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
     # #     
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
   # # # #  
 # # # # # #
 # # # # # # 

Esempi

Di seguito è riportato un esempio che dovrebbe testare la funzionalità di tutti i diversi tipi di campo:

|     O     O         |
|  O  ^ /  <^\\\      |
|    ^ >            ^ |
|   ^ ^ ^            =|
|  ^ ^ | ^    <^   O  |
| ^ > ^ | ^   O ^> v  |
||  ^U  ^  |  =    ^\ |
|  ^ ^ ^ ^U ^\ ---^   |
| = ^   ^     =    v  |

Dovrebbe risultare nel seguente output:

                     # 
                     # 
                     # 
                     # 
                   # # 
                   # # 
                   # # 
       # #         # # 
       # #         # # 
       # #         # # 
       # #         # # 
      ## #         # # 
      ## # #       # # 
   # ### # #       # # 
 # # ### # #       # # 
 # # ### # #       # # 

Regole

Sia le funzioni che i programmi completi costituiscono risposte valide per questa sfida. Riceverai il diagramma come una stringa separata da nuova riga e dovresti restituire il grafico di output nel formato specificato. Si applicano le regole di input / output predefinite . Mentre nell'output sono consentiti il ​​trascinamento e le nuove righe iniziali, ogni riga deve avere esattamente la stessa larghezza dell'input.

Per consentire soluzioni più creative, è necessario solo che il tuo programma produca il risultato corretto più del 90% delle volte per lo stesso diagramma. Dopotutto è una simulazione di probabilità.

punteggio

Questo è , quindi vince il punteggio più basso in byte.


Molto più semplice ma correlato .
Peter Taylor,

I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Dennis,

così v= [space]?
l4m2

@ l4m2 ve [space]differiscono nel modo in cui i cannoni interagiscono intorno a loro.
CensoredUsername

Risposte:


8

Python 3 , 431 429 410 byte

def t(a):e=enumerate;p=a.split("\n");o=[0]*len(p[0]);{m(i,j,p,o,1):m(i,j,p,o,-1)for i,r in e(p)for j,c in e(r)if"O"==c};[print("".join(" #"[round(16*r/max(o)+i)>15]for r in o))for i in range(16)]
def m(r,k,p,o,l,x=1):
 while r<len(p):
  c=p[r][k]
  if"^"==c:x/=2;m(r,k-l,p,o,l,x)
  if"U"==c:return
  if c in" vO":r+=1;continue
  l=[1,l,-1,l,-l,1][ord(c)%6];k-=l
  while";"<c<"?"and p[r][k]in" O-":k-=l
 o[k]+=x

Provalo online!

Questa risposta è uno sforzo collaborativo tra Wheat Wizard e CensoredUsername. Per riferimento, questo è l'algoritmo ungolfed.

-2 byte dal signor Xcoder

-19 byte da CensoredUsername


-2 byte se si passa a Python 2 (istruzione di stampa)?
caird coinheringaahing

1
Di questo è stato detto: but I can confirm it's doable in 519 characters of python 3 code ;) I don't think I can golf mine much more- CensoredUsername
Stephen

Ero irrimediabilmente ingenuo quando l'ho detto. Detto questo, garantire la competizione del golf era abbastanza divertente. Anche @cairdcoinheringaahing, l'affermazione di stampa di python 2 è un'affermazione, non un'espressione e non può quindi essere utilizzata nella comprensione di un elenco. Ciò significherebbe che l'oneliner in alto deve essere suddiviso in più righe rientrate che renderebbero nullo il guadagno di 2 byte rimuovendolo.
CensoredUsername

4

Python 2 , 731 byte

i=raw_input
l=i()
c=[]
while l:c,l=c+[l],i()
p=[[0]*len(l)for l in c]+[[0]*max(map(len,c))]
S=lambda r,C,p:r>=0and C>=0and r<len(p)and C<len(p[r])
def U(r,C,P,D,N=0):
 if S(r,C,p):p[r][C]+=P
 if S(r,C,c):
	K=c[r][C]
	if K in' O':U(r+1-N,C+D*N,P,D,N)
	elif'v'==K:U(r+1,C,P,D)
	elif'-'==K:U(r,C+D,P,D,N)
	elif'^'==K:U(r,C-1,P/2,-1);U(r,C+1,P/2,1)
	elif'/'==K:U(r,C-1,P,-1)
	elif'\\'==K:U(r,C+1,P,1)
	elif'='==K:U(r,C+D,P,D,1)
	elif'>'==K:U(r,C+1,P,1,1)
	elif'<'==K:U(r,C-1,P,-1,1)
	elif'|'==K:U(r,C-D,P,-D)
for r in range(len(c)):
 for C in range(len(c[r])):
	if'O'==c[r][C]:U(r+1,C,1.,1);U(r+1,C,1.,-1)
p=p[-1][::-1]
s=16/max(p)
f=['#'*min(int(n*s),16)+' '*min(int(16-n*s),16)for n in p]
print('\n'.join(map(''.join,zip(*f)))[::-1])

Provalo online!

-17 byte grazie a cahing coinheringaahing

-12 byte grazie a Nathan Shiraini

-56 byte passando al rientro misto (Python 2)

-28 grazie a CensoredUsername perché le probabilità sono normalizzate alla fine, quindi non è necessario che le probabilità finali sommino sempre fino a 1.

-7 byte grazie alla calcolatrice felina usando una eliffrase finale più breve .

-218 byte unendo le due funzioni



@cairdcoinheringaahing Giusto, grazie.
HyperNeutrino,

2
Nelle chiamate a Re Lcome R(r+1-N,C+N,P,N=N)(prima chiamata a R), non è necessario N=alla fine; dovrebbe essere R(r+1-N,C+N,P,N)invece.
Nathan.Eilisha Shiraini,

@NathanShiraini Bene, grazie.
HyperNeutrino,

... te ne sei dimenticato. Le ultime 2 righe di entrambi Le R^^ Inoltre, il tuo secondo livello di rientro è di 4 spazi ovunque, penso che potresti farcela 2.
Nathan.Eilisha Shiraini,

3

C, 569 568 556 byte

golfed

#define A s[1]
#define c(i,j,k) break;case i:x=j;y=k;
w,S,i,j,d,x,y,z;main(int*a,char**s){w=strchr(&A[1],'|')+2-A;a=calloc(w,4);for(;i++<'~~';j=0){for(;A[j];){if(A[z=j++]==79){d=rand()%2;x=4;y=7;z+=w;for(;z<strlen(A);){z+=x%3-1+(y%3-1)*w;switch(A[z]){case 85:goto e;c(32,x/3*(3+1),y/3*(3+1))c(45,d*2+3,7)c(94,(d=rand()%2)*2+3,7)c(118,4,8)c(47,3,7)d=0;c(92,5,7)d=1;c(124,(d=!d)*2+3,7)c(60,x,y)case 62:d=A[z]/2%2;case 61:x=d*8;y=4;}}a[z%w]++;e:;}}}for(i=-1;++i<w;S=a[i]>S?a[i]:S);for(j=17;j-->1;puts(""))for(i=0;i<w-1;printf("%c",a[i++]*16./S+0.6<j?32:35));}

Ungolfed

//Variable Definitions
//direction - marbles current direction, 0 -> left, 1-> right
//arrwidth - width of array
//x - change in x of marble in base 3 - 0 -> Left, 1 -> stay, 2-> right
//y - change in y of marble in base 3 - 0 -> Up, 1 -> stay, 2-> Down
//z - position of marble
//i - iterator on runs of program
//j - iterator on string
//k - iterator on outputstring
//argc - array holding all buckets

#define c(i,j,k) break;case i:x=j;y=k;

arrwidth,scale,i,j,direction,x,y,z;

main(int *argc, char**argv){
  arrwidth=strchr(&A[1],'|')+2 - A; //get width
  argc=calloc(arrwidth,4);
  for(;i++<'~~';j=0){
    for(;A[j];){
      if(A[z=j++] == 79){ //if it finds an O, start sim
        direction=rand()%2;
        x=4;
        y=7;
        z+=arrwidth;
        for(;z<strlen(A);){
          z+=x%3-1 + (y%3-1)*arrwidth;
          switch (A[z]){
            case 85://marble dies dont record
              goto e;
            c(32,x/3*(3+1),y/3*(3+1)) //case ' '
            c(45,direction*2+3,7)    //case -
            c(94,(direction=rand()%2)*2+3,7)    //case ^
            c(118,4,8)    //case v
            c(47,3,7)    //case /
              direction=0;
            c(92,5,7)   //case '\'
              direction=1;
            c(124,(direction=!direction)*2+3,7)
            c(60,x,y)    //case <
            case 62:    //case >
              direction=A[z]/2%2;
            case 61:  //case =
              x=direction*8;
              y=4;
          }
        }
        argc[z%arrwidth]++;
        e:;
      }
    }
  }
  //get output answer in terms of '#'
  for(i=-1;++i<arrwidth;scale=argc[i]>scale?argc[i]:scale);
  for(j=17;j-->1;puts(""))
    for(i=0; i < arrwidth-1;printf("%c",argc[i++]*16./scale+0.6<j?32:35));
}

Le modifiche

Ho salvato 12 byte modificando la mia macro del caso.

Gli appunti

Il mio codice utilizza un sistema di numeri interi di base 3 per determinare dove si dirige il marmo e sarà diretto dopo (per cannoni e roba).

Ho provato, quindi ho dovuto battere quella soluzione Python, l'ho fatto davvero.


1
Conto 568 byte; forse hai contato la nuova riga finale? E dannatamente mi sento male; superato in Python da C? Accidenti ...: P
HyperNeutrino,

Hai ragione, ho lasciato un newling finale nel file. Grazie!
dj0wns
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.