Simula un cassetto calzini


16

sfondo

Ho una collezione di "calze nei giorni feriali", che sono sette paia di calze etichettate dai giorni della settimana. Quando lavo i miei calzini, finiscono in un mucchio e devo sistemarli nelle coppie giuste prima di metterli nell'armadio. La mia strategia è quella di estrarre una calza a caso dalla pila e metterla su un cassetto. Ogni volta che c'è un paio di calzini abbinati sul cassetto, li lego insieme e li metto nell'armadio. Il tuo compito è simulare questo processo casuale e restituire il numero di pareggi richiesti per trovare la prima coppia corrispondente.

Ingresso

Il tuo input è un numero intero N ≥ 1 . Rappresenta il "numero di giorni in una settimana": ci sono N paia di calze nella pila e ogni coppia ha un'etichetta distinta. Se necessario, puoi anche prendere un seme PRNG come input.

Produzione

Il tuo output è il numero di calze che devo disegnare prima che venga trovata la prima coppia corrispondente. Ad esempio, se le prime due calze formano già una coppia corrispondente, l'output è 2.

Naturalmente, l'output è casuale e dipende dall'ordine di disegno. Partiamo dal presupposto che tutti gli ordini di disegno sono ugualmente probabili , quindi ogni volta che viene disegnato un calzino, la scelta è uniforme e indipendente da tutte le altre scelte.

Esempio

Sia N = 3 , in modo da avere 6 calze in totale, etichettato AABBCC . Una possibile esecuzione del "protocollo di disegno del calzino" è la seguente:

       | 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 prima coppia corrispondente è stata trovata dopo aver disegnato la seconda B , che era la terza calza da disegnare, quindi l'output corretto è 3.

Regole e punteggio

È possibile scrivere un programma completo o una funzione. Vince il conteggio di byte più basso e non sono consentite scappatoie standard. L'input e l'output possono essere in qualsiasi formato ragionevole, incluso unario (stringa di 1s).

Puoi presumere che l'RNG integrato nella tua lingua sia perfetto. Non è necessario simulare effettivamente il protocollo di disegno del calzino, purché le uscite abbiano la distribuzione di probabilità corretta.

"Casi test"

Ecco le probabilità approssimative di tutte le uscite per l'ingresso 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

Per testare la tua soluzione, puoi eseguirla per, diciamo, 40.000 volte e vedere se la distribuzione dell'output è ragionevolmente vicina a questa.


25
Vita reale, 42 byte -Draw all socks. End up with an odd number.
AdmBorkBork,


Quindi n = 8 non è uguale a 1-> 7 e quindi di nuovo 1? ovvero 4 calzini etichettati 1
Viktor Mellgren

@ViktorMellgren No, avresti 8 etichette distinte.
Zgarb,

Ho un cassetto pieno di calzini identici, quindi non è necessario smistarli.
JDługosz,

Risposte:


9

Gelatina , 8 byte

ḤX€Ṛ<RTḢ

Provalo online! oppure verifica la distribuzione per N = 7 .

sfondo

Sia n il numero di coppie; ci sono 2n calze individuali.

Per il primo sorteggio, ci sono 2n calzini e 0 di questi porterebbe a una coppia corrispondente. Pertanto, la probabilità di successo è 0 / 2n = 0 .

Dato che il primo pareggio non ha avuto successo, ci sono 2n - 1 calzini sulla pila e 1 di questi si tradurrebbe in una coppia corrispondente. Pertanto, la probabilità di successo è 1 / (2n - 1) .

Se il secondo pareggio non ha avuto successo, ci sono 2n - 2 calzini sulla pila e 2 di questi si tradurrebbe in una coppia corrispondente. Pertanto, la probabilità di successo è 2 / (2n - 2) .

In generale, se i primi k progetti non hanno avuto successo, ci sono 2n - k calzini sulla pila e 2 di questi si tradurrebbe in una coppia corrispondente. Pertanto, la probabilità di successo è k / (2n - k) .

Infine, se nessuno dei primi n estrazioni ha avuto successo, ci sono 2n - k calzini sulla pila e tutti si tradurrebbe in una coppia corrispondente. Pertanto, la probabilità di successo è n / (2n - n) = 1 .

