27 votos

La probabilidad de no sacar una palabra de una bolsa de cartas en el Scrabble

Supongamos que usted tenía una bolsa con $n$ azulejos, cada uno con una carta. Hay $n_A$ azulejos con la letra 'A', $n_B$ con 'B', y así sucesivamente, y $n_*$ 'comodín' azulejos (tenemos $n = n_A + n_B + \ldots + n_Z + n_*$). Supongamos que tienes un diccionario con un número finito de palabras. Usted escoge $k$ azulejos de la bolsa sin reemplazo. ¿Cómo calcular (o estimar) la probabilidad de que usted puede formar cero palabras del diccionario, dada la $k$ azulejos seleccionado?

Para aquellos no familiarizados con el Scrabble (TM), el carácter comodín puede ser utilizado para combinar con cualquier carta. Así, la palabra [INICIO] podría ser 'escribe' con los azulejos 'B', '*', 'S', 'T'.

Para dar una idea de la magnitud del problema, $k$ es bajita, como 7, $n$ es de alrededor de 100, y el diccionario contiene cerca de 100.000 palabras de tamaño $k$ o más pequeños.

edit: Por la forma de "una palabra", me refiero a una palabra de longitud no mayor que $k$. Por lo tanto, si la palabra [Un] está en el diccionario, luego por el dibujo ni una sola 'A' de la bolsa, uno "se ha formado una palabra'. El problema de los comodines se simplifica si se puede suponer que hay palabras de longitud 1 en el diccionario. Por si hay, cualquier sorteo de un comodín automáticamente puede coincidir con una longitud de 1 palabra, y por eso uno se puede concentrar en el caso donde no hay comodines. Por lo tanto el más resbaladizo forma de que el problema no tiene 1-letra de las palabras en el diccionario.

También, debo indicar explícitamente que el orden en el que las letras son procedentes de la bolsa es inmaterial. Uno no tiene que dibujar las letras en "corregir" el orden de la palabra.

8voto

guillermooo Puntos 2711

Es muy difícil sacar un bastidor que no contiene ninguna palabra válida en Scrabble y sus variantes. A continuación es un programa R escribí para la estimación de la la probabilidad de que la inicial de 7 de azulejos de rack no contiene una palabra válida. Es utiliza un método de monte carlo y de las Palabras Con los Amigos léxico (I no se pudo encontrar el oficial de Scrabble léxico en un formato sencillo). Cada ensayo consiste en dibujar un 7-el azulejo de rack, y, a continuación, comprobar si el rack contiene un válido palabra.

Un mínimo de palabras

Usted no tiene que escanear todo el léxico para comprobar si el rack contiene un válido palabra. Usted sólo tiene que escanear un mínimo de léxico que consta de un mínimo de palabras. Una palabra es mínima si contiene ninguna otra palabra como un subconjunto. Por ejemplo 'em' es una mínima palabra; "vacío" no es. El punto de esto es que si un rack contiene la palabra x , entonces también debe contener cualquier subconjunto de x. En en otras palabras: un bastidor no contiene palabras iff no contiene un mínimo de palabras. Por suerte, la mayoría de las palabras en el léxico, no mínimos, por lo que puede ser eliminado. También se puede combinar permutación palabras equivalentes. Yo era capaz de reducir la Palabras Con Amigos léxico de 172,820 a 201 mínimo de palabras.

Los comodines pueden ser fácilmente manejado por el tratamiento de los bastidores y las palabras como las distribuciones de sobre las letras. Debemos comprobar si un rack contiene una palabra restando una la distribución de los otros. Esto nos da el número de cada letra que falta desde el rack. Si la suma de estos números es de $\leq$ el número de comodines, a continuación, la palabra está en el estante.

El único problema con el método de monte carlo es que el evento que estamos interesados, es muy raro. Por lo que debe tomar muchas, muchas pruebas para conseguir un estimar con bastante pequeño error estándar. Corrí mi programa (se pega en la parte inferior) con $N=100.000$ ensayos y obtuvo un estimado de la probabilidad de 0.004 que el inicial rack no contiene una palabra válida. El estimado error estándar de la estimación es 0.0002. Sólo tardó un par de minutos para que se ejecute en mi Mac Pro, incluyendo la descarga del léxico.

Yo estaría interesado en ver si alguien puede subir con una eficiente exacta el algoritmo. Ingenua de un enfoque basado en la inclusión-exclusión parece que podría implican una explosión combinatoria.

Inclusión-exclusión

Creo que esta es una mala solución, pero aquí es incompleta croquis de todos modos. En principio, usted puede escribir un programa para hacer el cálculo, pero la especificación sería tortuoso.

