Une machine à grains maigre et moyenne

26

Un exemple classique pour initier les gens au concept d'une distribution de probabilité discrète est la machine à grains . Cette machine a une grande quantité de billes tombant d'un passage étroit en haut, après quoi elles frappent des rangées de broches entrelacées, où à chaque broche le marbre frappe, il peut tomber à gauche ou à droite de la broche. Enfin, les broches sont collectées dans des bacs verticaux au bas de la machine. Un schéma simple de cette machine ressemble à ceci:

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

Dans ce diagramme, le Osignifie l'emplacement d'où les billes tombent. Chacun ^est une épingle à laquelle le marbre a 50% de chances de se déplacer vers le carré à gauche ou à droite de l'épingle. Les billes se rassemblent ensuite dans les bacs au bas de l'appareil, et pour un nombre suffisamment important de billes, la hauteur des piles de marbre dans les bacs ressemblera à une distribution binomiale discrète.

Défi

Pour ce défi, vous calculerez la distribution de probabilité résultante des machines à grains en fonction de diagrammes comme celui ci-dessus. Les diagrammes sont interprétés comme un «programme» bidimensionnel que les billes traversent, soit vers des champs sur le côté, soit vers des champs en dessous du champ actuel. Lorsque les billes atteignent le bas de la machine, elles sont comptées pour la distribution de probabilité. Pour le garder intéressant, ces diagrammes contiendront quelques champs de plus que la simple source et les broches. Un exemple de diagramme est:

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

De plus, les billes ont désormais chacune un sens de rotation. Cette direction est définie par certains champs et détermine vers quel champ suivant le marbre se déplace dans plusieurs autres champs.

Les champs suivants sont définis:

  • O: La source. Génère des billes directement en dessous. La direction de ces billes est de 50% à gauche, 50% à droite. Chaque source produit la même quantité de billes.
  • U: Évier. Les billes qui entrent dans ce champ sont supprimées de la machine à grains.
  • : Espace libre. Si une bille arrive dans ce champ, elle se déplacera vers le champ ci-dessous.
  • -: Sol. Si une bille arrive dans ce champ, elle se déplacera vers le champ vers la gauche ou vers la droite, selon sa direction actuelle.
  • ^: Splitter. Si une bille arrive dans ce champ, elle a 50% de déplacement vers le champ vers la droite ou le champ vers la gauche du séparateur. Cela détermine également la direction du marbre.
  • v: Rejoignez. Si une bille arrive dans ce champ, elle se déplacera vers le champ ci-dessous.
  • /: Coussin incliné. Si une bille arrive dans ce champ, elle se déplacera sur le terrain à gauche du pavé, définissant la direction de la bille.
  • \: Identique à la précédente, mais à droite.
  • |: Réflecteur. Si une bille arrive dans ce champ, elle inversera la direction de la bille et déplacera la bille vers le champ vers la droite ou la gauche, en fonction de cette direction inversée.
  • =: Canon. Si une bille arrive dans ce champ, elle la déplacera vers la droite ou la gauche dans la direction actuelle, jusqu'à ce que la bille rencontre un champ qui ne l'est pas , -ouO .
  • <: Identique à la précédente, mais définit toujours la direction et se déplace vers la gauche.
  • >: Identique à la précédente, mais à droite.

Les garanties suivantes sont données concernant le schéma.

  • Chaque ligne d'entrée aura exactement la même longueur dans les champs.
  • Les champs les plus à gauche et à droite de chaque ligne seront toujours un | .
  • Le diagramme ne contiendra aucun chemin possible par lequel les billes peuvent se coincer dans la machine pour une quantité indéterminée d'itérations, comme \/ou^^ .
  • Le diagramme ne contiendra que les champs mentionnés ci-dessus.
  • Il existe une ou plusieurs sources

Résultat

Votre tâche consistera à générer un graphique à barres ASCII de 16 lignes de haut de la distribution de probabilité dans laquelle les billes sortent du bas du graphique, à l'échelle de sorte que la plus grande probabilité couvre les 16 caractères. Donc pour le problème suivant:

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

