Eksperyment z podwójną szczeliną

16

Leniwy fizyk ma za zadanie przeprowadzić eksperyment podwójnej szczeliny. Są jednak leniwi i nie można sobie pozwolić na samodzielne konfigurowanie całego sprzętu, dlatego też będą symulować efekty. Nie mogą jednak programować, więc będą potrzebować pomocy. Ponieważ są leniwi, twój program powinien być jak najkrótszy.


Biorąc pod uwagę nieparzystą liczbę całkowitą dodatnią n( n >= 1i n % 2 == 1), wykonaj symulację.

Jak to działa

Zaczniesz od pustego płótna, a każda klatka pojedynczej cząsteczki światła przejdzie przez szczeliny i wyląduje na płótnie. Cząstka wyląduje na maksimach z szansą:

n = 1:

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

n = 3:

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

n = 5:

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

itp.

Na przykład, ponieważ n=5zaznaczamy środkowe pole, istnieje 50% szansy na upadek. Jeśli spadnie na koniec kadru, jeśli nie przejdzie do następnych dwóch, istnieje 25% szansy na upadek. Jeśli spadnie na koniec kadru, jeśli nie przejdzie do następnych dwóch, istnieje 12,5% szansy na upadek. Jeśli nie spadnie, nie ma znaczenia, to wciąż koniec kadru.

Pojawiło się pewne zamieszanie dotyczące sposobu obliczania szans, większość z nich wynika z tego, że ludzie myślą o nich jako o prawdopodobieństwach, które powinny się sumować do 1. Usuń ten pomysł z twojego umysłu i powinien on trochę ci wyjaśnić.

  • Co najwyżej jedna cząstka będzie ładować na ramkę, co oznacza, że ​​cząstka może wcale nie wylądować na tej ramce.
  • Cząstka może być reprezentowana przez dowolny znak do wydrukowania.
  • Cząstka wyląduje w dowolnym miejscu pudełka z losową szansą.
  • Szerokość skrzynek powinna być 2n-1wielkością płótna. Dlatego n=5powinny być one 1/9szerokości płótna.
  • Wysokość skrzynek powinna odpowiadać wysokości płótna.
  • Cząstka nie powinna w ogóle wylądować poza pudełkami.
  • Jeśli cząstka już wylądowała w wybranym miejscu, co nie ma znaczenia, może tam ponownie wylądować.
  • Powyższe pola ascii służą przejrzystości, nie należy ich rysować.
  • Możesz wybrać własny rozmiar płótna, o ile jest to uzasadnione. Na przykład nie może mieć tylko kilku pikseli wysokości. Powinien też być w stanie zmieścić wszystkie znajdujące się na nim pudełka.
  • Jeśli twój kod śpi między ramkami, nie musisz dodawać go do swojej liczby bajtów.

Pomiędzy każdą z maksimów powinny być luki, minima. Powinna mieć taką samą szerokość jak pudełko, ale żadne cząstki tam nie wylądują. Zobacz poniższy schemat:

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

Program powinien działać, dopóki nie zostanie zatrzymany ręcznie.

Zasady

  • Generator liczb pseudolosowych (pRNG) jest w porządku.
  • Standardowe luki są zabronione.
  • Dane wejściowe mogą być pobierane w dowolnym rozsądnym formacie.
  • Powinieneś wyprowadzać dane do STDOUT.
  • To jest więc wygrywa najkrótsza odpowiedź.

Przykład

Poniższy plik GIF jest przykładem uruchomienia dla n = 5. Podrzuciłem go tylko szybko, więc szanse mogą być nieznaczne.

Przykład podwójnej szczeliny

TheLethalCoder
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Martin Ender

Odpowiedzi:

4

Python 2, 207 200 bajtów

Obiecuję, że istnieje metoda na to szaleństwo. Podąża za interpretacją prawdopodobieństwa, którą skomentowałem w PO.

Edycja: -7 bajtów poprzez sprytną leniwą ocenę (i usunięcie niektórych znaków)

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
algmyr
źródło
4

BASH, 396–11 = 385 bajtów

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

