Probabilità di non trarre una parola da un sacco di lettere in Scrabble


27

Supponi di avere una borsa con n tessere, ognuna con una lettera. Ci sono nA tessere A con la lettera 'A', con 'B', e così via, e tessere 'jolly' (abbiamo ). Supponiamo di avere un dizionario con un numero finito di parole. Scegli piastrelle dalla borsa senza sostituzione. Come calcoleresti (o stimerai) la probabilità che tu possa formare zero parole dal dizionario date le tessere selezionate?nBnn=nA+nB++nZ+n*KK

Per coloro che non hanno familiarità con Scrabble (TM), il carattere jolly può essere utilizzato per abbinare qualsiasi lettera. Pertanto, la parola [ BOOT ] potrebbe essere "digitata" con le tessere "B", "*", "O", "T".

Per dare un'idea della portata del problema, K è piccolo, come 7, n è circa 100, e il dizionario contiene circa 100.000 parole di dimensione K o inferiore.

modifica: Per "forma una parola", intendo una parola di lunghezza non maggiore di K . Pertanto, se la parola [ A ] è nel dizionario, quindi disegnando anche una sola "A" dalla borsa, si è "formata una parola". Il problema dei caratteri jolly è radicalmente semplificato se si può presumere che ci siano parole di lunghezza 1 nel dizionario. Se ci sono, qualsiasi estrazione di un carattere jolly può corrispondere automaticamente a una lunghezza di 1 parola, e quindi ci si può concentrare sul caso in cui non ci sono caratteri jolly. Pertanto, la forma più scivolosa del problema non ha parole di 1 lettera nel dizionario.

Inoltre, dovrei dichiarare esplicitamente che l'ordine in cui le lettere sono tratte dalla borsa è irrilevante. Non è necessario disegnare le lettere nell'ordine "corretto" della parola.


Non dovrebbe essere "scegli k tessere senza sostituzione"? Domanda molto interessante.

oops. in effetti dovrebbe.
shabbychef,

Per quanto ricordo Scrabble non consente le parole di una lettera, quindi almeno quella parte del problema è stata risolta;)
nico,

1
@nico buon punto, ma penso che questo sia solo per metà partita. Le parole di 1 lettera o non richiedono di giocare una lettera, oppure permetterebbero di posizionare una singola lettera in qualsiasi punto del tabellone, entrambe chiaramente inaccettabili. Tuttavia, stavo pensando alla mossa di apertura. In effetti, la domanda può essere formulata in modo compatto, per coloro che hanno familiarità con Scrabble, come "qual è la probabilità che il primo giocatore dovrà passare?"
shabbychef,

@nico Grazie per questo chiarimento. Teoricamente un problema simile riguarda i dizionari contenenti tutte le possibili combinazioni di due lettere come parole: in tal caso, ogni mano di 2 o più lettere contiene automaticamente una parola. Il commento di @ shabbychef a metà partita mostra quanto sia irrilevante la domanda originale per la maggior parte di Scrabble, perché a metà partita hai a disposizione una serie di parti di parole (prefissi, suffissi e persino sezioni centrali) oltre alle 7 lettere nella tua mano. Ciò aumenta notevolmente le possibilità di essere in grado di fare una parola.
whuber

Risposte:


14

Questo è un (lungo!) Commento sul bel lavoro che @vqv ha pubblicato in questa discussione. Ha lo scopo di ottenere una risposta definitiva. Ha fatto il duro lavoro di semplificare il dizionario. Non resta che sfruttarlo al massimo. I suoi risultati suggeriscono che una soluzione a forza bruta è fattibile . Dopotutto, incluso un carattere jolly, ci sono al massimo parole che si possono fare con 7 caratteri, e ne sembrano meno di 1/10000 - diciamo, circa un milione - non riesco a includere alcune parole valide. 277=10,460,353,203

