Эксперимент с двумя щелями

16

У ленивого физика есть задача провести эксперимент с двумя щелями. Тем не менее, они ленивы и не могут быть обеспокоены настройкой всего оборудования самостоятельно, поэтому имитируют эффекты. Хотя они не могут программировать, поэтому им понадобится помощь. Поскольку они ленивы, ваша программа должна быть максимально короткой.


Учитывая нечетное положительное целое число n( n >= 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%. Если он падает в конце кадра, если не перейти к следующим двум, есть вероятность 25% падения в них. Если он падает в конце кадра, если не перейти к следующим двум, есть вероятность падения в 12,5%. Если он не падает, это не имеет значения, это все равно конец кадра.

Существует некоторая путаница в том, как рассчитать шансы, в основном это связано с тем, что люди думают о них как о вероятностях, которые должны составлять в целом 1. Удалите эту идею из своего разума, и она должна немного прояснить ее для вас.

  • На кадр будет приходиться не более одной частицы, это означает, что частица может вообще не приземлиться на этот кадр.
  • Частица может быть представлена ​​любым печатным символом.
  • Частица приземлится в любом месте коробки со случайным шансом.
  • Ширина ящиков должна соответствовать 2n-1размеру холста. Так что n=5они должны быть 1/9шириной холста.
  • Высота ящиков должна быть высотой холста.
  • Частица вообще не должна попадать за пределы коробок.
  • Если частица уже приземлилась в выбранном месте, которое не имеет значения, она может снова приземлиться там.
  • Вышеуказанные поля ascii для ясности не должны быть нарисованы.
  • Вы можете выбрать свой собственный размер холста, если это разумно. Например, он должен иметь высоту не более нескольких пикселей. Это также должно быть в состоянии соответствовать всем коробкам на этом.
  • Если ваш код спит между кадрами, вам не нужно добавлять его в счетчик байтов.

Должны быть промежутки между каждым из максимумов, минимумов. Это должно быть той же ширины, что и коробка, но частицы там не будут приземляться. Смотрите следующую диаграмму:

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

Программа должна работать до тех пор, пока она не будет остановлена ​​вручную.

правила

  • Генератор псевдослучайных чисел (pRNG) в порядке.
  • Стандартные лазейки запрещены.
  • Входные данные могут быть приняты в любом разумном формате.
  • Вы должны вывести на STDOUT.
  • Это поэтому выигрывает самый короткий ответ.

пример

Следующий GIF является примером запуска для n = 5. Я только быстро его подобрал, так что шансы могут быть немного ниже.

Пример с двумя щелями

TheLethalCoder
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Мартин Эндер

Ответы:

4

Python 2, 207 200 байт

У этого безумия есть способ, обещаю. Следует интерпретации вероятности, которую я прокомментировал в ОП.

Изменить: -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
algmyr
источник
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

К сожалению, я не могу продемонстрировать это на TryItOnline из-за бесконечного цикла и управляющих последовательностей ANSI, которые перемещают курсор, но вы все равно можете скопировать и вставить его в свой терминал!

Unminified версия:

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
Проверьте подсказки для игры в гольф в Баше . Здесь вы можете собрать несколько легких, низко висящих фруктов - например, $[ ]вместо $(( )). Вместо того 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)). sector, SSи т. д. должны быть заменены именами переменных в 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]

выход

введите описание изображения здесь

J42161217
источник
Это кажется недействительным, для n = 5 должно быть только 5 блоков, у вас есть 9
TheLethalCoder
Я понял, что считаю как {... 3,2,1,2,3 ...}. Я могу это исправить, если это не будет принято
J42161217
2
@TheLethalCoder Исправлено! Улучшен! Golfed!
J42161217
Выглядит хорошо, голос от меня
TheLethalCoder
2

C # (.NET 4.5), 319 254 байта

Сохранено 65 байт благодаря 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;}}}

Фу, это было много работы, но это работает как-то.

Поскольку для этого используются Consoleспециальные функции и спящий поток, к сожалению, он не будет работать на TIO.

Ян Х.
источник
Скомпилируйте для Action<int>сохранения байтов, while(true)-> ( while(1>0)-> for(;;). using C=Console;Или using static Console;.
TheLethalCoder
Это приложение может быть делегатом, а? Не знал этого. Я обновлю это через секунду.
Ян Х.
Программы / функции разрешены по умолчанию, и анонимные лямбды считаются функциями (хотя правила для них становятся немного глубже, когда вам нужно их вызывать).
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ошибок.
Ян Х.
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. Анимация начинается, и в каждом кадре вводится петля. Начиная с середины, пробуется каждая пара столбцов. Как только одна пара столбцов выбрана, один столбец из пары выбирается случайным образом.

  3. Точка рисуется в произвольной позиции в выбранном столбце, внутренний цикл завершается, и начинается новый кадр.

Использует графическую библиотеку Quil, которая, по сути, является оболочкой обработки для Clojure.

Обратите внимание, что гольф-код не производит ту же анимацию, как показано в GIF. В коде для гольфа фон серый, а окно и точки меньше. Это имеет тот же эффект, но не так красиво.

GIF

Посмотрите код ungolfed для подробного объяснения:

(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
источник
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);
        }
    }
}
TheLethalCoder
источник