La probabilidad de que deseamos calcular es $$ P(k\text{-azulejo rack no contiene una palabra}) = 1 - P(k\text{-azulejo rack contiene una palabra}) . $$ El evento dentro de la probabilidad en el lado derecho de la unión de sucesos: $$ P(k\text{-azulejo rack contiene una palabra}) = P\left(\cup_{x \in M} \{ k\text{-azulejo rack contiene }x \} \right), $$ donde $M$ es un mínimo de léxico. Podemos ampliar mediante la inclusión-exclusión de la fórmula. Implica considerar todas las posibles intersecciones de los eventos anteriores. Deje que $\mathcal{P}(M)$ denotar el poder establecido de $M$, es decir, el conjunto de todos los posibles subconjuntos de $M$. Entonces $$ \begin{align} &P(k\text{-azulejo rack contiene una palabra}) \\ &= P\left(\cup_{x \in M} \{ k\text{-azulejo rack contiene }x \} \right) \\ &= \sum_{j=1}^{|M|} (-1)^{j-1} \sum_{S \in \mathcal{P}(M) : |S| = j} P\left( \carpeta cap_{x \in S} \{ k\text{-azulejo rack contiene }x \} \right) \end{align} $$

Lo último que hay que especificar es la forma de calcular la probabilidad en la última línea de arriba. Implica una hipergeométrica multivariante.
$$\carpeta cap_{x \in S} \{ k\text{-azulejo rack contiene }x \}$$ es el caso de que el rack contiene cada palabra en $S$. Este es un dolor de tratar debido a los comodines. Vamos a tener que considere, por el condicionamiento, cada uno de los siguientes casos: la cremallera no contiene los comodines, el rack contiene 1 comodín, el rack contiene 2 comodines, ...

Entonces $$ \begin{align} Y P\left( \carpeta cap_{x \in S} \{ k\text{-azulejo rack contiene }x \} \right) \\ &= \sum_{w=0}^{n_{*}} P\left( \carpeta cap_{x \in S} \{ k\text{-azulejo rack contiene }x \} | k\text{-azulejo rack contiene } w \text{ comodines} \right) \\ &\quad \times P(k\text{-azulejo rack contiene } w \text{ comodines}) . \end{align} $$

Voy a dejar aquí, porque las expansiones son tortuosos para escribir y no en todos los esclarecedor. Es más fácil escribir un programa de ordenador para hacerlo. Pero por ahora usted debe ver que la inclusión-exclusión enfoque es intratable. Es consiste en $2^{|M|}$ términos, cada uno de los cuales es también muy complicado. Para el el léxico de la que yo consideraba por encima de los $2^{|M|} \approx 3.2 \times 10^{60}$.

El escaneo de todos los posibles bastidores

Creo que este es computacionalmente más fácil, porque hay menos posible bastidores de posibles subconjuntos de un mínimo de palabras. Paso a paso vamos a reducir el conjunto de posibles $k$-azulejo bastidores hasta que el conjunto de racks que contienen no palabras. Para Scrabble (o Palabras Con los Amigos) el número de posibles 7-azulejo bastidores está en las decenas de miles de millones. Contando el número de aquellos que no contienen una palabra posible debe ser factible con una docena de líneas de código R. Pero Yo creo que usted debería ser capaz de hacerlo mejor que sólo la enumeración de todos los posibles bastidores. Por ejemplo, 'aa' es una mínima palabra. Que elimina de forma inmediata todos los los racks que contienen más de una 'a'. Usted puede repetir con otras palabras. La memoria no debería ser un problema para las computadoras modernas. 7-el azulejo de Scrabble rack requiere menos de 7 bytes de almacenamiento. En el peor de los íbamos a usar un par de gigabytes para almacenar todos los posibles bastidores, pero no creo que sea una buena idea. Alguien puede querer pensar más en esto.

Monte Carlo programa 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)), ")")

3voto

jldugger Puntos 7490

Esta es una (!) comentarios sobre el buen trabajo de @vqv ha publicado en este hilo. Se persigue el objetivo de obtener una respuesta definitiva. Él ha hecho el trabajo duro de simplificar el diccionario. Todo lo que queda es para explotarlo al máximo. Sus resultados sugieren que un ataque de fuerza bruta solución es factible. Después de todo, incluyendo un comodín que existen en la mayoría de los $27^7 = 10,460,353,203$ palabras que uno puede hacer con 7 caracteres, y parece que en menos de 1/10000 de ellos-por ejemplo, alrededor de un millón--no incluyen algunos de word válido.

