Suponha que você tenha uma sacola com ladrilhos, cada uma com uma letra. Existem blocos com a letra 'A', com 'B' e assim por diante, e 'curinga' (temos ). Suponha que você tenha um dicionário com um número finito de palavras. Você escolhe ladrilhos da sacola sem reposição. Como você calcula (ou estima) a probabilidade de formar zero palavras no dicionário, considerando os blocos selecionados?n B n ∗ n = n A + n B + … + n Z + n ∗ k k
Para aqueles que não estão familiarizados com o Scrabble (TM), o caractere curinga pode ser usado para corresponder a qualquer letra. Assim, a palavra [ BOOT ] pode ser 'soletrada' com os blocos 'B', '*', 'O', 'T'.
Para se ter uma idéia da escala do problema, é pequeno, como 7, é de cerca de 100 e o dicionário contém cerca de 100.000 palavras de tamanho ou menor.n k
edit: Por 'formar uma palavra', quero dizer uma palavra de comprimento não superior a . Assim, se a palavra [ A ] estiver no dicionário, então, tirando um único 'A' da sacola, a pessoa 'formará uma palavra'. O problema dos curingas é radicalmente simplificado se alguém puder assumir que há palavras com tamanho 1 no dicionário. Pois, se houver, qualquer empate de um curinga pode corresponder automaticamente a uma palavra de comprimento 1 e, portanto, é possível se concentrar no caso em que não há curingas. Portanto, a forma mais escorregadia do problema não possui palavras com uma letra no dicionário.
Além disso, devo declarar explicitamente que a ordem em que as cartas são retiradas da sacola é irrelevante. Não é necessário desenhar as letras na ordem 'correta' da palavra.
fonte
Respostas:
Este é um comentário (longo!) Sobre o bom trabalho que o @vqv postou neste tópico. O objetivo é obter uma resposta definitiva. Ele fez o trabalho duro de simplificar o dicionário. Tudo o que resta é explorá-lo ao máximo. Seus resultados sugerem que uma solução de força bruta é viável . Afinal, incluindo um curinga, existem no máximo palavras que se pode fazer com 7 caracteres e parece que menos de 1/10000 deles - digamos, cerca de um milhão - não incluirão algumas informações válidas. palavra.277=10,460,353,203
A primeira etapa é aumentar o dicionário mínimo com um caractere curinga, "?". 22 das letras aparecem em palavras de duas letras (todas, exceto c, q, v, z). Coloque um curinga nas 22 letras e adicione-o ao dicionário: {a ?, b ?, d ?, ..., y?} Estão agora. Da mesma forma, podemos inspecionar as palavras mínimas de três letras, causando algumas palavras adicionais para aparecer no dicionário. Por fim, adicionamos "??" para o dicionário. Após remover as repetições resultantes, ele contém 342 palavras mínimas.
Uma maneira elegante de proceder - uma que realmente use uma quantidade muito pequena de codificação - é ver esse problema como um problema algébrico . Uma palavra, considerada como um conjunto não ordenado de letras, é apenas um monômio. Por exemplo, "spats" é o monomial . O dicionário, portanto, é uma coleção de monômios. Pareceaps2t
(onde, para evitar confusão, escrevi para o caractere curinga).ψ
Um rack contém uma palavra válida se e somente se essa palavra divide o rack.
Uma maneira mais abstrata, mas extremamente poderosa, de dizer isso é que o dicionário gera um ideal no anel polinomial e que os racks possuem valores válidos. as palavras se tornam zero no anel de quociente , enquanto racks sem palavras válidas permanecem diferentes de zero no quociente. Se formarmos a soma de todos os racks em e computá-lo nesse anel de quociente, o número de racks sem palavras será igual ao número de monômios distintos no quociente.R = Z [ a , b , … , z , ψ ] R / I RI R=Z[a,b,…,z,ψ] R/I R
Além disso, a soma de todos os racks em é fácil de expressar. Seja a soma de todas as letras do alfabeto. contém um monomial para cada rack. (Como um bônus adicional, seus coeficientes contam o número de maneiras que cada rack pode ser formado, permitindo calcular sua probabilidade, se quisermos.)α = a + b + ⋯ + z + ψ α 7R α=a+b+⋯+z+ψ α7
Como um exemplo simples (para ver como isso funciona), suponha que (a) não usamos caracteres curinga e (b) todas as letras de "a" a "x" sejam consideradas palavras. Então, os únicos racks possíveis dos quais as palavras não podem ser formadas devem consistir inteiramente de y e z. Calculamos módulo o ideal gerado por um passo de cada vez, assim: { a , b , c , … , x }α=(a+b+c+⋯+x+y+z)7 {a,b,c,…,x}
Podemos ler a chance de obter um rack que não seja uma palavra da resposta final, : cada coeficiente conta as maneiras pelas quais o rack correspondente pode ser desenhado. Por exemplo, existem 21 (de 26 ^ 7 possíveis) maneiras de desenhar 2 y e 5 z porque o coeficiente de é igual a 21.y7+7y6z+21y5z2+35y4z3+35y3z4+21y2z5+7yz6+z7 y2z5
A partir de cálculos elementares, é óbvio que esta é a resposta correta. O ponto principal é que esse procedimento funciona independentemente do conteúdo do dicionário.
Observe como reduzir o módulo de potência o ideal em cada estágio reduz o cálculo: esse é o atalho revelado por essa abordagem. (Fim do exemplo.)
Os sistemas de álgebra polinomial implementam esses cálculos . Por exemplo, aqui está o código do Mathematica :
(O dicionário pode ser construído de maneira direta a partir do min.dict de @ vqv; coloquei uma linha aqui mostrando que é curto o suficiente para ser especificado diretamente, se você preferir.)
A saída - que leva dez minutos de computação - é 577958. ( NB Em uma versão anterior desta mensagem, cometi um pequeno erro na preparação do dicionário e obtive 577940. Editei o texto para refletir o que espero que esteja agora os resultados corretos!) Um pouco menos do que o milhão que eu esperava, mas da mesma ordem de magnitude.
Para calcular a chance de obter esse rack, precisamos levar em consideração o número de maneiras pelas quais o rack pode ser desenhado. Como vimos no exemplo, isso é igual ao seu coeficiente em . A chance de desenhar algum rack é a soma de todos esses coeficientes, facilmente encontrados ao definir todas as letras iguais a 1:α7
A resposta é igual a 1066056120, dando uma chance de 10,1914% de desenhar um rack do qual nenhuma palavra válida pode ser formada (se todas as letras forem igualmente prováveis).
Quando as probabilidades das letras variarem, substitua cada letra pela chance de ser sorteada:
O resultado é 1.079877553303%, a resposta exata (embora usando um modelo aproximado, desenhando com substituição). Olhando para trás, foram necessárias quatro linhas para inserir os dados (alfabeto, dicionário e frequências do alfabeto) e apenas três linhas para executar o trabalho: descrever como obter a próxima potência de modulo , tomar a 7ª potência recursivamente e substituir as probabilidades para as letras.α I
fonte
É muito difícil desenhar um rack que não contenha nenhuma palavra válida no Scrabble e suas variantes. Abaixo está um programa R que escrevi para estimar a probabilidade de o rack inicial de 7 blocos não conter uma palavra válida. Ele usa uma abordagem de monte carlo e o léxico Words With Friends (não consegui encontrar o léxico oficial do Scrabble em um formato fácil). Cada tentativa consiste em desenhar um rack de 7 blocos e verificar se o rack contém uma palavra válida.
Palavras mínimas
Você não precisa digitalizar o léxico inteiro para verificar se o rack contém uma palavra válida. Você só precisa digitalizar um léxico mínimo composto por palavras mínimas . Uma palavra é mínima se não contiver outra palavra como subconjunto. Por exemplo, 'em' é uma palavra mínima; 'vazio' não é. O ponto disso é que, se um rack contém a palavra x , também deve conter qualquer subconjunto de x . Em outras palavras: um rack não contém palavras se não contiver palavras mínimas. Felizmente, a maioria das palavras no léxico não é mínima, portanto elas podem ser eliminadas. Você também pode mesclar palavras equivalentes à permutação. Consegui reduzir o léxico Words With Friends de 172.820 para 201 palavras mínimas.
Os curingas podem ser facilmente manipulados tratando racks e palavras como distribuições nas letras. Verificamos se um rack contém uma palavra subtraindo uma distribuição da outra. Isso nos dá o número de cada letra que falta no rack. Se a soma desses números for o número de curingas, a palavra estará no rack.≤
O único problema com a abordagem de Monte Carlo é que o evento em que estamos interessados é muito raro. Portanto, são necessárias muitas e muitas tentativas para obter uma estimativa com um erro padrão pequeno o suficiente. Executei meu programa (colado na parte inferior) com tentativas e obtive uma probabilidade estimada de 0,004 de que o rack inicial não contenha uma palavra válida . O erro padrão estimado dessa estimativa é 0,0002. Demorou apenas alguns minutos para rodar no meu Mac Pro, incluindo o download do léxico.N=100,000
Eu estaria interessado em ver se alguém pode criar um algoritmo exato eficiente. Uma abordagem ingênua baseada na inclusão-exclusão parece envolver uma explosão combinatória.
Inclusão-exclusão
Eu acho que essa é uma solução ruim, mas aqui está um esboço incompleto. Em princípio, você pode escrever um programa para fazer o cálculo, mas a especificação seria tortuosa.
A probabilidade que queremos calcular é O evento dentro da probabilidade no lado direito é uma união de eventos: onde é um léxico mínimo. Podemos expandi-lo usando a fórmula de inclusão-exclusão. Envolve considerar todas as interseções possíveis dos eventos acima. Vamos denotam o conjunto das partes de , ou seja, o conjunto de todos os subconjuntos possíveis de . Então
A última coisa a especificar é como calcular a probabilidade na última linha acima. Envolve uma hipergeometria multivariada. é o evento que o rack contém cada palavra . É difícil lidar com isso por causa dos curingas. Por condicionamento, teremos que considerar cada um dos seguintes casos: o rack não contém curingas, o rack contém 1 curinga, o rack contém 2 curingas, ...
Então
Vou parar por aqui, porque as expansões são tortuosas para escrever e nem um pouco esclarecedoras. É mais fácil escrever um programa de computador para fazer isso. Mas agora você deve ver que a abordagem de inclusão-exclusão é intratável. Envolve termos, cada um dos quais também é muito complicado. Para o léxico, considerei acima .2|M| 2|M|≈3.2×1060
Digitalizando todos os racks possíveis
Eu acho que isso é computacionalmente mais fácil, porque há menos racks possíveis do que possíveis subconjuntos de palavras mínimas. Reduzimos sucessivamente o conjunto de possíveisk - prateleiras de ladrilhos até obtermos o conjunto de prateleiras que não contêm palavras. Para Scrabble (ou Words With Friends), o número possível de racks de 7 blocos é de dezenas de bilhões. Contar o número daqueles que não contêm uma palavra possível deve ser possível com algumas dezenas de linhas de código R. Mas acho que você deve ser capaz de fazer melhor do que apenas enumerar todos os racks possíveis. Por exemplo, 'aa' é uma palavra mínima. Isso elimina imediatamente todos os racks que contêm mais de um 'a'. Você pode repetir com outras palavras. A memória não deve ser um problema para computadores modernos. Um rack Scrabble de 7 blocos requer menos de 7 bytes de armazenamento. Na pior das hipóteses, usaríamos alguns gigabytes para armazenar todos os racks possíveis, mas também não acho que seja uma boa ideia. Alguém pode querer pensar mais sobre isso.
Programa Monte Carlo R
fonte
Srikant está certo: um estudo de Monte Carlo é o caminho a percorrer. Existem duas razões. Primeiro, a resposta depende fortemente da estrutura do dicionário. Dois extremos são: (1) o dicionário contém todas as palavras possíveis de uma única letra. Nesse caso, a chance de não formar uma palavra em um empate de ou mais letras é zero. (2) O dicionário contém apenas palavras formadas em uma única letra ( por exemplo , "a", "aa", "aaa", etc. ) A chance de não formar uma palavra com um letras é facilmente determinada e obviamente é diferente de zero. Qualquer resposta definitiva em formato fechado teria que incorporar toda a estrutura do dicionário e seria uma fórmula realmente terrível e longa.1 k
A segunda razão é que o MC é realmente viável: você só precisa fazer o que é certo. O parágrafo anterior fornece uma pista: não apenas gere palavras aleatoriamente e procure-as; em vez disso, analise o dicionário primeiro e explore sua estrutura.
Uma maneira representa as palavras no dicionário como uma árvore. A árvore está enraizada no símbolo vazio e se ramifica em cada letra até o fim; suas folhas são (é claro) as próprias palavras. No entanto, também podemos inserir todas as permutações não triviais de cada palavra na árvore também (até delas para cada palavra). Isso pode ser feito com eficiência, porque não é necessário armazenar todas essas permutações; somente as arestas da árvore precisam ser adicionadas. As folhas permanecem as mesmas. De fato, isso pode ser simplificado ainda mais, insistindo que a árvore seja seguida em ordem alfabética .k!−1
Em outras palavras, para determinar se um conjunto múltiplo de caracteres está no dicionário, primeiro organize os elementos na ordem de classificação,k em seguida, procure essa "palavra" classificada em uma árvore construída a partir dos representantes classificados das palavras no dicionário original. Na verdade, ele será menor que a árvore original porque mescla todos os conjuntos de palavras equivalentes à classificação, como {stop, post, pots, opts, spot}. De fato, em um dicionário em inglês, essa classe de palavras nunca seria alcançada, porque "so" seria encontrado primeiro. Vamos ver isso em ação. O multiset classificado é "opst"; o "o" ramifica para todas as palavras que contêm apenas as letras {o, p, ..., z}, o "p" ramifica para todas as palavras que contêm apenas {o, p, ..., z} e no máximo um "o" e, finalmente, o "s" se ramifica para a folha "so"! (Presumi que nenhum dos candidatos plausíveis "o", "op", "
É necessária uma modificação para lidar com curingas: deixarei que os tipos de programadores entre vocês pensem sobre isso. Não aumentará o tamanho do dicionário (deve diminuir, de fato); desacelerará um pouco a travessia da árvore, mas sem alterá-la de maneira fundamental. Em qualquer dicionário que contenha uma palavra de uma letra, como inglês ("a", "i"), não há complicações: a presença de um curinga significa que você pode formar uma palavra! (Isso sugere que a pergunta original pode não ser tão interessante quanto parece.)
O resultado é que uma única pesquisa no dicionário requer (a) a classificação de um conjunto múltiplo de letras e (b) a travessia de não mais do que arestas de uma árvore. O tempo de execução é . Se você habilmente gerar multisets aleatórios em ordem classificada (posso pensar em várias maneiras eficientes de fazer isso), o tempo de execução será reduzido para . Multiplique isso pelo número de iterações para obter o tempo total de execução.k O ( k log ( k ) ) O ( k )k k O(klog(k)) O(k)
Aposto que você poderia conduzir este estudo com um conjunto real de Scrabble e um milhão de iterações em questão de segundos.
fonte
Abordagem Monte Carlo
A abordagem rápida e suja é fazer um estudo de Monte Carlo. Desenhe ladrilhos vezes e, para cada desenho de ladrilhos, veja se é possível formar uma palavra. Indique o número de vezes que você pode formar uma palavra por . A probabilidade desejada seria:m k m wk m k mw
Abordagem direta
Deixe o número de palavras no dicionário ser dado por . Seja o número de maneiras pelas quais podemos formar a palavra . Deixe o número de letras necessário para a palavra ser indicado por (ou seja, a palavra precisa de número de letras 'a' etc). Denotar o número de palavras que pode formar com todas as peças por .t s s ° s th m um , m b , . . . , m zS ts sth sth ma,mb,...,mz m um Nsth ma N
e
(Incluir o impacto dos blocos curinga é um pouco mais complicado. Adiaremos esse problema por enquanto.)
Assim, a probabilidade desejada é:
fonte