L'expérience de la double fente


16

Un physicien paresseux a pour tâche de réaliser l'expérience à double fente. Cependant, ils sont paresseux et ne peuvent pas se soucier de configurer tous les équipements eux-mêmes et vont donc simuler les effets. Cependant, ils ne peuvent pas programmer et vont avoir besoin d'aide. Comme ils sont paresseux, votre programme doit être aussi court que possible.


Étant donné un entier positif impair n( n >= 1et n % 2 == 1), effectuez la simulation.

Comment ça fonctionne

Vous commencerez avec une toile vide et chaque image une seule particule de lumière passera par les fentes et atterrira sur la toile. La particule atterrira à un maximum avec une chance de:

n = 1:

+-----+
|     |
| 1/2 |
|     |
+-----+

n = 3:

+-----+ +-----+ +-----+
|     | |     | |     |
| 1/4 | | 1/2 | | 1/4 |
|     | |     | |     |
+-----+ +-----+ +-----+

n = 5:

+-----+ +-----+ +-----+ +-----+ +-----+
|     | |     | |     | |     | |     |
| 1/8 | | 1/4 | | 1/2 | | 1/4 | | 1/8 |
|     | |     | |     | |     | |     |
+-----+ +-----+ +-----+ +-----+ +-----+

etc.

Par exemple, pour n=5nous cochons la case du milieu, il y a 50% de chances de tomber dedans. S'il tombe en fin de trame, sinon passe aux deux suivants, il y a 25% de chances de tomber dans ceux-ci. S'il tombe en fin de trame, sinon passe aux deux suivants, il y a 12,5% de chances de tomber dans ceux-ci. S'il ne tombe pas, cela n'a pas d'importance, c'est quand même la fin du cadre.

Il y a eu une certaine confusion sur la façon de calculer les chances, la plupart de cela est dû au fait que les gens les considèrent comme des probabilités qui devraient s'additionner à 1. Retirez cette idée de votre esprit et cela devrait l'éclaircir un peu pour vous.

  • Au plus, une particule gisera par image, cela signifie qu'une particule ne peut pas du tout atterrir sur cette image.
  • Une particule peut être représentée par n'importe quel caractère imprimable.
  • La particule atterrira n'importe où dans la boîte avec une chance aléatoire.
  • La largeur des boîtes doit être 2n-1la taille de la toile. Donc, n=5ils devraient être 1/9th de la largeur de la toile.
  • La hauteur des boîtes doit être la hauteur de la toile.
  • La particule ne doit pas du tout atterrir à l'extérieur des boîtes.
  • Si une particule a déjà atterri à un endroit choisi peu importe, elle peut y atterrir à nouveau.
  • Les cases ascii ci-dessus sont pour plus de clarté, elles ne doivent pas être dessinées.
  • Vous pouvez choisir votre propre taille de toile tant qu'elle est raisonnable. Par exemple, il ne doit pas seulement faire quelques pixels de haut. Il devrait également pouvoir contenir toutes les boîtes dessus.
  • Si votre code dort entre les trames, vous n'avez pas besoin d'ajouter cela dans votre nombre d'octets.

Il devrait y avoir des écarts entre chacun des maxima, un minimum. Cela devrait avoir la même largeur qu'une boîte mais aucune particule n'y atterrira. Voir le schéma suivant:

+---+---+---+---+---+
|   |   |   |   |   |
|max|min|max|min|max|
|   |   |   |   |   |
+---+---+---+---+---+

Le programme doit s'exécuter jusqu'à ce qu'il soit arrêté manuellement.

Règles

  • Un générateur de nombres pseudo aléatoires (pRNG) est très bien.
  • Les failles standard sont interdites.
  • L'entrée peut être prise par n'importe quel format raisonnable.
  • Vous devez sortir vers STDOUT.
  • C'est le donc la réponse la plus courte l'emporte.

Exemple

Le GIF suivant est un exemple exécuté pour n = 5. Je ne l'ai fait que rapidement, donc les chances peuvent être légèrement réduites.

Exemple de double fente


Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Martin Ender

Réponses:


4

Python 2, 207 200 octets

Il y a une méthode à cette folie, je le promets. Suit l'interprétation de probabilité que j'ai commentée dans le PO.

Edit: -7 octets grâce à une évaluation paresseuse intelligente (et en supprimant certains signes)

import time  # not counted for byte total
import random as R,curses as C
r=R.randint
c=C.initscr()
h,w=c.getmaxyx()
n=input()
w/=2*n-1
while 1:
 all(r(0,1)or c.addch(r(0,h-1),(i*(2-4*r(0,1))+n)*w-r(1,w),42)for i in range(n/2+1))
 c.refresh()
 time.sleep(0.1)  # not counted for byte total

4

BASH, 396 - 11 = 385 octets