El primer paso es aumentar el mínimo diccionario con un carácter comodín "?". 22 de las cartas que aparecen en palabras de dos letras (c, q, v, z). Lindan con un comodín a los 22 letras y agregar al diccionario: {?, b?, d?, ..., y?} ahora están en. Del mismo modo podemos inspeccionar el mínimo de palabras de tres letras, causando algunas palabras adicionales a aparecer en el diccionario. Por último, añadimos "??" para el diccionario. Después de la eliminación de repeticiones que el resultado, que contiene 342 mínimo de palabras.

Una elegante manera de proceder, que utiliza una cantidad muy pequeña de codificación de hecho, es ver este problema como una expresión algebraica uno. Una palabra, considerado como un desordenado conjunto de letras, es sólo un monomio. Por ejemplo, "polainas" es el monomio $a p s^2 t$. El diccionario, por tanto, es una colección de monomials. Parece

$$\{a^2 a, b, d, ..., o z \psi, w x \psi \psi^2\}$$

(donde, para evitar confusiones, he escrito $\psi$ para el carácter comodín).

Un rack contiene una palabra válida si y sólo si esa palabra se divide el rack.

Una más abstracto, pero muy poderoso, la manera de decir esto es que el diccionario se genera un ideal $I$ en el polinomio anillo de $R = \mathbb{Z}[a, b, \ldots, z, \psi]$ y que los bastidores con palabras válidas convierte en cero en el cociente del anillo $R/I$, mientras que los bastidores sin palabras válidas siendo distinto de cero en el cociente. Si se forma la suma de todos los bastidores en $R$ y se calcula en este cociente del anillo, entonces el número de bastidores sin palabras es igual al número de los distintos monomials en el cociente.

Además, la suma de todos los bastidores en $R$ es fácil de expresar. Deje que $\alpha = a + b + \cdots + z + \psi$ ser la suma de todas las letras del alfabeto. $\alpha^7$ contiene un monomio por cada rack. (Como un bono adicional, sus coeficientes de contar el número de maneras en las que cada estante puede ser formado, lo que nos permite calcular la probabilidad de que si nos gusta.)

Como un simple ejemplo (para ver cómo funciona esto), supongamos que (a) no usar caracteres comodín y (b) todas las letras de la "a" a la "x" se consideran palabras. Entonces la única posible bastidores de que las palabras no pueden ser formados debe consistir enteramente de y y z. Calculamos $\alpha=(a+b+c+\cdots+x+y+z)^7$ modulo el ideal generado por $\{a,b,c, \ldots, x\}$ un paso a la vez, por lo tanto:

$$\eqalign{ \alpha^0 y= 1 \cr \alpha^1 &= a+b+c+\cdots+x+y+z \equiv y+z \mod I \cr \alpha^2 &\equiv (y+z)(a+b+\cdots+y+z) \equiv (y+z)^2 \mod I \cr \cdots &\cr \alpha^7 &\equiv (y+z)^6(a+b+\cdots+y+z) \equiv (y+z)^7 \mod I \text{.} }$$

Podemos leer en la posibilidad de obtener un no-palabra bastidor de la respuesta final, $y^7 + 7 y^6 z + 21 y^5 z^2 + 35 y^4 z^3 + 35 s^3 z^4 + 21 y^2 z^5 + 7 y z^6 + z^7$: cada coeficiente cuenta las formas en que la correspondiente bastidor puede ser dibujado. Por ejemplo, hay 21 (de 26^7 posibles) formas para dibujar 2 y y 5 z debido a que el coeficiente de $y^2 z^5$ es igual a 21.

Desde la primaria los cálculos, es obvio que esta es la respuesta correcta. El punto es que este procedimiento funciona independientemente de los contenidos del diccionario.

Observe cómo la reducción de la potencia del modulo el ideal que en cada etapa se reduce el cálculo: es el acceso directo revelada por este enfoque. (Final del ejemplo.)

Polinomio de álgebra sistemas de aplicación de estos cálculos. Por ejemplo, aquí se Mathematica código:

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]

(El diccionario puede ser construido en una forma sencilla de @vqv min.dict; me ponga una línea aquí mostrando que es lo suficientemente corto como para ser especificado directamente si así lo desea).

El resultado-que lleva a los diez minutos de computación--es 577958. (NB En una versión anterior de este mensaje, yo había hecho un pequeño error en la preparación del diccionario y obtuvo 577940. He modificado el texto para reflejar lo que espero que ahora son los resultados correctos!) Un poco menos que los millones o así me lo esperaba, pero del mismo orden de magnitud.

Para calcular la probabilidad de obtener un rack, tenemos que tener en cuenta el número de maneras en las que el bastidor puede ser dibujado. Como vimos en el ejemplo, esto es igual a su coeficiente en $\alpha^7$. La probabilidad de extraer algunas tales rack es la suma de todos estos coeficientes, se encuentran fácilmente por la configuración de todas las cartas igual a 1:

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

