Una máquina de frijoles magra y mala

26

Un ejemplo clásico para presentar a las personas el concepto de una distribución de probabilidad discreta es la máquina de frijoles . Esta máquina tiene una gran cantidad de canicas que caen desde un pasadizo estrecho en la parte superior, después de lo cual golpean hileras de alfileres entrelazados, donde en cada alfiler golpea la canica puede caer a la izquierda o la derecha del alfiler. Finalmente, los pasadores se recogen en contenedores verticales en la parte inferior de la máquina. Un diagrama simple de esta máquina se ve así:

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

En este diagrama, Osignifica la ubicación de donde caen las canicas. Cada uno ^es un alfiler en el que la canica tiene un 50% de posibilidades de moverse al cuadrado a la izquierda o a la derecha del alfiler. Luego, las canicas se juntan en los contenedores en la parte inferior del dispositivo, y para un número suficientemente grande de canicas, la altura de las pilas de canicas en los contenedores se asemejará a una distribución binomial discreta.

Reto

Para este desafío, calculará la distribución de probabilidad resultante de las máquinas de frijoles en base a diagramas como el anterior. Los diagramas se interpretan como un "programa" bidimensional por el que pasan las canicas, ya sea hacia los campos laterales o los campos debajo del campo actual. Cuando las canicas alcanzan el fondo de la máquina, se cuentan para la distribución de probabilidad. Para mantenerlo interesante, estos diagramas contendrán algunos campos más que solo la fuente simple y los pines. Un diagrama de ejemplo es:

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

Además, las canicas ahora tienen una dirección de rotación. Esta dirección es establecida por algunos campos y determina a qué campo siguiente se mueve la canica en varios otros campos.

Se definen los siguientes campos:

  • O: Fuente. Genera canicas directamente debajo de él. La dirección de estas canicas es 50% izquierda, 50% derecha. Cada fuente produce la misma cantidad de canicas.
  • U: Lavabo. Cualquier canica que ingrese a este campo se elimina de la máquina de frijoles.
  • : Espacio vacio. Si una canica llega a este campo, se moverá al campo de abajo.
  • -: Suelo. Si una canica llega a este campo, se moverá al campo a la izquierda o al campo a la derecha, dependiendo de su dirección actual.
  • ^: Splitter. Si una canica llega a este campo, tiene un 50% de movimiento al campo a la derecha o al campo a la izquierda del divisor. Esto también determina la dirección de la canica.
  • v: Unirse. Si una canica llega a este campo, se moverá al campo de abajo.
  • /: Almohadilla inclinada. Si una canica llega a este campo, se moverá al campo a la izquierda de la plataforma, configurando la dirección de la canica.
  • \: Igual que el anterior, pero a la derecha.
  • |: Reflector. Si una canica llega a este campo, invertirá la dirección de la canica y la moverá al campo hacia la derecha o hacia la izquierda, en función de esta dirección inversa.
  • =: Cañón. Si una canica llega a este campo, la moverá hacia la derecha o hacia la izquierda en la dirección actual, hasta que la canica encuentre un campo que no sea , -o O.
  • <: Igual que el anterior, pero siempre establecerá la dirección y se moverá hacia la izquierda.
  • >: Igual que el anterior, pero a la derecha.

Las siguientes garantías se dan con respecto al diagrama.

  • Cada fila de entrada tendrá exactamente la misma longitud en los campos.
  • El campo más a la izquierda y a la derecha de cada fila siempre será a |.
  • El diagrama no contendrá ninguna ruta posible a través de la cual las canicas puedan quedar atrapadas en la máquina durante una cantidad indeterminada de iteraciones, como \/o ^^.
  • El diagrama solo contendrá los campos mencionados anteriormente.
  • Hay una o más fuentes

Resultado

Su tarea será generar un gráfico de barras ASCII de 16 líneas de altura de la distribución de probabilidad en la que las canicas salen del lado inferior del gráfico, escaladas de modo que la mayor probabilidad cubra los 16 caracteres. Entonces para el siguiente problema:

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

