L'esperimento a doppia fenditura


16

Un fisico pigro ha il compito di eseguire l'esperimento a doppia fenditura. Tuttavia, sono pigri e non possono preoccuparsi di installare tutto l'equipaggiamento da soli e quindi simuleranno gli effetti. Non possono programmare, quindi avranno bisogno di aiuto. Dato che sono pigri, il programma dovrebbe essere il più breve possibile.


Dato un numero intero dispari positivo n( n >= 1e n % 2 == 1), eseguire la simulazione.

Come funziona

Inizierai con una tela vuota e ogni cornice una singola particella di luce attraverserà le fessure e atterrerà sulla tela. La particella atterrerà ai massimi con una possibilità di:

n = 1:

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

n = 3:

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

n = 5:

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

eccetera.

Ad esempio, n=5se selezioniamo la casella centrale, c'è una probabilità del 50% di cadere al suo interno. Se cade alla fine del frame, se non passa ai due successivi, c'è una probabilità del 25% di cadere in quelli. Se cade alla fine del fotogramma, se non passa ai due successivi, c'è una probabilità del 12,5% di cadere in quelli. Se non cade, non importa, è comunque la fine del fotogramma.

C'è stata una certa confusione su come calcolare le possibilità, la maggior parte di ciò è dovuto al fatto che le persone le considerano come probabilità che dovrebbero sommare a 1. Rimuovi quell'idea dalla tua mente e dovrebbe chiarirla un po 'per te.

  • Al massimo una particella verrà caricata per frame, questo significa che una particella potrebbe non atterrare affatto su quel frame.
  • Una particella può essere rappresentata da qualsiasi carattere stampabile.
  • La particella atterrerà ovunque nella scatola con una possibilità casuale.
  • La larghezza delle scatole dovrebbe essere 2n-1la dimensione della tela. Quindi n=5dovrebbero essere 1/9la larghezza della tela.
  • L'altezza delle scatole dovrebbe essere l'altezza della tela.
  • La particella non dovrebbe atterrare al di fuori delle scatole.
  • Se una particella è già atterrata in un punto scelto, non importa, può atterrare di nuovo lì.
  • Le caselle ASCII sopra sono per chiarezza, non devono essere disegnate.
  • Puoi scegliere la tua dimensione di tela purché sia ​​ragionevole. Ad esempio, non deve essere alto solo pochi pixel. Dovrebbe anche essere in grado di adattare tutte le scatole su di esso.
  • Se il codice si trova tra i frame, non è necessario aggiungerlo nel conteggio dei byte.

Dovrebbero esserci degli spazi tra ciascuno dei massimi, un minimo. Dovrebbe avere la stessa larghezza di una scatola ma nessuna particella atterrerà lì. Vedi il diagramma seguente:

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

Il programma dovrebbe essere eseguito fino a quando non viene arrestato manualmente.

Regole

  • Un generatore di numeri pseudo casuali (pRNG) va bene.
  • Sono vietate le scappatoie standard .
  • L'input può essere preso in qualsiasi formato ragionevole.
  • È necessario eseguire l'output su STDOUT.
  • Questo è quindi vince la risposta più breve.

Esempio

La seguente GIF è un esempio eseguito per n = 5. L'ho rovesciato rapidamente, quindi le possibilità potrebbero essere leggermente ridotte.

Esempio di doppia fenditura


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

Risposte:


4

Python 2, 207 200 byte

C'è un metodo per questa follia, lo prometto. Segue l'interpretazione della probabilità che ho commentato nel PO.

Modifica: -7 byte attraverso una valutazione pigra intelligente (e la rimozione di alcuni segni)

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 byte

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

Sfortunatamente non posso dimostrarlo su TryItOnline a causa del loop infinito e delle sequenze di escape ANSI che spostano il cursore, ma puoi comunque copiarlo e incollarlo nel tuo terminale!

Versione non modificata:

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
Dai un'occhiata ai consigli per giocare a golf a Bash . Ci sono alcuni frutti facili da appendere bassi da raccogliere qui, ad es. $[ ]Anziché $(( )). Invece di for i in `seq $((($1+1)/2)) -1 1`;do ...;doneprovare for((i=($1+1)/2;i>0;i--));{ ...;}. Invece di [ $(($RANDOM%2)) -eq 1 ]provare ((RANDOM%2)). sector, SSecc. devono essere sostituiti con 1 nome di variabile char.
Trauma digitale

3

Mathematica, 231 byte

(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->" "]])&


ingresso

[5]

produzione

inserisci qui la descrizione dell'immagine


Questo sembra essere non valido, per n = 5 ci dovrebbero essere solo 5 caselle, hai 9
TheLethalCoder

Mi sono reso conto di aver contato come {... 3,2,1,2,3 ...}. Posso risolverlo se non viene accettato
J42161217

2
@TheLethalCoder Fixed! Migliorato! Golfed!
J42161217

Sembra buono, elogiato da me
TheLethalCoder

2

C # (.NET 4.5), 319 254 byte

Risparmiato 65 byte grazie a 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;}}}

Accidenti, è stato un sacco di lavoro, ma funziona in qualche modo.

Dal momento che utilizza Consolefunzioni specifiche e Thread inattivo, purtroppo non funzionerà su TIO.


Compilare a una Action<int>per salvare byte, while(true)-> ( while(1>0)-> for(;;). using C=Console;O using static Console;.
TheLethalCoder

Quell'applicazione può anche essere delegata? Non lo sapevo. Lo aggiornerò tra un secondo.
Ian H.

Programmi / funzioni sono consentiti per impostazione predefinita e le lambda anonime contano come funzioni (anche se le regole su di esse diventano un po 'più profonde quando è necessario chiamarle).
TheLethalCoder

255 bytenamespace 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 Quel codice non funziona: / Fornisce solo molti Variable is not existing in the current contexterrori.
Ian H.

1

Clojure + Quil, 394 byte

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

Beh, certamente non ho vinto, ma questo è stato un buon allenamento per il cervello! Potrei aver scelto un modo eccessivamente rotonda di farlo, ma funziona! Fondamentalmente, come funziona è:

  1. I valori x di ogni colonna vengono calcolati in base a n. Quindi, le "colonne attive" che conterranno i punti vengono filtrate. Le colonne vengono quindi zippate con le possibilità che verranno scelte.

  2. L'animazione ha inizio e ogni frame viene inserito un loop. A partire dal centro, viene provata ogni coppia di colonne. Una volta scelta una coppia di colonne, viene scelta casualmente una colonna della coppia.

  3. Un punto viene disegnato in una posizione casuale all'interno della colonna scelta, il ciclo interno viene chiuso e inizia un nuovo fotogramma.

Utilizza la libreria grafica Quil, che è essenzialmente un wrapper di elaborazione per Clojure.

Nota, il codice golf non produce la stessa animazione mostrata nella GIF. Nel codice golf, lo sfondo è grigio e la finestra e i punti sono più piccoli. Ha lo stesso effetto, non è così carino.

GIF

Vedi il codice non golfato per una spiegazione approfondita:

(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 byte

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

Provalo online! (Non funzionerà ma sai).

Versione completa / formattata:

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