O experimento com fenda dupla

16

Um físico preguiçoso tem o trabalho de realizar o experimento de fenda dupla. No entanto, eles são preguiçosos e não podem se incomodar em montar todo o equipamento e simular os efeitos. Eles não podem programar, portanto, precisarão de ajuda. Como eles são preguiçosos, seu programa deve ser o mais curto possível.


Dado um número inteiro positivo ímpar n( n >= 1e n % 2 == 1), execute a simulação.

Como funciona

Você começará com uma tela vazia e em cada quadro uma única partícula de luz atravessará as fendas e pousará na tela. A partícula aterrará no máximo com uma 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.

Por exemplo, para n=5marcar a caixa do meio, há 50% de chance de cair nela. Se cair no final do quadro, se não passar para os próximos dois, há 25% de chance de cair neles. Se cair no final do quadro, se não passar para os próximos dois, há uma chance de 12,5% de cair nesses. Se não cair, não importa, ainda é o fim do quadro.

Houve alguma confusão sobre como calcular as chances, a maior parte disso se deve ao fato de as pessoas pensarem nelas como probabilidades que devem somar 1. Retire essa ideia da sua mente e ela deve esclarecer um pouco para você.

  • No máximo, uma partícula será concedida por quadro, isso significa que uma partícula pode não pousar nesse quadro.
  • Uma partícula pode ser representada por qualquer caractere imprimível.
  • A partícula pousará em qualquer lugar da caixa com uma chance aleatória.
  • A largura das caixas deve ser 2n-1do tamanho da tela. Portanto, n=5eles devem ter 1/9a largura da tela.
  • A altura das caixas deve ser a altura da tela.
  • A partícula não deve pousar fora das caixas.
  • Se uma partícula já pousou em um local escolhido, não importa, ela pode pousar lá novamente.
  • As caixas ascii acima são para maior clareza, não devem ser desenhadas.
  • Você pode escolher seu próprio tamanho de tela, desde que seja razoável. Por exemplo, não deve ter apenas alguns pixels de altura. Ele também deve ser capaz de encaixar todas as caixas nele.
  • Se o seu código dorme entre os quadros, você não precisa adicioná-lo à sua contagem de bytes.

Deve haver espaços entre cada um dos máximos, um mínimo. Essa deve ter a mesma largura de uma caixa, mas nenhuma partícula cairá lá. Veja o seguinte diagrama:

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

O programa deve ser executado até que seja parado manualmente.

Regras

  • Um gerador de números pseudo-aleatórios (pRNG) é bom.
  • As brechas padrão são proibidas.
  • A entrada pode ser obtida por qualquer formato razoável.
  • Você deve enviar para STDOUT.
  • Isso é então a resposta mais curta vence.

Exemplo

O GIF a seguir é um exemplo de execução n = 5. Eu só bati rápido, então as chances podem ser um pouco menores.

Exemplo de fenda dupla

TheLethalCoder
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Martin Ender

Respostas:

4

Python 2, 207 200 bytes

Existe um método para essa loucura, prometo. Segue a interpretação de probabilidade que comentei no OP.

Editar: -7 bytes através de uma avaliação preguiçosa inteligente (e remover alguns sinais)

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
fonte
4

BASH, 396 - 11 = 385 bytes

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

Infelizmente, não posso demonstrar isso no TryItOnline devido às seqüências intermináveis ​​de escape de loop e ANSI que movem o cursor, mas você ainda pode copiar e colar no seu terminal!

Versão não minificada:

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
fonte
1
Confira as dicas para jogar golfe no bash . Existem algumas frutas fáceis e fáceis de colher para você colher aqui - por exemplo, em $[ ]vez de $(( )). Em vez de for i in `seq $((($1+1)/2)) -1 1`;do ...;done, tente for((i=($1+1)/2;i>0;i--));{ ...;}. Em vez de [ $(($RANDOM%2)) -eq 1 ], tente ((RANDOM%2)). sector, SSetc deve ser substituído por 1 nome de variável de caractere.
Digital Trauma
3

Mathematica, 231 bytes

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


entrada

[5]

resultado

insira a descrição da imagem aqui

J42161217
fonte
Parece ser inválido, pois n = 5 deve haver apenas 5 caixas, você tem 9
TheLethalCoder 2/17/17
Eu percebi que eu contado como {... 3,2,1,2,3 ...} eu posso corrigi-lo se ele não é aceito.
J42161217
2
@TheLethalCoder Fixed! Melhorado! Golfed!
J42161217
Parece bom, upvote de mim
TheLethalCoder
2

C # (.NET 4.5), 319254 bytes

Economizou 65 bytes graças ao 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;}}}

Ufa, isso foi muito trabalhoso, mas funciona de alguma forma.

Como isso usa Consolefunções específicas e o thread em suspensão, infelizmente não funcionará no TIO.

Ian H.
fonte
Compilar a um Action<int>para salvar bytes, while(true)-> ( while(1>0)-> for(;;). using C=Console;Ou using static Console;.
TheLethalCoder
Esse aplicativo também pode ser um delegado? Não sabia disso. Vou atualizá-lo em um segundo.
Ian H.
Programas / funções são permitidos por padrão e lambdas anônimas contam como funções (embora as regras neles se aprofundem um pouco quando você precisar chamá-las).
TheLethalCoder
255 bytesnamespace 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 Esse código não funciona: / Apenas fornece muitos Variable is not existing in the current contexterros.
21430 Ian
1

Clojure + Quil, 394 bytes

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

Bem, eu certamente não ganhei, mas este foi um bom treino para o cérebro! Eu posso ter escolhido uma maneira excessivamente indireta de fazer isso, mas funciona! Basicamente, como funciona é:

  1. Os valores x de cada coluna são calculados com base em n . Em seguida, as "colunas ativas" que conterão os pontos são filtradas. As colunas são compactadas com as possibilidades de serem escolhidas.

  2. A animação é iniciada e, a cada quadro, um loop é inserido. A partir do meio, cada par de colunas é tentado. Depois que um par de colunas é escolhido, uma coluna do par é escolhida aleatoriamente.

  3. Um ponto é desenhado em uma posição aleatória dentro da coluna escolhida, o loop interno sai e um novo quadro é iniciado.

Usa a biblioteca de gráficos Quil, que é essencialmente um wrapper de Processamento para Clojure.

Observe que o código golfado não produz a mesma animação mostrada no GIF. No código do golfe, o fundo é cinza e a janela e os pontos são menores. Tem o mesmo efeito, não é tão bonito.

GIF

Veja o código não destruído para uma explicação detalhada:

(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)))))))
Carcinigenicado
fonte
0

C #, 238 bytes

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

Experimente online!(Não vai funcionar, mas você sabe).

Versão completa / formatada:

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
fonte