Il primo passo è aumentare il dizionario minimo con un carattere jolly "?". 22 delle lettere compaiono in parole di due lettere (tutte tranne c, q, v, z). Aggiungete un jolly a quelle 22 lettere e aggiungetele al dizionario: {a ?, b ?, d ?, ..., y?} Sono ora presenti. Allo stesso modo possiamo ispezionare le parole minime di tre lettere, causando alcune parole aggiuntive apparire nel dizionario. Infine, aggiungiamo "??" al dizionario. Dopo aver rimosso le ripetizioni che ne risultano, contiene 342 parole minime.

Un modo elegante di procedere - uno che utilizza davvero una piccolissima quantità di codifica - è vedere questo problema come algebrico . Una parola, considerata come un insieme di lettere non ordinate, è solo un monomio. Ad esempio, "spats" è il monomiale . Il dizionario è quindi una raccolta di monomi. Sembraun'pS2t

{a2,un'B,un'd,...,ozψ,wXψ,ψ2}

(dove, per evitare confusione, ho scritto per il carattere jolly).ψ

Un rack contiene una parola valida se e solo se quella parola divide il rack.

Un modo più astratto, ma estremamente potente, per dirlo è che il dizionario genera un ideale nell'anello polinomiale R = Z [ a , b , , z , ψ ] e che i rack con parole valide diventano zero nel quoziente ring R / I , mentre i rack senza parole valide rimangono diversi da zero nel quoziente. Se formiamo la somma di tutti i rack in R e la calcoliamo in questo anello di quoziente, allora il numero di rack senza parole è uguale al numero di monomi distinti nel quoziente.ioR=Z[a,b,,z,ψ]R/IR

Inoltre, la somma di tutti i rack in è semplice da esprimere. Sia α = a + b + + z + ψ la somma di tutte le lettere dell'alfabeto. α 7 contiene un monomio per ciascun rack. (Come bonus aggiuntivo, i suoi coefficienti contano il numero di modi in cui ogni rack può essere formato, permettendoci di calcolare la sua probabilità se vogliamo.)Rα=a+b++z+ψα7

Come semplice esempio (per vedere come funziona), supponiamo che (a) non usiamo i caratteri jolly e (b) tutte le lettere da "a" a "x" siano considerate parole. Quindi le uniche possibili cremagliere dalle quali non è possibile formare le parole devono consistere interamente in y e z. Calcoliamo modulo l'ideale generato da { a , b , c , ... , x } un passo alla volta, quindi:α=(a+b+c++x+y+z)7{a,b,c,,x}

α0=1α1=a+b+c++x+y+zy+zmodIα2(y+z)(a+b++y+z)(y+z)2modIα7(y+z)6(a+b++y+z)(y+z)7modI.

Possiamo leggere la possibilità di ottenere un rack senza parole dalla risposta finale, : ciascun coefficiente conta i modi in cui è possibile disegnare il rack corrispondente. Ad esempio, ci sono 21 (su 26 ^ 7 possibili) modi per disegnare 2 y e 5 z perché il coefficiente di yy7+7y6z+21y5z2+35y4z3+35y3z4+21y2z5+7yz6+z7 uguale a 21.y2z5

Dai calcoli elementari, è ovvio che questa è la risposta corretta. Il punto è che questa procedura funziona indipendentemente dal contenuto del dizionario.

Nota come ridurre la potenza del modulo l'ideale in ogni fase riduce il calcolo: questa è la scorciatoia rivelata da questo approccio. (Fine dell'esempio.)

I sistemi di algebra polinomiale implementano questi calcoli . Ad esempio, ecco il codice Mathematica :

alphabet =  a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + 
            p + q + r + s + t + u + v + w + x + y + z + \[Psi];
dictionary = {a^2, a b, a d, a e, ..., w z \[Psi], \[Psi]^2};
next[pp_] := PolynomialMod[pp alphabet, dictionary];
nonwords = Nest[next, 1, 7];
Length[nonwords]

(Il dizionario può essere costruito in modo semplice dal min. Min di @ vqv; ho inserito qui una riga che mostra che è abbastanza corto da essere specificato direttamente se lo desideri.)