Niestety nie mogę tego zademonstrować na TryItOnline z powodu niekończących się sekwencji ucieczki pętli i ANSI, które poruszają kursorem, ale nadal możesz skopiować i wkleić go do swojego terminalu!

Wersja nieuprawniona:

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
Andrew Dunai
źródło
1
Sprawdź wskazówki dotyczące gry w golfa w bash . Można tu zebrać kilka łatwych, nisko wiszących owoców - np. $[ ]Zamiast $(( )). Zamiast tego for i in `seq $((($1+1)/2)) -1 1`;do ...;donespróbuj for((i=($1+1)/2;i>0;i--));{ ...;}. Zamiast tego [ $(($RANDOM%2)) -eq 1 ]spróbuj ((RANDOM%2)). sector, SSitp. należy zastąpić 1 nazwą zmiennej char.
Cyfrowa trauma
3

Mathematica, 231 bajtów

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


Wejście

[5]

wynik

wprowadź opis zdjęcia tutaj

J42161217
źródło
To wydaje się być nieprawidłowe, dla n = 5 powinno być tylko 5 pól, masz 9
TheLethalCoder
Uświadomiłem sobie, że liczyłem jak {... 3,2,1,2,3 ...}. Mogę to naprawić, jeśli nie zostanie zaakceptowane
J42161217,
2
@TheLethalCoder Naprawiono! Ulepszony! Grał w golfa!
J42161217,
Wygląda dobrze, głosuj ode mnie
TheLethalCoder
2

C # (.NET 4.5), 319 254 bajtów

Zaoszczędź 65 bajtów dzięki 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;}}}

Uff, to było dużo pracy, ale jakoś działa.

Ponieważ wykorzystuje to Consoleokreślone funkcje i tryb uśpienia wątku, niestety nie będzie działać na TIO.

Ian H.
źródło
Skompiluj do, Action<int>aby zapisać bajty, while(true)-> ( while(1>0)-> for(;;). using C=Console;Lub using static Console;.
TheLethalCoder
Ta aplikacja może być również delegatem? Nie wiedziałem tego. Zaktualizuję to za chwilę.
Ian H.
Programy / funkcje są domyślnie dozwolone, a anonimowe lambdy liczą się jako funkcje (chociaż reguły na nich są nieco głębsze, gdy trzeba je wywołać).
TheLethalCoder
255 bajtównamespace 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 Ten kod nie działa: / Po prostu daje dużo Variable is not existing in the current contextbłędów.
Ian H.
1

Clojure + Quil, 394 bajty

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

Cóż, na pewno nie wygrałem, ale to był dobry trening mózgu! Być może wybrałem zbyt rondo, ale to działa! Zasadniczo, jak to działa:

  1. Wartości x każdej kolumny są obliczane na podstawie n. Następnie „aktywne kolumny”, które będą zawierać kropki, są odfiltrowywane. Kolumny są następnie spakowane z możliwością wybrania.

  2. Rozpocznie się animacja i do każdej klatki zostanie wprowadzona pętla. Zaczynając od środka, wypróbowywana jest każda para kolumn. Po wybraniu jednej pary kolumn losowo wybierana jest jedna kolumna z pary.

  3. Kropka jest rysowana w losowej pozycji w wybranej kolumnie, wewnętrzna pętla wychodzi i rozpoczyna się nowa klatka.

Korzysta z biblioteki graficznej Quil, która jest zasadniczo opakowaniem przetwarzania dla Clojure.

Uwaga: kod w golfa nie generuje takiej samej animacji, jak pokazano w pliku GIF. W kodzie golfowym tło jest szare, a okno i kropki są mniejsze. Ma ten sam efekt, po prostu nie jest tak ładny.

GIF

Zobacz objaśniony kod, aby uzyskać szczegółowe wyjaśnienie:

(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)))))))
Carcigenicate
źródło
0

C #, 238 bajtów

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

Wypróbuj online!(To nie zadziała, ale wiesz).

Wersja pełna / sformatowana:

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);
        }
    }
}
TheLethalCoder
źródło