La respuesta es igual a 1066056120, dando una oportunidad de 10.1914% de dibujo de un bastidor de que no hay una palabra puede ser formado (si todas las letras son igualmente probables).

Cuando las probabilidades de las letras varían, basta con sustituir cada letra con su posibilidad de ser dibujada:

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)

La salida es 1.079877553303%, la exacta respuesta (aunque usando un modelo aproximado, dibujo con reemplazo). Mirando hacia atrás, tomó cuatro líneas para introducir los datos (alfabeto, diccionario, y el alfabeto de frecuencias) y sólo tres líneas para hacer el trabajo: describir cómo tomar la siguiente potencia de $\alpha$ modulo I$$, tomar la 7ª potencia de forma recursiva, y sustituir las probabilidades para las letras.

3voto

jldugger Puntos 7490

Srikant es correcta: un estudio de Monte Carlo es el camino a seguir. Hay dos razones. En primer lugar, la respuesta depende fuertemente de la estructura del diccionario. Los dos extremos son (1) el diccionario contiene todo lo posible de una sola letra de la palabra. En este caso, la posibilidad de no hacer de una palabra en un sorteo de $1$ o más letras es cero. (2) El diccionario contiene sólo palabras formadas por una sola letra (por ejemplo, "a", "aa", "aaa", etc.). La posibilidad de no hacer de una palabra en un sorteo de $k$ letras es fácilmente determinado y que, obviamente, es distinto de cero. Cualquier definido de forma cerrada respuesta tendría que incorporar la totalidad de la estructura de los diccionarios y sería verdaderamente terrible y larga fórmula.

La segunda razón es que la MC, de hecho, es posible: usted sólo tiene que hacerlo a la derecha. El párrafo anterior nos proporciona una pista: no sólo generar palabras al azar y mirar hacia arriba; en su lugar, analizar el diccionario de primera y explotar su estructura.

Una forma representa las palabras en el diccionario como un árbol. El árbol está arraigada en el símbolo vacío y ramas en cada letra todo el camino hacia abajo; sus hojas son (por supuesto) las palabras en sí. Sin embargo, también podemos insertar todas trivial permutaciones de cada palabra en el árbol, demasiado (hasta $k!-1$ de ellos para cada palabra). Esto se puede hacer de manera eficiente, porque uno no tiene que almacenar todos los permutaciones; sólo los bordes en el árbol necesita ser añadido. Las hojas siguen siendo los mismos. De hecho, esto se puede simplificar más, insistiendo en que el árbol se siguieron en orden alfabético.

En otras palabras, para determinar si un conjunto múltiple de $k$ personajes está en el diccionario, primero organizar los elementos en orden, a continuación, busque este ordenadas de la palabra "de" en un árbol construido a partir de la ordenada representantes de las palabras en el diccionario original. Esto va a ser menor que el árbol original debido a que se combina con todos los conjuntos de palabras que son una especie de equivalente, tales como {stop, post, ollas, opta, irregular}. De hecho, en el diccionario inglés esta clase de palabras que nunca alcance de todos modos, porque "por lo que" podría ser que encuentre primero. Vamos a ver esto en acción. La ordenada conjunto múltiple es "opst"; la "o" sería rama a todas las palabras que contiene sólo las letras {o, p, ..., z}, la "p" sería rama a todas las palabras que contienen sólo {o, p, ..., z} y en más de una "o", y por último, la "s" sería una rama de la hoja ", por eso"! (He supuesto que ninguno de los candidatos plausibles "o", "op", "po", "ops", o "pos" en el diccionario).

Una modificación es necesaria para manejar los comodines: voy a permitir que el programador tipos entre los que usted piensa acerca de eso. No va a aumentar el tamaño del diccionario (se debe reducir, de hecho); es ligeramente más lento que el árbol de recorrido, pero sin cambiar en lo fundamental. En cualquier diccionario que contiene una sola letra de la palabra, como el inglés ("a", "i"), no hay ninguna complicación: la presencia de un comodín significa que usted puede formar una palabra! (Esto sugiere que la pregunta original, puede no ser tan interesante como suena.)

El resultado de todo esto es que una simple búsqueda en diccionario requiere (a) la clasificación de un $k$-carta de conjunto múltiple y (b) que atraviesa no más de $k$ bordes de un árbol. El tiempo de ejecución es $O(k \log(k))$. Si usted hábilmente generar al azar multisets en orden (no puedo pensar en varias formas eficaces de hacer esto), el tiempo de ejecución se reduce a $O(k)$. Multiplique esto por el número de iteraciones para obtener el tiempo total de ejecución.

Apuesto a que podría llevar a cabo este estudio con un verdadero juego de Scrabble, y un millón de iteraciones en cuestión de segundos.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X