L'output - che richiede dieci minuti di calcolo - è 577958. ( NB In una versione precedente di questo messaggio avevo fatto un piccolo errore nella preparazione del dizionario e ottenuto 577940. Ho modificato il testo per riflettere ciò che spero siano ora i risultati corretti!) Poco meno del milione o così mi aspettavo, ma dello stesso ordine di grandezza.

Per calcolare la possibilità di ottenere un tale rack, dobbiamo tenere conto del numero di modi in cui il rack può essere disegnato. Come abbiamo visto nell'esempio, questo equivale al suo coefficiente in . La possibilità di disegnare alcuni di questi rack è la somma di tutti questi coefficienti, facilmente reperibile impostando tutte le lettere uguali a 1:α7

nonwords /. (# -> 1) & /@ (List @@ alphabet)

La risposta equivale a 1066056120, dando una probabilità del 10,1914% di estrarre un rack da cui non è possibile formare una parola valida (se tutte le lettere sono ugualmente probabili).

Quando le probabilità delle lettere variano, basta sostituire ogni lettera con la possibilità di essere disegnata:

tiles = {9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 
         4, 2, 2, 1, 2, 1, 2};
chances = tiles / (Plus @@ tiles);
nonwords /. (Transpose[{List @@ alphabet, chances}] /. {a_, b_} -> a -> b)

L'output è 1,079877553303%, la risposta esatta (anche se usando un modello approssimativo, disegnando con la sostituzione). Guardando indietro, ci sono volute quattro righe per inserire i dati (alfabeto, dizionario e frequenze alfabetiche) e solo tre righe per eseguire il lavoro: descrivere come prendere la potenza successiva di modulo I , prendere la 7a potenza in modo ricorsivo e sostituire la probabilità per le lettere.αI


+1 Unire il lessico e ridimensionarlo al minimo è un'idea intelligente. L'algebra è al di là di me, ma sembra che tu stia calcolando una probabilità multinomiale, piuttosto che ipergeometrica. Quindi la probabilità è di campionare con la sostituzione. Penso che ciò spieghi perché la tua risposta dell'1,08% è molto più grande della mia stima dello 0,4%. C'è un modo per modificare il tuo approccio per gestire il campionamento senza sostituzione?
vqv

2
@vqv Sì. Ora che abbiamo un elenco di circa mezzo milione di rack senza parole, è semplice (modificando le ultime due righe di codice) calcolare la possibilità di ogni rack (senza sostituzione) e ottenere il risultato ipergeometrico. La risposta esatta è 349870667877/80678106432000 = 0,43366% . Con prove N = 100K la tua SE è dello 0,021%, quindi la tua risposta dovrebbe essere compresa tra lo 0,38% e lo 0,49% (IC bilaterale al 99%). Sono così felice che le nostre risposte siano d'accordo!
whuber

@whuber Potresti eseguire il calcolo usando la distribuzione delle tessere Words With Friends (WWF)? La mia stima dello 0,4% si basa sul lessico del WWF e sulla distribuzione delle piastrelle del WWF. Penso che tu stia usando la distribuzione delle tessere Scrabble con il lessico WWF.
vqv

Ops. La risposta esatta in realtà è 349870675899 (avevo 8022 di sconto a causa di un errore nel mio dizionario). Fortunatamente questo non fa alcuna differenza pratica.
whuber

@vqv Non ho familiarità con le varie distribuzioni di piastrelle. Ho copiato il mio direttamente dal tuo codice (e ho usato il tuo dizionario) :-). Se intendi la distribuzione su osxreality.com/2010/01/01/… , ottengo 1,15444% (con sostituzione), 0,43366% (senza sostituzione). Il secondo numero in realtà differisce dalle frequenze di Scrabble all'ottava cifra significativa.
whuber

14

È molto difficile disegnare un rack che non contenga alcuna parola valida in Scrabble e nelle sue varianti. Di seguito è riportato un programma R che ho scritto per stimare la probabilità che il rack a 7 tessere iniziale non contenga una parola valida. Utilizza un approccio monte carlo e il lessico Words With Friends (non sono riuscito a trovare il lessico ufficiale di Scrabble in un formato semplice). Ogni prova consiste nel disegnare un rack di 7 tessere e quindi verificare se il rack contiene una parola valida.