Come funziona

Ḥ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

Gelatina, 8 byte

Rx2ẊĠṪ€Ṃ

Provalo online!

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

Per verificare, ecco una versione che mostra sia l'output desiderato sia il risultato dell'operazione "shuffle list" (per vedere in che ordine sono stati disegnati i calzini).


5

Python, 66 byte

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

Dennis ha escogitato un modo intelligente per riordinare le cose, risparmiando 5 byte.


4

MATL , 16 15 byte

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

Provalo online! Oppure osserva la distribuzione empirica per 1000 campioni nel N caso = 7 (ci vuole un po 'di tempo).

Questo genera direttamente la variabile casuale che rappresenta il risultato, in base alla sua distribuzione di probabilità. Sia N il numero di coppie di calzino e p ( k ) denoti la probabilità che il sorteggio k -esito abbia successo, condizionato al fatto che il sorteggio k -esimo non abbia avuto successo. Quindi (vedi anche qui ):

  • p (1) è ovviamente 0. Non puoi avere una coppia con un singolo calzino.
  • p (2) è 1 / (2 * N −1). Alla seconda estrazione c'è un calzino vincente che può essere scelto tra 2 * N −1 calzini rimanenti.
  • p (3) è 2 / (2 * N −2). Alla terza estrazione ci sono 2 calzini vincenti su 2 * N −2. Il numero di calze vincenti è 2 perché le due calze ottenute dopo la seconda estrazione erano diverse.
  • In generale, con lo stesso ragionamento, p ( k ) è ( k −1) / (2 * N - k +1)
  • Con la formula sopra, p ( N +1) è 1. Se arrivi al sorteggio N + 1 °, allora avrai sicuramente successo.

Quindi il codice scorre per un massimo di N +1. Alla k -esca viene generata una variabile casuale che equivale a 1 con probabilità ( k -1) / (2 * N - k ), o 0 altrimenti. Ogni volta che la variabile casuale è uguale a 1 (il sorteggio ha avuto esito positivo) il processo si interrompe e viene emesso l'attuale 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
Tu ed io abbiamo avuto la stessa idea, ma conosci MATL :)
Programma man

3

MATL , 14 13 byte

EZ@G\&=XRafX<

Provalo online! Oppure osserva la distribuzione empirica per 4000 campioni nel caso N = 7 (ci vuole un po 'di tempo).

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 byte

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

Spiegazione

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

Puoi salvare quattro caratteri sostituendoli f=(n)=>con n=>(o due, se vuoi mantenere il compito, alcuni lo mantengono , altri lo rimuovono ).
Gustavo Rodrigues,

Bella cattura, l'ho risolto. Sebbene, quando ho letto "Puoi scrivere un programma completo o una funzione" nelle regole, ho pensato che fosse un requisito.
kamoroso94

3
Secondo il consenso su Meta , le funzioni senza nome che non sono associate a un nome sono accettabili per impostazione predefinita.
Zgarb,

Non dovrebbe essere JavaSock? (sì, zoppo)
gcampbell


2

Python 3, 142 105 104 byte

Grazie a Eʀɪᴋ ᴛʜᴇ Gᴏʟғᴇʀ per aver salvato un byte!

La mia prima risposta:

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

La mia nuova risposta:

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

Entrambi escono con un NameErroron s.


2

R, 49

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

Sono sicuro che ci deve essere un modo migliore per farlo in R! Ho provato a fare qualcosa di più intelligente, ma non ha funzionato.

Modifica: migliorato da @bouncyball poiché non deve essere una funzione.


devi usare function(N)? usando N=scan();salverebbe 2 byte
bouncyball

1

Python 2, 101 byte

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

0

VBA, 61 byte

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

- modella la probabilità di spostamento della corrispondenza del calzino data la precedente mancata corrispondenza. Nel punto di valutazione, K è "calzini in mano", quindi il numero di pareggio è uno in più.


0

Pyth, 14 byte

lhfnT{T._.S*2S

Spiegazione:

       ._        #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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.