Simuler un tiroir à chaussettes


16

Contexte

J'ai une collection de "chaussettes de semaine", qui sont sept paires de chaussettes étiquetées par les jours de la semaine. Quand je lave mes chaussettes, elles finissent en tas, et je dois les disposer en paires correctes avant de les mettre dans le placard. Ma stratégie consiste à retirer une chaussette au hasard de la pile et à la mettre dans un tiroir. Chaque fois qu'il y a une paire de chaussettes assortie sur le tiroir, je les attache ensemble et les mets dans le placard. Votre tâche consiste à simuler ce processus aléatoire et à renvoyer le nombre de tirages requis pour trouver la première paire correspondante.

Contribution

Votre entrée est un entier N ≥ 1 . Il représente le "nombre de jours dans une semaine": il y a N paires de chaussettes dans la pile, et chaque paire a une étiquette distincte. Si nécessaire, vous pouvez également prendre une graine PRNG en entrée.

Production

Votre résultat est le nombre de chaussettes que je dois dessiner avant de trouver la première paire correspondante. Par exemple, si les deux premières chaussettes forment déjà une paire correspondante, la sortie est 2.

Bien sûr, la sortie est aléatoire et dépend de l'ordre de dessin. Nous supposons que tous les ordres de dessin sont également probables , de sorte que chaque fois qu'une chaussette est tirée, le choix est uniforme et indépendant de tous les autres choix.

Exemple

Soit N = 3 , pour avoir au total 6 chaussettes, étiquetées AABBCC . Une exécution possible du «protocole de dessin de chaussettes» est la suivante:

       | 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

La première paire correspondante a été trouvée après avoir dessiné le deuxième B , qui était la troisième chaussette à tirer, donc la sortie correcte est 3.

Règles et notation

Vous pouvez écrire un programme complet ou une fonction. Le nombre d'octets le plus bas l'emporte et les failles standard sont interdites. L'entrée et la sortie peuvent être dans n'importe quel format raisonnable, y compris unaire (chaîne de 1s).

Vous pouvez supposer que le RNG intégré à votre langue est parfait. Vous n'avez pas besoin de simuler réellement le protocole de dessin de chaussettes, tant que vos sorties ont la distribution de probabilité correcte.

"Cas de test"

Voici les probabilités approximatives de toutes les sorties pour l'entrée 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

Pour tester votre solution, vous pouvez l'exécuter, disons, 40 000 fois et voir si la distribution de sortie est raisonnablement proche de cela.


25
Real Life, 42 bytes -Draw all socks. End up with an odd number.
AdmBorkBork


Donc n = 8 n'est pas égal à 1-> 7 puis à nouveau 1? soit 4 chaussettes étiquetées 1
Viktor Mellgren

@ViktorMellgren Non, vous auriez 8 étiquettes distinctes.
Zgarb

J'ai un tiroir plein de chaussettes identiques, donc pas besoin de les trier.
JDługosz

Réponses:


9

Gelée , 8 octets

ḤX€Ṛ<RTḢ

Essayez-le en ligne! ou vérifiez la distribution pour N = 7 .

Contexte

Soit n le nombre de paires; il y a 2n chaussettes individuelles.

Pour le premier tirage, il y a 2n chaussettes et 0 d'entre elles donnerait une paire assortie. Par conséquent, la probabilité de réussite est de 0 / 2n = 0 .

Étant donné que le premier tirage n'a pas réussi, il y a 2n - 1 chaussettes sur la pile et 1 d'entre elles entraînerait une paire correspondante. Par conséquent, la probabilité de réussite est de 1 / (2n - 1) .

Si le deuxième tirage n'a pas réussi, il y a 2n - 2 chaussettes sur la pile et 2 d'entre elles donneraient une paire correspondante. Par conséquent, la probabilité de réussite est de 2 / (2n - 2) .

En général, si les k premiers tirages ont échoué, il y a 2n - k chaussettes sur la pile et 2 d'entre elles donneraient une paire correspondante. Par conséquent, la probabilité de réussite est k / (2n - k) .

Enfin, si aucun des n premiers tirages n'a réussi, il y a 2n - k chaussettes sur la pile et toutes aboutiraient à une paire assortie. Par conséquent, la probabilité de réussite est n / (2n - n) = 1 .