Parole minime

Non è necessario eseguire la scansione dell'intero lessico per verificare se il rack contiene una parola valida. Hai solo bisogno di scansionare un lessico minimo composto da parole minime . Una parola è minima se non contiene altre parole come sottoinsieme. Ad esempio 'em' è una parola minima; 'vuoto' non lo è. Il punto è che se un rack contiene la parola x , deve contenere anche qualsiasi sottoinsieme di x . In altre parole: un rack non contiene parole se non contiene parole minime. Fortunatamente, la maggior parte delle parole nel lessico non sono minime, quindi possono essere eliminate. Puoi anche unire parole equivalenti di permutazione. Sono stato in grado di ridurre il lessico di Words With Friends da 172.820 a 201 parole minime.

I caratteri jolly possono essere facilmente gestiti trattando rack e parole come distribuzioni sulle lettere. Controlliamo se un rack contiene una parola sottraendo una distribuzione dall'altra. Questo ci dà il numero di ogni lettera mancante dal rack. Se la somma di quel numero è il numero di caratteri jolly, la parola è nel rack.

L'unico problema con l'approccio Monte Carlo è che l'evento a cui siamo interessati è molto raro. Quindi dovrebbero essere necessarie molte, molte prove per ottenere una stima con un errore standard abbastanza piccolo. Ho fatto funzionare il mio programma (incollato in basso) con prove e ottenuto una probabilità stimata di 0,004 che la cremagliera iniziale non contiene una parola valida . L'errore standard stimato di tale stima è 0.0002. Il mio Mac Pro ha impiegato solo un paio di minuti, incluso il download del lessico.N=100,000

Sarei interessato a vedere se qualcuno può inventare un algoritmo esatto efficiente. Un approccio ingenuo basato sull'inclusione-esclusione sembra che potrebbe comportare un'esplosione combinatoria.

Inclusione-esclusione

Penso che questa sia una cattiva soluzione, ma qui c'è comunque uno schizzo incompleto. In linea di principio è possibile scrivere un programma per eseguire il calcolo, ma le specifiche sarebbero tortuose.

La probabilità che desideriamo calcolare è L'evento all'interno della probabilità sul lato destro è un'unione di eventi: P ( k -tile rack contiene una parola ) = P ( x M { k -tile rack contiene  x } ) , dove M

P(k-tile rack does not contain a word)=1P(k-tile rack contains a word).
P(k-tile rack contains a word)=P(xM{k-tile rack contains x}),
Mè un lessico minimo. Possiamo espanderlo utilizzando la formula di inclusione-esclusione. Si tratta di considerare tutte le possibili intersezioni degli eventi sopra. Let denota l'insieme potenza di M , ossia l'insieme di tutti i possibili sottoinsiemi di M . Poi P(M)MM
P(k-tile rack contains a word)=P(xM{k-tile rack contains x})=j=1|M|(1)j1SP(M):|S|=jP(xS{k-tile rack contains x})


xS{k-tile rack contains x}
S

Poi

P(xS{k-tile rack contains x})=w=0nP(xS{k-tile rack contains x}|k-tile rack contains w wildcards)×P(k-tile rack contains w wildcards).

2|M|2|M|3.2×1060

Scansione di tutti i possibili rack

k-tile rack fino a quando non si ottiene l'insieme di rack che non contiene parole. Per Scrabble (o Words With Friends) il numero di possibili rack da 7 tessere è in decine di miliardi. Contare il numero di quelli che non contengono una possibile parola dovrebbe essere fattibile con poche decine di righe di codice R. Ma penso che dovresti essere in grado di fare meglio del semplice elenco di tutti i possibili rack. Ad esempio, "aa" è una parola minima. Ciò elimina immediatamente tutti i rack contenenti più di una "a". Puoi ripetere con altre parole. La memoria non dovrebbe essere un problema per i computer moderni. Un rack Scrabble a 7 tessere richiede meno di 7 byte di memoria. Nel peggiore dei casi useremmo alcuni gigabyte per memorizzare tutti i possibili rack, ma non penso neanche che sia una buona idea. Qualcuno potrebbe voler pensare di più a questo.

