Експеримент з подвійною щілиною


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. Я лише швидко збив його, щоб шанси трохи знизилися.

Приклад подвійної щілини


Коментарі не для розширеного обговорення; ця розмова була переміщена до чату .
Мартін Ендер

Відповіді:


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

4

БАШ, 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, що переміщують курсор, але ви все одно можете скопіювати та вставити його у свій термінал!

Немініфікована версія:

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 іменами змінних char.
Цифрова травма

3

Математика, 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

Виглядає добре, голос від мене
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. Значення х кожного стовпця обчислюються виходячи з n. Потім «активні колонки», які будуть містити крапки, відфільтрують. Потім стовпці блискавковуються з можливістю їх вибору.

  2. Анімація запускається, і в кожен кадр вводиться цикл. Починаючи з середини, кожна пара стовпців пробується. Після вибору однієї пари стовпців, один стовпчик з пари вибирається випадковим чином.

  3. Точка малюється у випадковому положенні в обраному стовпчику, внутрішній цикл виходить, і починається новий кадр.

Використовується графічна бібліотека Quil, яка по суті є обгорткою для обробки Clojure.

Зауважте, що код із гольфу не створює тієї ж анімації, як показано на 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);
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.