Bir çorap çekmecesini simüle et


16

Arka fon

Haftanın günleri ile etiketlenmiş yedi çift çorap olan "hafta içi çorapları" koleksiyonum var. Çoraplarımı yıkadığımda, bir yığınla bitiyorlar ve dolaba koymadan önce onları doğru çiftlere yerleştirmeliyim. Stratejim, bir kerede kazıktan bir rastgele çorap çekmek ve bir çekmeceye koymak. Çekmecede eşleşen bir çift çorap olduğunda, onları birbirine bağlarım ve dolaba koyarım. Göreviniz bu rastgele işlemi simüle etmek ve ilk eşleşen çifti bulmak için gerekli çekiliş sayısını döndürmektir.

Giriş

Girişiniz N ≥ 1 tamsayısıdır . "Bir haftadaki gün sayısını" temsil eder: yığınta N çift ​​çorap vardır ve her çiftin ayrı bir etiketi vardır. Gerekirse, giriş olarak bir PRNG tohumu da alabilirsiniz.

Çıktı

Çıktınız, ilk eşleşen çift bulunmadan önce çizmem gereken çorap sayısıdır. Örneğin, ilk iki çorap zaten eşleşen bir çift oluşturuyorsa, çıktı olur 2.

Tabii ki, çıktı rastgele ve çizim sırasına bağlıdır. Tüm çizim siparişlerinin eşit derecede olası olduğunu varsayıyoruz , böylece bir çorap her çekildiğinde, seçim tek tiptir ve diğer tüm seçimlerden bağımsızdır.

Misal

Let N = 3 biz toplam 6 çorap, etiketli olması böylece, aabbcc . "Çorap çekme protokolünün" olası bir çalışması aşağıdaki gibidir:

       | 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

İlk eşleşen çift, çizilecek üçüncü çorap olan ikinci B'nin çizilmesinden sonra bulundu , böylece doğru çıktı 3.

Kurallar ve puanlama

Tam bir program veya işlev yazabilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklara izin verilmez. Giriş ve çıkış, tekli ( 1s dizeleri ) dahil olmak üzere herhangi bir makul biçimde olabilir .

Dilinizin yerleşik RNG'sinin mükemmel olduğunu varsayabilirsiniz. Çıktılarınız doğru olasılık dağılımına sahip olduğu sürece, çorap çekme protokolünü simüle etmek zorunda değilsiniz.

"Test senaryoları"

N = 7 girişi için tüm çıkışların yaklaşık olasılıkları şunlardır :

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

Çözümünüzü test etmek için, örneğin 40 000 kez çalıştırabilir ve çıktı dağıtımının buna oldukça yakın olup olmadığını görebilirsiniz.


25
Gerçek Hayat, 42 bayt -Draw all socks. End up with an odd number.
AdmBorkBork


Yani n = 8, 1-> 7 ve sonra tekrar 1'e eşit değil mi? 1 etiketli 4 çorap
Viktor Mellgren

@ViktorMellgren Hayır, 8 ayrı etiketiniz olurdu.
Zgarb

Aynı çoraplarla dolu bir çekmecem var, bu yüzden onları sıralamaya gerek yok.
JDługosz

Yanıtlar:


9

Jöle , 8 bayt

ḤX€Ṛ<RTḢ

Çevrimiçi deneyin! veya N = 7 için dağılımı doğrulayın .

Arka fon

N çift ​​sayısı olsun ; orada 2n bireysel çorap.

İlk çekiliş için 2n çorap var ve 0 tanesi eşleşen bir çiftle sonuçlanacak. Bu nedenle, başarı olasılığı 0 / 2n = 0'dır .

İlk çekiliş başarılı olmadığından , kazıkta 2n - 1 çorap var ve 1 tanesi eşleşen bir çiftle sonuçlanacak. Bu nedenle, başarı olasılığı 1 / (2n - 1) 'dir .

Eğer ikinci beraberlik başarılı olmadı vardır 2n - 2 yığınının üzerine çorap ve 2 eşleşen bir çifti neden olacaktır bunlardan. Bu nedenle, başarı olasılığı 2 / (2n - 2) 'dir .

Genel olarak, ilk k çekilemeleri başarısız olsaydı , kazık üzerinde 2n - k çorap var ve bunların 2'si eşleşen bir çiftle sonuçlanacaktır. Bu nedenle, başarı olasılığı k / (2n - k) 'dir .

Son olarak, ilk n çekilişinin hiçbiri başarılı olmazsa , kazık üzerinde 2n - k çorap var ve hepsi eşleşen bir çiftle sonuçlanacaktır. Bu nedenle, başarı olasılığı n / (2n - n) = 1'dir .