Su programa debe producir la siguiente solución (tenga en cuenta que debe tener el mismo ancho que el programa de entrada, incluidas las tuberías a un lado:

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

Ejemplos

El siguiente es un ejemplo que debería probar la funcionalidad de todos los diferentes tipos de campo:

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

Debería dar como resultado el siguiente resultado:

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

Reglas

Ambas funciones y programas completos constituyen respuestas válidas para este desafío. Recibirá el diagrama como una cadena separada por una nueva línea y deberá devolver el gráfico de salida en el formato dado. Se aplican las reglas predeterminadas de entrada / salida . Si bien las líneas nuevas y finales se permiten en la salida, cada fila debe tener exactamente el mismo ancho que la entrada.

Para permitir soluciones más creativas, solo se requiere que su programa muestre el resultado correcto más del 90% del tiempo para el mismo diagrama. Es una simulación de probabilidad después de todo.

Tanteo

Este es el , por lo que gana la puntuación más baja en bytes.

Nombre de usuario censurado
fuente
Mucho más simple pero relacionado .
Peter Taylor
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Dennis
entonces v= [space]?
l4m2
@ l4m2 vy [space]difieren en cómo los cañones interactúan a su alrededor.
CensuradoUsuario

Respuestas:

8

Python 3 , 431 429 410 bytes

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

Pruébalo en línea!

Esta respuesta es un esfuerzo de colaboración entre Wheat Wizard y CensoredUsername. Como referencia, este es el algoritmo sin golf.

-2 bytes del Sr. Xcoder

-19 bytes de CensoredUsername

Hat Wizard
fuente
-2 bytes si cambia a Python 2 (declaración de impresión)?
caird coinheringaahing
1
De esto se dijo: but I can confirm it's doable in 519 characters of python 3 code ;) I don't think I can golf mine much more- Nombre de usuario censurado
Stephen
Fui irremediablemente ingenuo cuando dije eso. Dicho esto, garantizar la competencia de golf fue bastante divertido. También @cairdcoinheringaahing, la declaración de impresión de python 2 es una declaración, no una expresión y, por lo tanto, no se puede usar en una comprensión de la lista. Esto significaría que el oneliner en la parte superior debe dividirse en varias líneas con sangría, lo que haría que la ganancia de 2 bytes al eliminarlo sea nula.
CensuradoNombre
4

Python 2 , 731 bytes

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

Pruébalo en línea!

-17 bytes gracias a caird coinheringaahing

-12 bytes gracias a Nathan Shiraini

-56 bytes cambiando a sangría mixta (Python 2)

-28 gracias a CensoredUsername porque las probabilidades se normalizan al final, por lo que no es necesario que las probabilidades finales siempre sumen 1.

-7 bytes gracias a la calculadora felina mediante el uso de una elifdeclaración final más corta .

-218 bytes fusionando las dos funciones

Hiperneutrino
fuente
1052 bytes
caird coinheringaahing
@cairdcoinheringaahing Correcto, gracias.
HyperNeutrino
2
En las llamadas a Ry Lcomo R(r+1-N,C+N,P,N=N)(primera llamada a R), no es necesario el N=al final; debería ser R(r+1-N,C+N,P,N)en su lugar.
Nathan.Eilisha Shiraini
@NathanShiraini Correcto, gracias.
HyperNeutrino
... te olvidaste un poco. Las últimas 2 líneas de ambos Ly R^^ Además, su segundo nivel de sangría es de 4 espacios en todas partes, creo que podría hacerlo 2.
Nathan.Eilisha Shiraini
3

C, 569 568 556 bytes

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

Sin golf

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

Ediciones

Ahorré 12 bytes cambiando mi macro de caso.

Notas

Mi código utiliza un sistema de enteros de base 3 para determinar hacia dónde se dirige la canica y hacia dónde se dirigirá (para cañones y demás).

Lo intenté, así que tuve que superar esa solución de Python, realmente lo hice.

dj0wns
fuente
1
Cuento 568 bytes; ¿quizás contó la nueva línea final? Y maldita sea me siento mal; superado en Python por C? Jeez ...: P
HyperNeutrino
Tienes razón, dejé una novela final en el archivo. ¡Gracias!
dj0wns