Votre programme doit produire la solution suivante (notez qu'il doit avoir la même largeur que le programme d'entrée, y compris les tuyaux sur le côté:

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

Exemples

Voici un exemple qui devrait tester la fonctionnalité de tous les différents types de champs:

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

Il devrait en résulter la sortie suivante:

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

Règles

Les fonctions et les programmes complets constituent des réponses valables à ce défi. Vous recevrez le diagramme sous forme de chaîne séparée par des sauts de ligne et vous devrez renvoyer le graphique de sortie dans le format donné. Règles d'entrée / sortie par défaut s'appliquent. Bien que les sauts de ligne de fin et de début soient autorisés dans la sortie, chaque ligne doit avoir exactement la même largeur que l'entrée.

Pour permettre des solutions plus créatives, il est seulement nécessaire que votre programme génère le résultat correct plus de 90% du temps pour le même diagramme. C'est une simulation de probabilité après tout.

Notation

C'est le , donc le score le plus bas en octets l'emporte.

CensoredUsername
la source
Beaucoup plus simple mais lié .
Peter Taylor
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Dennis
alors v= [space]?
l4m2
@ l4m2 vet [space]diffèrent dans la façon dont les canons interagissent autour d'eux.
CensoredUsername

Réponses:

8

Python 3 , 431 429 410 octets

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

Essayez-le en ligne!

Cette réponse est un effort de collaboration entre Wheat Wizard et CensoredUsername. Pour référence, il s'agit de l'algorithme non golfé.

-2 octets de M. Xcoder

-19 octets de CensoredUsername

Assistant Chapeau
la source
-2 octets si vous passez à Python 2 (instruction d'impression)?
caird coinheringaahing
1
De cela a été dit: 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
J'étais désespérément naïf quand j'ai dit ça. Cela dit, assurer la compétition de golf était assez amusant. Aussi @cairdcoinheringaahing, l'instruction print de python 2 est une instruction, pas une expression et elle ne peut donc pas être utilisée dans une compréhension de liste. Cela signifierait que la doublure en haut doit être divisée en plusieurs lignes en retrait, ce qui rendrait le gain de 2 octets de la suppression nulle.
CensoredUsername
4

Python 2 , 731 octets

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

Essayez-le en ligne!

-17 octets grâce au caird coinheringaahing

-12 octets grâce à Nathan Shiraini

-56 octets en passant à l'indentation mixte (Python 2)

-28 grâce à CensoredUsername car les probabilités sont normalisées à la fin, il n'est donc pas nécessaire que les probabilités de fin s'additionnent toujours à 1.

-7 octets grâce à la calculatrice féline en utilisant une fin plus courte elif instruction de .

-218 octets en fusionnant les deux fonctions

HyperNeutrino
la source
1052 octets
caird coinheringaahing
@cairdcoinheringaahing D'accord, merci.
HyperNeutrino
2
Dans les appels vers Ret Lcomme R(r+1-N,C+N,P,N=N)(premier appel vers R), vous n'avez pas besoin du N=à la fin; ça devrait être à la R(r+1-N,C+N,P,N)place.
Nathan.Eilisha Shiraini
@NathanShiraini D'accord, merci.
HyperNeutrino
... vous en avez oublié. Les 2 dernières lignes des deux Let R^^ De plus, votre deuxième niveau d'indentation est de 4 espaces partout, je pense que vous pourriez en faire 2.
Nathan.Eilisha Shiraini
3

C, 569 568 556 octets

Golfé

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

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

Modifications

Enregistré 12 octets en changeant ma macro de cas.

Remarques

Mon code utilise un système d'entiers de base 3 pour déterminer où le marbre se dirigera et se dirigera après (pour les canons et les trucs).

J'ai essayé donc j'ai dû battre cette solution python, je l'ai vraiment fait.

dj0wns
la source
1
Je compte 568 octets; peut-être avez-vous compté la nouvelle ligne de fuite? Et sacrément je me sens mal; déjoué en Python par C? Jeez ...: P
HyperNeutrino
Vous avez raison, j'ai laissé un petit dernier dans le fichier. Merci!
dj0wns