Моделюйте шухляду для носок


16

Фон

У мене є колекція «шкарпеток у будній день», які представляють сім пар шкарпеток, позначених по днях тижня. Коли я праю шкарпетки, вони закінчуються в купі, і я повинен розставити їх у потрібні пари, перш ніж покласти їх у шафу. Моя стратегія - одночасно витягнути один випадковий шкарпетку з палі і покласти її на ящик. Всякий раз, коли на ящику є відповідна пара шкарпеток, я зав'язую їх і складаю в шафу. Ваше завдання - імітувати цей випадковий процес і повернути кількість малюнків, необхідних для пошуку першої пари, що відповідає.

Вхідні дані

Ваш вхід - ціле число N ≥ 1 . Він являє собою "кількість днів у тиждень": в купі є N пар пар шкарпеток, і кожна пара має чітку мітку. Якщо потрібно, ви також можете взяти насіння PRNG як вихідний матеріал.

Вихідні дані

Ваш вихід - це кількість шкарпеток, які я повинен намалювати до того, як буде знайдена перша відповідна пара. Наприклад, якщо перші два шкарпетки вже утворюють відповідну пару, вихід є 2.

Звичайно, вихід є випадковим і залежить від порядку нанесення. Ми припускаємо, що всі замовлення на малювання однаково вірогідні , тому кожен раз, коли малюється шкарпетка, вибір є рівномірним та незалежним від усіх інших варіантів.

Приклад

Нехай N = 3 , щоб у нас було 6 шкарпеток із позначкою AABBCC . Можливий запуск "протоколу малювання носка" такий:

       | Pile   | Drawer | Pairs
Begin  | AABBCC | -      | -
Draw B | AABCC  | B      | -
Draw C | AABC   | BC     | -
Draw B | AAC    | C      | BB
Draw A | AC     | AC     | BB
Draw A | C      | C      | AA BB
Draw C | -      | -      | AA BB CC

Перша пара, що відповідає, була знайдена після того, як було намальовано другий B , який був третім носком, який потрібно намалювати, тому правильний вихід є 3.

Правила та оцінка

Ви можете написати повну програму або функцію. Виграє найменший байт, а стандартні лазівки заборонені. Введення та вихід можуть бути у будь-якому розумному форматі, включаючи одинарний (рядок 1s).

Ви можете припустити, що вбудований RNG у вашій мові ідеальний. Вам не потрібно насправді моделювати протокол малювання носка, якщо ваші виходи мають правильний розподіл ймовірностей.

"Тестові справи"

Ось приблизні ймовірності всіх виходів на вхід N = 7 :

Output       2     3     4     5     6     7     8
Probability  0.077 0.154 0.210 0.224 0.186 0.112 0.037

Щоб перевірити своє рішення, ви можете запустити його, скажімо, в 40 000 разів і побачити, чи розподіл вихідних даних досить близький до цього.


25
Справжнє життя, 42 байти -Draw all socks. End up with an odd number.
AdmBorkBork


Отже n = 8 не дорівнює 1-> 7, а потім 1 знову? тобто 4 шкарпетки з позначкою 1
Віктор Мелгрен

@ViktorMellgren Ні, у вас було б 8 різних ярликів.
Згарб

У мене ящик, повний однакових шкарпеток, тому немає потреби розбирати їх.
JDługosz

Відповіді:


9

Желе , 8 байт

ḤX€Ṛ<RTḢ

Спробуйте в Інтернеті! або перевірити розподіл на N = 7 .

Фон

Нехай n - кількість пар; є 2n індивідуальних шкарпеток.

Для першого розіграшу є 2n шкарпеток, і 0 з них призведе до сумісної пари. Тому ймовірність успіху дорівнює 0 / 2n = 0 .

Оскільки перший розіграш виявився невдалим, на ворсі є 2n - 1 шкарпетка, і 1 з них призведе до сумісної пари. Тому ймовірність успіху дорівнює 1 / (2n - 1) .

Якщо другий розіграш виявився невдалим, на ворсі є 2n - 2 шкарпетки, і 2 з них призвели до сумісної пари. Тому ймовірність успіху дорівнює 2 / (2n - 2) .