Comment ça fonctionne

Ḥ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

Gelée, 8 octets

Rx2ẊĠṪ€Ṃ

Essayez-le en ligne!

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

Pour vérifier, voici une version qui affiche à la fois la sortie souhaitée et le résultat de l'opération "shuffle list" (pour voir dans quel ordre les chaussettes ont été dessinées).


5

Python, 66 octets

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

Dennis a imaginé une manière intelligente de réorganiser les choses en économisant 5 octets.


4

MATL , 16 15 octets

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

Essayez-le en ligne! Ou observez la distribution empirique de 1000 échantillons dans le N = 7 (cela prend un certain temps).

Cela génère directement la variable aléatoire représentant le résultat, en fonction de sa distribution de probabilité. Soit N le nombre de paires de chaussettes, et soit p ( k ) la probabilité que le k- ème tirage soit réussi, à condition que le k -1-ème tirage n'aboutisse pas. Ensuite (voir aussi ici ):

  • p (1) est évidemment 0. Vous ne pouvez pas avoir une paire avec une seule chaussette.
  • p (2) est 1 / (2 * N -1). Au deuxième tirage, il y a une chaussette gagnante qui peut être choisie parmi les 2 * N −1 chaussettes restantes.
  • p (3) est 2 / (2 * N −2). Au troisième tirage, il y a 2 chaussettes gagnantes sur 2 * N −2. Le nombre de chaussettes gagnantes est de 2 car les deux chaussettes que vous avez obtenues après le deuxième tirage étaient différentes.
  • En général, par le même raisonnement, p ( k ) est ( k −1) / (2 * N - k +1)
  • Par la formule ci-dessus, p ( N +1) est 1. Si vous arrivez au N + 1-ème tirage, vous êtes assuré de réussir alors.

Ainsi, le code itère pour un maximum de N +1 tirages. Au k -ième tirage, une variable aléatoire est générée qui est égale à 1 avec la probabilité ( k -1) / (2 * N - k ), ou 0 sinon. Chaque fois que la variable aléatoire est égale à 1 (le tirage a réussi), le processus s'arrête et le courant k est sorti.

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
Toi et moi avons eu la même idée, mais tu connais MATL :)
Program man

3

MATL , 14 13 octets

EZ@G\&=XRafX<

Essayez-le en ligne! Ou observez la distribution empirique de 4000 échantillons dans le cas N = 7 (cela prend un certain temps).

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 octets

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

Explication

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

Vous pouvez enregistrer quatre caractères en les remplaçant f=(n)=>par n=>(ou deux, si vous souhaitez conserver l'affectation, certains la conservent , d' autres la suppriment ).
Gustavo Rodrigues

Belle prise, je l'ai réparé. Bien que, lorsque j'ai lu "Vous pouvez écrire un programme complet ou une fonction" dans les règles, j'ai pensé que c'était une exigence.
kamoroso94

3
Conformément au consensus sur Meta , les fonctions non nommées qui ne sont pas liées à un nom sont acceptables par défaut.
Zgarb

Cela ne devrait-il pas être JavaSock? (oui, boiteux)
gcampbell


2

Python 3, 142 105 104 octets

Grâce à Eʀɪᴋ ᴛʜᴇ Gᴏʟғᴇʀ d' avoir sauvé un octet!

Ma première réponse:

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

Ma nouvelle réponse:

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

Les deux sortent avec un NameErroron s.


2

R, 49

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

Je suis sûr qu'il doit y avoir une meilleure façon de faire cela dans R! J'ai essayé de faire quelque chose de plus intelligent, mais cela n'a pas fonctionné.

Edit: Amélioré par @bouncyball car il ne doit pas être une fonction.


devez-vous utiliser function(N)? l'utilisation N=scan();économiserait 2 octets
bouncyball

1

Python 2, 101 octets

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

0

VBA, 61 octets

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

- modélise la probabilité de changement de correspondance des chaussettes en raison d'un échec antérieur. Au point d'évaluation, K est "chaussettes en main", donc le numéro de tirage est un de plus.


0

Pyth, 14 octets

lhfnT{T._.S*2S

Explication:

       ._        #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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.