Programma Monte Carlo R.

# 
#  scrabble.R
#  
#  Created by Vincent Vu on 2011-01-07.
#  Copyright 2011 Vincent Vu. All rights reserved.
# 

# The Words With Friends lexicon
# http://code.google.com/p/dotnetperls-controls/downloads/detail?name=enable1.txt&can=2&q=
url <- 'http://dotnetperls-controls.googlecode.com/files/enable1.txt'
lexicon <- scan(url, what=character())

# Words With Friends
letters <- c(unlist(strsplit('abcdefghijklmnopqrstuvwxyz', NULL)), '?')
tiles <- c(9, 2, 2, 5, 13, 2, 3, 4, 8, 1, 1, 4, 2, 5, 8, 2, 1, 6, 5, 7, 4, 
           2, 2, 1, 2, 1, 2)
names(tiles) <- letters

# Scrabble
# tiles <- c(9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 
#            2, 2, 1, 2, 1, 2)


# Reduce to permutation equivalent words
sort.letters.in.words <- function(x) {
  sapply(lapply(strsplit(x, NULL), sort), paste, collapse='')
}

min.dict <- unique(sort.letters.in.words(lexicon))
min.dict.length <- nchar(min.dict)

# Find all minimal words of length k by elimination
# This is held constant across iterations:
#   All words in min.dict contain no other words of length k or smaller
k <- 1
while(k < max(min.dict.length))
{
  # List all k-letter words in min.dict
  k.letter.words <- min.dict[min.dict.length == k]

  # Find words in min.dict of length > k that contain a k-letter word
  for(w in k.letter.words)
  {
    # Create a regexp pattern
    makepattern <- function(x) {
      paste('.*', paste(unlist(strsplit(x, NULL)), '.*', sep='', collapse=''), 
            sep='')
    }
    p <- paste('.*', 
               paste(unlist(strsplit(w, NULL)), 
                     '.*', sep='', collapse=''), 
               sep='')

    # Eliminate words of length > k that are not minimal
    eliminate <- grepl(p, min.dict) & min.dict.length > k
    min.dict <- min.dict[!eliminate]
    min.dict.length <- min.dict.length[!eliminate]
  }
  k <- k + 1
}

# Converts a word into a letter distribution
letter.dist <- function(w, l=letters) {
  d <- lapply(strsplit(w, NULL), factor, levels=l)
  names(d) <- w
  d <- lapply(d, table)
  return(d)
}

# Sample N racks of k tiles
N <- 1e5
k <- 7
rack <- replicate(N,
                  paste(sample(names(tiles), size=k, prob=tiles), 
                        collapse=''))

contains.word <- function(rack.dist, lex.dist)
{
  # For each word in the lexicon, subtract the rack distribution from the 
  # letter distribution of the word.  Positive results correspond to the 
  # number of each letter that the rack is missing.
  y <- sweep(lex.dist, 1, rack.dist)

  # If the total number of missing letters is smaller than the number of 
  # wildcards in the rack, then the rack contains that word
  any(colSums(pmax(y,0)) <= rack.dist[names(rack.dist) == '?'])
}

# Convert rack and min.dict into letter distributions
min.dict.dist <- letter.dist(min.dict)
min.dict.dist <- do.call(cbind, min.dict.dist)
rack.dist <- letter.dist(rack, l=letters)

# Determine if each rack contains a valid word
x <- sapply(rack.dist, contains.word, lex.dist=min.dict.dist)

message("Estimate (and SE) of probability of no words based on ", 
        N, " trials:")
message(signif(1-mean(x)), " (", signif(sd(x) / sqrt(N)), ")")

Wow ... follow-up molto bello.
Matt Parker,

