Une formule est demandée. Malheureusement, la situation est si compliquée qu'il semble que toute formule ne soit qu'un moyen détourné d'énumérer toutes les possibilités. Au lieu de cela, cette réponse propose un algorithme qui (a) équivaut à une formule impliquant des sommes de produits de coefficients binomiaux et (b) peut être porté sur de nombreuses plates-formes.
Pour obtenir une telle formule, divisez les possibilités en groupes mutuellement disjoints de deux manières: selon le nombre de lettres absentes du mot sélectionnées dans le rack (que ce soit ) et selon le nombre de caractères génériques (blancs) sélectionnés ( que ce soit w ). Lorsqu'il y a r = 7 tuiles dans le rack, N tuiles disponibles, M tuiles disponibles avec des lettres absentes du mot et W = 2 blancs disponibles, le nombre de choix possibles donné par ( m , w ) estmwr=7NMW=2(m,w)
(Mm)(Ww)(N−M−Wr−m−w)
car les choix de lettres non vierges, de blancs et de lettres de mots sont indépendants et conditionnels à (m,w,r).
Cela réduit le problème de trouver le nombre de façons d'épeler un mot lors de la sélection uniquement à partir des tuiles représentant les lettres du mot, étant donné que blancs sont disponibles et que les tuiles r - m - w seront sélectionnées. La situation est désordonnée et aucune formule fermée ne semble disponible. Par exemple, avec w = 0 espaces et m = 3 lettres hors mot sont dessinées, il restera précisément quatre lettres pour épeler "boot" qui ont été tirées des tuiles "b", "o" et "t" . Étant donné qu'il y a 2 "b", 8 "o" et 6wr−m−ww=0m=3286"t" dans le jeu de tuiles Scrabble, il y a des probabilités positives de dessiner (multisets) "bboo", "bbot", "bbtt", "booo", "boot", "bott", "bttt", "oooo "," ooot "," oott "," ottt "et" tttt ", mais un seul de ces sorts" boot ". Et c'était le cas facile! Par exemple, en supposant que le rack contient cinq tuiles choisies au hasard parmi les tuiles "o", "b" et "t", ainsi que les deux blancs, il existe de nombreuses autres façons d'épeler "boot" - et non de l'épeler. Par exemple, "boot" peut être orthographié à partir de "__boott" et "__bbttt", mais pas de "__ttttt".
Ce comptage - le cœur du problème - peut être géré de manière récursive. Je vais le décrire avec un exemple. Supposons que nous souhaitons compter les façons d'orthographier "boot" avec une tuile vide et quatre autres tuiles de la collection de tuiles "b", "o" et "t" (d'où les deux tuiles restantes montrent des lettres non vides pas en { "b", "o", "t"}). Considérez la première lettre, "b":
Un "b" peut être tracé chemins à partir des deux tuiles "b" disponibles. Cela réduit le problème de compter le nombre de façons d'épeler le suffixe "oot" en utilisant les deux blancs et seulement trois autres tuiles de la collection de tuiles "o" et "t".(21)
Un blanc peut être désigné comme un "b". Cela réduit le problème de compter le nombre de façons d'orthographe "oot" en utilisant le blanc restant et seulement trois autres tuiles de la collection de tuiles "o" et "t".
En général, les étapes (1) et (2) - qui sont disjointes et contribuent donc de manière additive aux calculs de probabilité - peuvent être implémentées en boucle sur le nombre possible de blancs qui pourraient être utilisés pour la première lettre. Le problème réduit est résolu récursivement. Le cas de base se produit quand il reste une lettre, qu'il y a un certain nombre de tuiles avec cette lettre disponible et qu'il peut aussi y avoir des blancs dans le rack. Il suffit de s'assurer que le nombre de blancs dans le rack plus le nombre de tuiles disponibles sera suffisant pour obtenir la quantité souhaitée de cette dernière lettre.
Voici le R
code de l'étape récursive. rack
est généralement égal à , est un tableau de décomptes des lettres (comme ), est une structure similaire donnant le nombre de tuiles disponibles avec ces lettres, et est le nombre de blancs supposés se produire dans le rack.7word
c(b=1, o=2, t=1)
alphabet
wild
f <- function(rack, word, alphabet, wild) {
if (length(word) == 1) {
return(ifelse(word > rack+wild, 0, choose(alphabet, rack)))
}
n <- word[1]
if (n <= 0) return(0)
m <- alphabet[1]
x <- sapply(max(0, n-wild):min(m, rack),
function(i) {
choose(m, i) * f(rack-i, word[-1], alphabet[-1], wild-max(0, n-i))
})
return(sum(x))
}
Une interface pour cette fonction spécifie les tuiles Scrabble standard, convertit un mot donné en sa structure de données multiset et effectue la double somme sur et w . Voici où les coefficients binomiaux ( Mmw et ( W(Mm) sont calculés et multipliés.(Ww)
scrabble <- function(sword, n.wild=2, rack=7,
alphabet=c(a=9,b=2,c=2,d=4,e=12,f=2,g=3,h=2,i=9,j=1,k=1,l=4,m=2,
n=6,o=8,p=2,q=1,r=6,s=4,t=6,u=4,v=2,w=2,x=1,y=2,z=1),
N=sum(alphabet)+n.wild) {
word = sort(table(strsplit(sword, NULL))) # Sorting speeds things a little
a <- sapply(names(word), function(s) alphabet[s])
names(a) <- names(word)
x <- sapply(0:n.wild, function(w) {
sapply(sum(word):rack-w,
function(i) {
f(i, word, a, wild=w) *
choose(n.wild, w) * choose(N-n.wild-sum(a), rack-w-i)
})
})
return(list(numerator = sum(x), denominator = choose(N, rack),
value=sum(x) / choose(N, rack)))
}
Essayons cette solution et chronométrons au fur et à mesure. Le test suivant utilise les mêmes entrées que celles utilisées dans les simulations de @Rasmus Bååth :
system.time(x <- sapply(c("boot", "red", "axe", "zoology"), scrabble))
Cette machine signale un temps total écoulé de seconde: relativement rapide. Les resultats?0.05
> x
boot red axe zoology
numerator 114327888 1249373480 823897928 11840
denominator 16007560800 16007560800 16007560800 16007560800
value 0.007142118 0.07804896 0.0514693 7.396505e-07
La probabilité pour « démarrage » de est exactement égale à la valeur 2.381.831 / 333490850 obtenu dans mon autre réponse (qui utilise une méthode similaire , mais des canapés dans un cadre plus puissant nécessitant une plate - forme de calcul algèbre symbolique). Les probabilités pour les quatre mots sont assez proches des simulations de Baath (qui ne pouvait attendre de donner une valeur exacte pour « Zoology » en raison de sa faible probabilité de 11 840 / 16007560800 , qui est inférieur à un sur un million).114327888/160075608002381831/33349085011840/16007560800,