E='echo -en';$E "\e[2J\e[99A";while :;do sleep 0.01;for i in `seq $((($1+1)/2)) -1 1`;do p=$(((($1+1)/2 - $i)));[ $p -lt 0 ]&&p=$((-$p));p=$((2**(p+1)));if [ $RANDOM -lt $((32768/$p)) ];then [ $(($RANDOM%2)) -eq 1 ]&&i=$((($1+1)-i));sector=$(((i*2-1)-1));C=`tput cols`;R=`tput lines`;SS=$((C/($1*2-1)));SX=$((SS*sector));X=$((SX+(RANDOM%SS)));Y=$((RANDOM%R));$E "\e[$Y;${X}H*";break;fi;done;done

Malheureusement, je ne peux pas le démontrer sur TryItOnline en raison de la boucle sans fin et des séquences d'échappement ANSI qui déplacent le curseur, mais vous pouvez toujours le copier-coller dans votre terminal!

Version non minimisée:

E='echo -en'
$E "\e[2J\e[99A"

while :
do
    sleep 0.01
    for i in `seq $((($1+1)/2)) -1 1`
    do
        p=$(((($1+1)/2 - $i)))
        [ $p -lt 0 ] && p=$((-$p));
        p=$((2**(p+1)))
        if [ $RANDOM -lt $((32768/$p)) ]
        then
            [ $(($RANDOM%2)) -eq 1 ] && i=$((($1+1)-i));
            sector=$(((i*2-1)-1))
            C=`tput cols`
            R=`tput lines`
            SS=$((C/($1*2-1)))
            SX=$((SS*sector))
            X=$((SX+(RANDOM%SS)))
            Y=$((RANDOM%R))
            $E "\e[$Y;${X}H*"
            break
        fi
    done
done

1
Consultez les conseils pour jouer au golf à bash . Vous pouvez récolter ici quelques fruits faciles à suspendre, par exemple $[ ]au lieu de $(( )). Au lieu de for i in `seq $((($1+1)/2)) -1 1`;do ...;done, essayez for((i=($1+1)/2;i>0;i--));{ ...;}. Au lieu de [ $(($RANDOM%2)) -eq 1 ], essayez ((RANDOM%2)). sector, SS, Etc doit être remplacé par 1 noms de variables char.
Digital Trauma

3

Mathematica, 231 octets