Sono un po 'sorpreso che sia stato ridotto a 201 parole. Anche se per la prima parola riprodotta, le nostre regole della casa accettano "I" e "A" come parole, il che probabilmente ridurrebbe ulteriormente il numero di parole minime. Speravo di vedere qualcuno espellere l'analisi dell'inclusione-esclusione, che dovrebbe essere piuttosto pelosa ...
Shabbychef,

@shabbychef Non ci sono parole di 1 lettera nel lessico. La maggior parte delle parole minime sono di 2 e 3 lettere. Ecco la distribuzione completa delle parole minime: 2: 73, 3:86, 4:31, 5: 9, 6: 2. Le parole di 6 lettere sono: GLYCYL e SYZYGY.
vqv

@shabbychef Ho aggiornato la mia risposta per includere uno schizzo di un esatto approccio di inclusione-esclusione. È peggio che peloso.
vqv

ottimo lavoro! Adoro che questa domanda, che potrebbe essere posta come una frase (per quelli con sufficiente background), ha messo in evidenza monte carlo, inclusione-esclusione, DAG, ricerca di alberi, algebra polinomiale e che le tue simulazioni siano confermate dal teorico di @ whuber. Saluti!
Shabbychef,

7

1k

La seconda ragione è che MC è davvero fattibile: devi solo farlo bene. Il paragrafo precedente fornisce un indizio: non solo generare parole a caso e cercarle; invece, analizza prima il dizionario e sfrutta la sua struttura.

k!1

