ダブルスリット実験


16

怠zyな物理学者は、二重スリット実験を実行する仕事を持っています。ただし、それらは怠け者であり、すべての機器をセットアップすることに煩わされることはないため、エフェクトをシミュレートします。彼らはプログラムできないので、いくつかの助けが必要になります。怠laなので、プログラムはできるだけ短くする必要があります。


奇数の正の整数nn >= 1およびn % 2 == 1)を指定して、シミュレーションを実行します。

使い方

空のキャンバスから始めて、各フレームの光の粒子がスリットを通過してキャンバスに着地します。パーティクルは次の機会に最大値に到達します:

n = 1

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

n = 3

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

n = 5

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

たとえばn=5、中央のボックスをチェックすると、50%の確率でその中に落ちます。フレームの終わりに落ちた場合、次の2つに移動しないと、25%の確率でそれらに落ちます。フレームの終わりに落ちた場合、次の2つに移動しなければ、それらに落ちる可能性は12.5%です。それが落ちなければ、それは重要ではありません、それはまだフレームの終わりです。

チャンスを計算する方法については混乱がありました。これは、ほとんどの場合、1になる可能性があると考えている人々によるものです。その考えを心から取り除き、それを少しクリアする必要があります。

  • フレームごとに最大で1つのパーティクルがロードされます。これは、パーティクルがそのフレームにまったく着弾しないことを意味します。
  • 粒子は、印刷可能な任意の文字で表すことができます。
  • パーティクルは、ランダムなチャンスでボックス内のどこにでも着弾します。
  • ボックスの幅は2n-1キャンバスのサイズにする必要があります。そのため、n=5それらは1/9キャンバスの幅のthでなければなりません。
  • ボックスの高さは、キャンバスの高さでなければなりません。
  • 粒子は箱の外に全く着地してはいけません。
  • パーティクルが、問題ではない選択されたスポットに既に着陸している場合、再び着陸することができます。
  • 上記のASCIIボックスは明確にするためのものであり、描画しないでください。
  • 妥当な範囲で、独自のキャンバスサイズを選択できます。たとえば、数ピクセルの高さだけではいけません。また、その上のすべてのボックスに適合することができるはずです。
  • コードがフレーム間でスリープする場合、それをバイトカウントに追加する必要はありません。

それぞれの最大値、最小値の間にギャップがあるはずです。これはボックスと同じ幅にする必要がありますが、パーティクルはそこに着地しません。次の図を参照してください。

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

プログラムは、手動で停止するまで実行する必要があります。

ルール

  • 擬似乱数ジェネレーター(pRNG)は問題ありません。
  • 標準的な抜け穴は禁止されています。
  • 入力は、合理的な形式で行われます。
  • STDOUTに出力する必要があります。
  • これはので、最短の答えが勝ちます。

次のGIFは、の実行例ですn = 5。私はそれをすぐにノックしたので、チャンスはわずかにずれます。

ダブルスリットの例


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
マーティンエンダー

回答:


4

Python 2、207 200バイト

この狂気には方法があります、私は約束します。OPでコメントした確率の解釈に従います。

編集:いくつかの巧妙な遅延評価(およびいくつかの兆候を削除)を通じて-7バイト

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バイト

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

残念ながら、カーソルを移動する無限ループとANSIエスケープシーケンスのため、TryItOnlineでこれを示すことはできませんが、それを端末にコピーアンドペーストできます。

縮小版:

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
bashでのゴルフヒントをご覧ください。ここで収穫できる簡単で簡単な果物がいくつかあります-例えばの$[ ]代わりに$(( ))。代わりにfor i in `seq $((($1+1)/2)) -1 1`;do ...;done、試してくださいfor((i=($1+1)/2;i>0;i--));{ ...;}。代わりに[ $(($RANDOM%2)) -eq 1 ]、試してください((RANDOM%2))sectorSSなどは1文字の変数名に置き換える必要があります。
デジタル外傷

3

Mathematica、231バイト

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


入力

[5]

出力

ここに画像の説明を入力してください


これは無効のようです。n= 5の場合、ボックスは5つだけで、
9〜TheLethalCoder

{... 3,2,1,2,3 ...}のように数えることに気付きました。受け入れられない場合は修正できます
-J42161217

2
@TheLethalCoder修正!改善されました!ゴルフ!
-J42161217

よさそうだ、私から
賛成

2

C#(.NET 4.5)、319 254バイト

TheLethalCoderのおかげで65バイト節約されました!

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

うーん、それは大変な仕事でしたが、どういうわけか機能します。

これはConsole特定の関数とThread Sleepを使用するため、残念ながらTIOでは動作しません。


コンパイルAction<int>バイトを保存するには、while(true)- >(while(1>0)- > for(;;)using C=Console;using static Console;
TheLethalCoder

そのアプリケーションも代理人になることが許可されていますか?知らなかった。すぐに更新します。
イアンH.

プログラム/関数はデフォルトで許可されており、匿名ラムダは関数としてカウントされます(ただし、それらを呼び出す必要がある場合、それらのルールは少し深くなります)。
TheLethalCoder

255バイト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;}}}
-TheLethalCoder

@TheLethalCoderそのコードは機能しません:/たくさんのエラーを返しますVariable is not existing in the current context
イアンH.

1

Clojure + Quil、394バイト

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

まあ、私は確かに勝ちませんでしたが、これは良い脳トレでした!私はこれをやり過ぎた方法を選んだかもしれませんが、うまくいきます!基本的に、その仕組みは次のとおりです。

  1. 各列のx値はに基づいて計算されnます。次に、ドットを含む「アクティブな列」が除外されます。列は、選択される可能性で圧縮されます。

  2. アニメーションが開始され、各フレームでループに入ります。中央から始めて、列の各ペアが試行されます。列のペアが1つ選択されると、そのペアから1つの列がランダムに選択されます。

  3. 選択した列内のランダムな位置にドットが描画され、内側のループが終了し、新しいフレームが始まります。

基本的にClojureの処理ラッパーであるQuilグラフィックライブラリを使用します。

ゴルフのコードは、GIFに表示されるのと同じアニメーションを生成しないことに注意してください。ゴルフのコードでは、背景は灰色で、ウィンドウとドットは小さくなっています。同じ効果がありますが、きれいではありません。

GIF

詳細な説明については、未使用のコードを参照してください。

(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バイト

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

オンラインでお試しください!(動作しませんが、わかりません)。

フル/フォーマット済みバージョン:

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);
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.