Загалом, якби перші креслення k були невдалими, на ворсі є 2n - k шкарпетки, і 2 з них призвели до сумісної пари. Тому ймовірність успіху дорівнює k / (2n - k) .

Нарешті, якщо жоден з перших n нічиїх не вдався, на ворсі є шматки 2n - k, і всі вони призвели до сумісної пари. Тому ймовірність успіху дорівнює n / (2n - n) = 1 .

Як це працює

ḤX€Ṛ<RTḢ  Main link. Argument: n

Ḥ         Unhalve; yield 2n.
 X€       Map `random draw' over [1, ..., 2n], pseudo-randomly choosing an integer
          from [1, ..., k] for each k in [1, ..., 2n].
   Ṛ      Reverse the resulting array.
     R    Range; yield [1, ..., n].
    <     Perform vectorized comparison.
          Comparing k with the integer chosen from [1, ..., 2n - (k - 1)] yields 1
          with probability (k - 1) / (2n - (k - 1)), as desired.
          The latter half of elements of the left argument do not have a counter-
          part in the right argument, so they are left untouched and thus truthy.
      T   Truth; yield all indices of non-zero integers.
       Ḣ  Head; extract the first one.

8

Желе, 8 байт

Rx2ẊĠṪ€Ṃ

Спробуйте в Інтернеті!

R    generate [1, 2, ..., n]
x2   duplicate every element (two socks of each pair)
Ẋ    shuffle the list, to represent the order in which socks are drawn
Ġ    group indices by value. this will produce a list of pairs of indices;
       each pair represents the point in time at which each of the corresponding
       socks were drawn
Ṫ€   take the last element of each pair. this returns an array of n integers
       which represent the points in time at which a matching sock was drawn
Ṃ    minimum, find the first point at which a matching sock was drawn

Щоб переконатися, ось версія, яка відображає як потрібний вихід, так і результат операції "перетасувати список" (щоб побачити, які шкарпетки порядку були намальовані).


5

Пітон, 66 байт

from random import*
f=lambda n,k=1:k>randint(1,n*2)or-~f(n-.5,k+1)

Денніс придумав розумний спосіб переставити речі, заощадивши 5 байт.


4

MATL , 16 15 байт

Q:"r@qGEy-/<?@.

Спробуйте в Інтернеті! Або спостерігайте за емпіричним розподілом на 1000 зразків у випадку N = 7 (це потребує певного часу).

Це безпосередньо генерує випадкову змінну, що представляє результат, виходячи з її розподілу ймовірностей. Нехай N буде число пар шкарпеток, і нехай р ( К ) позначає ймовірність того, що K -го Жеребкування пройшло успішно, обумовлено тим , що до -1-й розіграш ні успішним. Потім (див. Також тут ):

  • p (1) очевидно 0. Ви не можете мати пару з одним носком.
  • p (2) дорівнює 1 / (2 * N −1). У другому розіграші є один виграшний носок, який може бути обраний із 2 * N −1 залишилися шкарпеток.
  • p (3) дорівнює 2 / (2 * N −2). У третьому розіграші є 2 виграшні шкарпетки з 2 * N −2. Кількість виграшних шкарпеток - 2, оскільки два шкарпетки, які ви отримали після другого розіграшу, були різними.
  • Загалом, за тими ж міркуваннями p ( k ) є ( k −1) / (2 * N - k +1)
  • За вищенаведеною формулою, p ( N +1) дорівнює 1. Якщо ви потрапите на N + 1-е розіграш, ви гарантовано зможете досягти успіху.

Таким чином, код повторює максимум N +1. На k -му малюнку генерується випадкова величина, яка дорівнює 1 з ймовірністю ( k -1) / (2 * N - k ), або 0 в іншому випадку. Щоразу, коли випадкова величина дорівнює 1 (розіграш був успішним) процес зупиняється і виводиться струм k .

Q:      % Input N implicitly. Generate [1 2 ... N+1] (values of draw index, k)
"       % For each
  r     %   Random variable uniformly distributed on the interval (0,1)
  @q    %   Push iteration index, k-1
  GE    %   Push 2*N
  y     %   Duplicate: push k-1 again
  -     %   Subtract: gives 2*N-k+1
  /     %   Divide: gives (k-1)/(2*N-k+1)
  <     %   Push 1 if random value is less than (k-1)/(2*N-k+1), 0 otherwise
  ?     %   If we got a 1
    @   %     Push k
    .   %     Break loop
        %   End if implicitly
        % End loop implicitly
        % Display implicitly

1
У вас і у мене одна і та ж ідея, але ви знаєте MATL :)
Програмна людина

3

MATL , 14 13 байт

EZ@G\&=XRafX<

Спробуйте в Інтернеті! Або спостерігайте за емпіричним розподілом 4000 зразків у випадку N = 7 (це потребує певного часу).

E      % Input N implicitly. Multiply by 2
Z@     % Random permutation of [1 2 ... 2*N]
G\     % Modulo N: random permutation of [0 0 1 1 ... N-1 N-1]
&=     % Compare all pairs for equality. Gives an N×N matrix
XR     % Upper triangular part excluding the diagonal
a      % True for each column if it contains at least one true entry
f      % Get indices of true values
X<     % Take minimum. Implicitly display

3

JavaScript, 77 73 байт

n=>{p={};for(i=n;i--;p[i]=2);while(--p[n*Math.random()|0])i++;return i+2}

Пояснення

var f = (n) => {
    var index;      // used first to initialize pile, then as counter
    var pile = {};  // sock pile

    // start with index = n
    // check that index > 0, then decrement
    // put 2 socks in pile at index
    for(index = n; index--; pile[index] = 2);
    // index is now -1, reuse for counter

    // pick random sock out of pile and decrement its count
    // continue loop if removed sock was not the last
    while(--pile[n * Math.random() | 0]) {
        index++;    // increment counter
    }
    // loop finishes before incrementing counter when first matching pair is removed
    // add 1 to counter to account for initial value of -1
    // add 1 to counter to account for drawing of first matching pair
    return index + 2;
};

Ви можете зберегти чотири символи, замінивши f=(n)=>на n=>(або два, якщо ви хочете зберегти завдання, деякі зберегти його , а інші видалити ).
Густаво Родрігес

Хороший улов, я це виправив. Хоча, коли я читав у правилах «Ви можете написати повну програму або функцію», я вважав, що це є вимогою.
kamoroso94

3
Відповідно до консенсусу щодо Meta , неназвані функції, які не пов'язані з ім'ям, за замовчуванням прийнятні.
Згарб

Чи не повинен це бути JavaSock? (так, кульгавий)
gcampbell


2

Python 3, 142 105 104 байт

Завдяки Eʀɪᴋ ʀɪᴋ Gᴏʟғᴇʀ за збереження одного байта!

Моя перша відповідь:

import random 
i=[x/2 for x in range(int(2*input()))]
d=[]
a=0
random.shuffle(i)
while 1:
 b=i.pop()
 if b in d:
  print(a)
  s
 d=d+[b]
 a+=1

Моя нова відповідь:

from random import*
i=range(int(input()))*2
shuffle(i)
j=0
for x in i:
 if x in i[:j]:print(1+j)+s
 j+=1

Обидва виходять із NameErrorввімкненим s.


2

R, 49

N=scan();which(duplicated(sample(rep(1:N,2))))[1]

Я впевнений, що повинен бути кращий спосіб зробити це в R! Я спробував зробити щось розумніше, але це не вийшло.

Редагувати: Удосконалено за допомогою @bouncyball, оскільки це не повинно бути функцією.


вам доводиться користуватися function(N)? використання N=scan();врятувало б 2 байти
bouncyball

1

Python 2, 101 байт

from random import*
d=[]
p=range(input())*2
shuffle(p)
while list(set(d))==d:d+=p.pop(),
print len(d)

0

VBA, 61 байт

Function K(D):While 2*D-K>K/Rnd:K=K+1:Wend:K=K+1:End Function

- моделює ймовірність зсуву шкарпетки відповідно до попереднього невдачі. У точці оцінки K - це "шкарпетки в руці", тому число малювання - ще одне.


0

Піт, 14 байт

lhfnT{T._.S*2S

Пояснення:

       ._        #Start with a list of all prefixes of
         .S      #a randomly shuffled
           *2S   #range from 1 to input (implicit), times 2.
  f              #filter this to only include elements where
   nT{T          #element is not equal to deduplicated self (i.e. it has duplicates)
lh               #print the length of the first element of that filtered list
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.