kquindi cerca questa "parola" ordinata in un albero costruito dai rappresentanti ordinati delle parole nel dizionario originale. Questo sarà in realtà più piccolo dell'albero originale perché unisce tutti i set di parole che sono equivalenti all'ordinamento, come {stop, post, pot, opts, spot}. In effetti, in un dizionario inglese questa classe di parole non sarebbe mai stata raggiunta comunque perché "così" sarebbe stato trovato per primo. Vediamo questo in azione. Il multiset ordinato è "opst"; la "o" si diramerebbe a tutte le parole che contengono solo le lettere {o, p, ..., z}, la "p" si diramerebbe a tutte le parole che contengono solo {o, p, ..., z} e al massimo una "o", e infine la "s" si ramificherebbe alla foglia "così"! (Ho ipotizzato che nessuno dei plausibili candidati "o", "op", "

È necessaria una modifica per gestire i caratteri jolly: lascerò che i tipi di programmatore tra di voi ci pensino. Non aumenterà la dimensione del dizionario (dovrebbe ridurlo, in effetti); rallenterà leggermente l'attraversamento dell'albero, ma senza modificarlo in alcun modo fondamentale. In qualsiasi dizionario che contiene una parola di una sola lettera, come l'inglese ("a", "i"), non vi è alcuna complicazione: la presenza di un carattere jolly significa che puoi formare una parola! (Questo suggerisce che la domanda originale potrebbe non essere così interessante come sembra.)

Il risultato è che una singola ricerca nel dizionario richiede (a) l'ordinamento a K-letter multiset e (b) attraversando non più di Kbordi di un albero. Il tempo di esecuzione èO(Klog(K)). Se si generano abilmente multiset casuali in ordine ordinato (posso pensare a diversi modi efficienti per farlo), il tempo di esecuzione si riduce aO(K). Moltiplicare questo per il numero di iterazioni per ottenere il tempo di esecuzione totale.

Scommetto che potresti condurre questo studio con un vero set di Scrabble e un milione di iterazioni in pochi secondi.


@whuber L'albero è un'idea ordinata (votazione per quell'idea) ma non richiederebbe molta memoria? Immagino che dipenda da quanto sia diverso il dizionario, ma immagino che un dizionario abbastanza diverso richiederebbe molti alberi Ad esempio, l'albero "b" inizierebbe con la lettera "b" invece di "a" per tutte quelle parole che non avere 'a' in loro. Allo stesso modo, l'albero 'c' inizierebbe con la lettera 'c' per quelle parole che non hanno 'a' e 'b' ma hanno 'c'. Il mio approccio diretto proposto sembra più semplice in quanto richiede un attraversamento di una volta di tutte le parole del dizionario, no?

1
@Srikant: l'albero avrebbe probabilmente bisogno di molta meno RAM della cache per iniziare l'intero dizionario. Sei davvero preoccupato per qualche megabyte di RAM, comunque? A proposito, c'è solo un albero, non molti: sono tutti radicati nella parola vuota. Il tuo approccio, come ho capito, richiede più ricerche nel dizionario (fino a 7!) Su ogni iterazione , rendendolo impraticabile come paure di @shabbychef. Sarebbe utile se potessi elaborare l'algoritmo che hai in mente dove scrivi "vedi se riesci a formare una parola": ciò nasconde molti dettagli importanti!
whuber

@whuber: mi sono reso conto che dopo aver pubblicato il mio commento c'è solo un albero. Reg il mio approccio - Sono d'accordo che la mia proposta di Monte Carlo è sfocata e la tua risposta spiega come si può effettivamente implementare Monte Carlo in questa impostazione. In realtà intendevo dire che l' approccio diretto (vedi la mia risposta) potrebbe in realtà essere più semplice in quanto quell'approccio richiede un'operazione una tantum sul dizionario a differenza di un monte carlo che richiede diverse migliaia di iterazioni sull'albero. Mi chiedo solo i meriti relativi degli approcci.

@Srikant Mi sono trattenuto dal commentare il tuo approccio diretto perché sospetto che ottenga le risposte sbagliate. Non sembra spiegare la struttura del dizionario: vale a dire le relazioni dei sottoinsiemi tra le parole. Ad esempio, la tua formula otterrebbe la risposta corretta di zero per tutti i dizionari che contengono tutte le possibili parole di una lettera?
whuber

@whuber hmmm buon punto. Forse sto rispondendo alla domanda sbagliata!

2

Approccio Monte Carlo

L'approccio rapido e sporco è quello di fare uno studio di Monte Carlo. DisegnareK piastrelle m volte e per ogni sorteggio di K tiles see if you can form a word. Denote the number of times you could form a word by mw. The desired probability would be:

1mwm

Direct Approach

Let the number of words in the dictionary be given by S. Let ts be the number of ways in which we can form the sth word. Let the number of letters needed by the sth word be denoted by ma,mb,...,mz (i.e., the sth word needs ma number of 'a' letters etc). Denote the number of words we can form with all tiles by N.

N=(nk)

and

ts=(nama)(nbmb)...(nzmz)

(Including the impact of wildcard tiles is a bit trickier. I will defer that issue for now.)

Thus, the desired probability is:

1stsN

The quick and dirty approach may not be so quick! The dictionary may contain 100,000 words, and the search for a match of the given tiles could be a coding disaster.
shabbychef

@shabbychef This is something well done to suit spell checkers. See for instance n3labs.com/pdf/lexicon-squeeze.pdf

@shabbychef Reg monte-carlo- if the dictionary is sorted a match should be fairly quick no? In any case, the direct approach that I outlined earlier was flawed. I fixed it. The problem in my earlier solution was that the same word can be formed multiple ways (e.g., 'bat', 'b*t' etc).

1
@shabbychef On further reflection, I agree with you that the monte carlo approach will not work. One issue is that you need to figure out which words you can actually form with the k tiles and the second one is that you can form multiple words with the k tiles. Calculating these combinations from k tiles is probably not that easy.

1
@Srikant Grazie. La tua formula sembra presumere che tu debba usare tutte le k lettere per formare la parola, ma non penso che sia ciò che l'OP sta chiedendo. (Non è così che si gioca Scrabble, comunque.) Con quell'assunto implicito, sei sulla buona strada ma devi modificare l'algoritmo: non devi ripetere il calcolo per le parole nel dizionario che sono permutazioni l'una dell'altra. Ad esempio, non devi sottrarre sia t_ {stop} che t_ {post} nella tua formula. (Questa è una modifica facile da implementare.)
whuber
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.