Nasıl çalışır

Ḥ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

Jöle, 8 bayt

Rx2ẊĠṪ€Ṃ

Çevrimiçi deneyin!

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

Doğrulamak için, hem istenen çıktıyı hem de "karışık liste" işleminin sonucunu gösteren bir sürüm (hangi sipariş çoraplarının çizildiğini görmek için).


5

Python, 66 bayt

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

Dennis, 5 bayt tasarruf ederek işleri yeniden düzenlemenin akıllıca bir yolunu düşündü.


4

MATL , 16 15 bayt

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

Çevrimiçi deneyin! Ya da N = 7 durumunda 1000 örnek için ampirik dağılımı gözlemleyin (biraz zaman alır).

Bu , olasılık dağılımına bağlı olarak, sonucu temsil eden rasgele değişkeni doğrudan üretir . Let , N çorap çiftlerinin sayısı olabilir ve izin s ( k olasılığını belirtir) k inci çekme gerçeğine durumunu, başarılı K -1 inci çekme başarılı değildi. Sonra (ayrıca buraya bakınız ):

  • p (1) açıkçası 0'dır. Tek çoraplı bir çiftiniz olamaz.
  • p (2) 1 / (2 * N- 1) 'dir. İkinci çekilişte 2 * N −1 kalan çoraptan seçilebilen bir kazanan çorap var .
  • p (3) 2 / (2 * N- 2) 'dir. Üçüncü çekilişte 2 * N −2 üzerinden 2 kazanan çorap var . Kazanan çorap sayısı 2'dir, çünkü ikinci çekilişten sonra aldığınız iki çorap farklıydı.
  • Genel olarak, aynı mantıkla, p ( k ) ( k −1) / (2 * N - k +1)
  • Yukarıdaki formüle göre, p ( N +1) 1'dir. N + 1'inci çekilişe ulaşırsanız başarılı olmanız garanti edilir.

Böylece kod maksimum N +1 çekilişi için yinelenir . En k rastgele değişken olasılık ile 1 (eşit olduğu oluşturulur çizmek-inci k (2 x-1) / N - k başka bir şekilde), ya da 0. Rastgele değişken 1'e eşit olduğunda (çekme başarılı olmuştur) işlem durur ve akım k çıkar .

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
Sen ve ben aynı fikri vardı, ama biliyorsun MATL :)
adam

3

MATL , 14 13 bayt

EZ@G\&=XRafX<

Çevrimiçi deneyin! Veya N = 7 durumunda 4000 örnek için ampirik dağılımı gözlemleyin (biraz zaman alır).

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 bayt

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

açıklama

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

Dört karakter değiştirerek kaydedebilirsiniz f=(n)=>ile n=>(eğer atama tutmak istiyorsanız, veya ikisinin bazı tutmak , bazı kaldır o ).
Gustavo Rodrigues

Güzel yakaladım, düzelttim. Kurallarda "Tam bir program veya işlev yazabilirsiniz" yazısını okuduğumda bunun bir gereklilik olduğunu düşündüm.
kamoroso94

3
Gereğince Meta üzerinde uzlaşma , bir isme bağlı olmayan isimsiz fonksiyonlar varsayılan olarak kabul edilebilir.
Zgarb

Bu JavaSock olmamalı mı? (evet, topal)
gcampbell


2

Python 3, 142 105 104 bayt

Bir bayt kaydettiği için Eʀɪᴋ ᴛʜᴇ Gᴏʟғᴇʀ'ye teşekkürler !

İlk cevabım:

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

Yeni cevabım:

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

Her ikisi de bir NameErroraçık ile çıkar s.


2

R, 49

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

Eminim bunu R'de yapmanın daha iyi bir yolu olmalı! Akıllıca bir şey yapmayı denedim ama işe yaramadı.

Düzenleme: Bir işlev olması gerekmediğinden @bouncyball tarafından geliştirildi.


kullanmak zorunda function(N)mısın kullanarak N=scan();2 bayt tasarruf
bouncyball

1

Python 2, 101 bayt

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

0

VBA, 61 bayt

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

- önceki eşleşme başarısızlığı nedeniyle çorap eşleşmesinin değişen olasılığını modeller. Değerlendirme noktasında, K "eldeki çoraplar" dır, bu nedenle çekiliş sayısı birdir.


0

Pyth, 14 bayt

lhfnT{T._.S*2S

Açıklama:

       ._        #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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.