(R=RandomInteger;p=20(#+1)+10;s=Array[0&,{20,6p-3}];i=(#+1)/2;Monitor[While[1<2,y=RandomChoice[Join[q=Riffle[Array[2^#&,i,0],Table[0,i-1]],Reverse@Most@q]->Array[Range[4#+1]&,i,0][[i]]];s[[R@19+1,10y-R@9]]=1;s],Grid[s//. 0->" "]])&


contribution

[5]

production

entrez la description de l'image ici


Cela semble invalide, pour n = 5, il ne devrait y avoir que 5 cases, vous en avez 9
TheLethalCoder

J'ai réalisé que je comptais comme {... 3,2,1,2,3 ...}. Je peux le réparer s'il n'est pas accepté
J42161217

2
@TheLethalCoder Fixed! Amélioré! Golfé!
J42161217

Ça a l'air bien, vote positif de ma part
TheLethalCoder

2

C # (.NET 4.5), 319 254 octets

65 octets enregistrés grâce à TheLethalCoder!

namespace System{using static Console;n=>{for(var r=new Random();;)for(int w=WindowWidth/(2*n-1),i=(n-1)/2,c=0,m=2,l;i>-1;i--,c+=2)if((l=r.Next(0,(m*=2+1)*2))<2){SetCursorPosition((i+(l<1?c:0))*2*w+r.Next(0,w),r.Next(0,WindowHeight));Write('*');break;}}}

Ouf, c'était beaucoup de travail, mais ça marche d'une manière ou d'une autre.

Comme cela utilise Consoledes fonctions spécifiques et Thread sleep, cela ne fonctionnera malheureusement pas sur TIO.


Compiler en un Action<int>pour enregistrer les octets, while(true)-> ( while(1>0)-> for(;;). using C=Console;Ou using static Console;.
TheLethalCoder

Cette demande est également autorisée à être délégué? Je ne le savais pas. Je le mettrai à jour dans une seconde.
Ian H.

Les programmes / fonctions sont autorisés par défaut et les lambdas anonymes comptent comme des fonctions (bien que les règles les concernant deviennent un peu plus profondes lorsque vous devez les appeler).
TheLethalCoder

255 octetsnamespace System{using static Console;n=>{for(var r=new Random();;)for(int w=WindowWidth/(2*n-1),i=(n-1)/2,c=0,m=2,l;i>-1;i--,c+=2)if((l =r.Next(0,(m*=2+1)*2))<2){SetCursorPosition((i+(l<1?c:0))*2*w+r.Next(0,w),r.Next(0,WindowHeight));Write('*');break;}}}
TheLethalCoder

@TheLethalCoder Ce code ne fonctionne pas: / donne juste beaucoup d' Variable is not existing in the current contexterreurs.
Ian H.

1

Clojure + Quil, 394 octets

(use '[quil.core])(defn -main[n](let[w 999 h 100 c(/ w(-(* n 2)1))s(range 0 w c)a(vec(take-nth 2 s))v(fn[x](<(rand)x))q(fn[a b](+ a(rand-int(- b a))))g(for[i(range(int(/ n 2))-1 -1)][i(- n 1 i)])z(for[[j i](map vector(range 1(inc(count g)))g)][(/ 1(Math/pow 2 j))i])](defsketch m :size[w h]:draw #(loop[[[p i]& r]z](when p(if(v p)(let[o(a(rand-nth i))](point(q o(+ o c))(q 0 h)))(recur r)))))))

Eh bien, je n'ai certainement pas gagné, mais c'était un bon entraînement cérébral! J'ai peut-être choisi une façon trop détournée de le faire, mais cela fonctionne! Fondamentalement, comment cela fonctionne:

  1. Les valeurs x de chaque colonne sont calculées en fonction de n. Ensuite, les "colonnes actives" qui contiendront les points sont filtrées. Les colonnes sont ensuite zippées avec les possibilités qu'elles seront choisies.

  2. L'animation démarre et à chaque image, une boucle est entrée. En partant du milieu, chaque paire de colonnes est essayée. Une fois qu'une paire de colonnes est choisie, une colonne de la paire est choisie au hasard.

  3. Un point est dessiné à une position aléatoire dans la colonne choisie, la boucle intérieure se termine et un nouveau cadre commence.

Utilise la bibliothèque graphique Quil, qui est essentiellement un wrapper de traitement pour Clojure.

Remarque, le code golfé ne produit pas la même animation que celle montrée dans le GIF. Dans le code golfé, l'arrière-plan est gris et la fenêtre et les points sont plus petits. Cela a le même effet, ce n'est pas aussi joli.

GIF

Voir le code non golfé pour une explication approfondie:

(ns bits.golf.interference.interference
  (:require [quil.core :as q]))

; Canvas size
(def width 1800)
(def height 800)

(defn -main [n]
  (let [col-width (/ width (- (* n 2) 1))
        ; The left-most x of each column
        col-starts (range 0 width col-width)

        ; The columns that need to be drawn. Need "vec" so I can index it later.
        active-cols (vec (take-nth 2 col-starts))

        ; Function taking a decimal percentage, and returning whether or not it's satisfied.
        ; (chance? 0.5) would be used to simulate a coin toss.
        chance? (fn [perc] (< (rand) perc))

        ; Function that returns a random int between a and b
        r-int (fn [a b] (+ a (rand-int (- b a))))

        ; Generates index pairs for each complimentary column.
        indices (for [i (range (int (/ n 2)) -1 -1)]
                  [i (- n 1 i)])

        ; Zips each index pair from above with the chance that it will be" chosen"
        zipped-perc (for [[j i] (map vector (range 1 (inc (count indices))) indices)]
                      [(/ 1 (Math/pow 2 j)) i])]

    ; Animation boilerplate
    (q/defsketch Interference
      :size [width height]
      :draw
      ; The animation loop. It contains a loop over each complimentary column. It tries each column pair starting
      ;  from the middle, and works outward. Once it picks a pair of columns, it randomly chooses one of them.
      #(loop [[[p i] & r] zipped-perc]
         (when p
           ; Pick this column?
           (if (chance? p)
             ; Pick one of the column pairs
             (let [col (active-cols (rand-nth i))]
               ; Set the coloring and dot size
               (q/fill 0 0 0)
               (q/stroke-weight 5)
               ; And finally draw the dot
               (q/point (r-int col (+ col col-width))
                        (r-int 0 height)))

             ; If the column wasn't chosen, loop again to try the next one
             (recur r)))))))

0

C #, 238 octets

namespace System{using static Console;n=>{for(var r=new Random();;)for(int i=0,p=1,w=WindowWidth/(2*n-1),x;i<n+1;i+=2)if(r.Next(p*=2)<1){SetCursorPosition(r.Next(x=(n-1+(r.Next(2)<1?i:-i))*w,x+w),r.Next(WindowHeight));Write("*");break;}}}

Essayez-le en ligne! (Ça ne marchera pas mais tu sais).

Version complète / formatée:

namespace System
{
    using static Console;

    class P
    {
        static void Main()
        {
            Action<int> f = n =>
            {
                for (var r = new Random(); ;)
                {
                    for (int i = 0, p = 1, w = WindowWidth / (2 * n - 1), x; i < n + 1; i += 2)
                        if (r.Next(p *= 2) < 1)
                        {
                            SetCursorPosition(r.Next(x = (n - 1 + (r.Next(2) < 1 ? i : -i)) * w, x + w), r.Next(WindowHeight));
                            Write("*");
                            break;
                        }

                    Threading.Thread.Sleep(25);
                }
            };

            f(5);
        }
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.