Bir formül isteniyor. Ne yazık ki, durum o kadar karmaşıktır ki, herhangi bir formül sadece tüm olasılıkları sıralamak için dolambaçlı bir yol olacaktır. Bunun yerine, bu cevap bir , (a) binom katsayılarının toplamlarını içeren bir formüle eşit algoritma ve (b) birçok platforma taşınabilir.
Böyle bir formül elde etmek için, olasılıkları karşılıklı olarak ayrık gruplara ayırın : rafta kelimede olmayan harflerin kaçına göre (bu m ) ve kaç joker karakter (boşluk) seçildiğine göre ( bu w ). Olduğunda r=7 rafa fayans, N mevcut zemin, M sözcüğün harfleri ile mevcut kiremit ve W=2 mevcut boşlukları, verilen olası seçim sayısı (m,w) olduğu
(Mm)(Ww)(N−M−Wr−m−w)
çünkü kelime olmayan harflerin, boşlukların ve kelime harflerinin seçimleri bağımsız koşulludur (m,w,r).
Bu, kelimenin harfleri temsil eden çini sadece seçerken Bir kelimeyi yollarını sayısını bulma problemi azaltır verilen bu boşlukları edilebilir ve r - m - w çini seçilecektir. Durum dağınık ve kapalı formül mevcut değil. Örneğin, w = 0 boşluklar ve m = 3 sözcük dışı harfler çizildiğinde, "b", "o" ve "t" döşemelerinden çizilen "boot" kelimesini hecelemek için tam olarak dört harf kalır. . Verilen 2 "b" s, 8wr−m−ww=0m=328 "o" ve 6Scrabble kiremit kümesinde "t", çizim (multisets) "bboo", "bbot", "bbtt", "booo", "boot", "bott", "bttt", "oooo "," ooot "," oott "," ottt "ve" tttt ", ancak bu büyülerden yalnızca biri" boot ". Ve bu kolay durumdu! Örneğin, rafın "o", "b" ve "t" döşemelerinden rastgele seçilen beş döşemeyi içerdiğini varsayarsak, her iki boşlukla birlikte "çizme" yi hecelemenin ve hecelememenin daha birçok yolu vardır. Örneğin, "önyükleme", "__boott" ve "__bbttt" ifadelerinden hecelenebilir, ancak "__ttttt" öğesinden değil.
Sorunun kalbi olan bu sayım tekrar tekrar ele alınabilir. Bir örnekle anlatacağım. "Boşluk" yazımının "b", "o" ve "t" kutucuklarından oluşan bir boş ve dört kutucukla yazım yollarını saymak istediğimizi varsayalım (geri kalan iki kutucuk boş olmayan harfleri { "b", "o", "t"}). İlk harfi "b" düşünün:
Bir "b" çizilebilir mevcut iki "b" kiremit yolları. Bu, "o" ve "t" fayans koleksiyonundan hem boşlukları hem de sadece üç karo kullanarak "oot" sonekini yazmanın yollarını sayma sorununu azaltır.(21)
Bir boşluk "b" olarak tanımlanabilir. Bu, kalan boş ve "o" ve "t" fayans koleksiyonundan sadece üç karo kullanarak "oot" yazım yollarının sayısını sayma sorununu azaltır.
Genel olarak, ayrık olan ve dolayısıyla olasılık hesaplamalarına katkı sağlayan katkıda bulunan (1) ve (2) aşamaları, ilk harf için kullanılabilecek boşluk sayısının üzerinde bir döngü olarak uygulanabilir. Azalan problem özyinelemeli olarak çözülür. Temel durum, bir harf kaldı, bu harfin bulunduğu belirli sayıda karo olduğunda oluşur ve rafta da bazı boşluklar olabilir. Sadece raftaki boşluk sayısının ve mevcut döşemelerin sayısının son mektubun istenen miktarını elde etmek için yeterli olduğundan emin olmalıyız.
İşte R
özyinelemeli adım için kod. rack
Genellikle eşittir , harfler (örneğin, ve sayıları bir dizisi olan ), bu harflerle mevcut kiremit numaraları veren benzer bir yapıdır, ve boşlukların sayısı rafa oluştuğu varsayılmaktadır.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))
}
Bu işleve yönelik bir arabirim standart Scrabble döşemelerini belirtir, belirli bir sözcüğü çok kümeli veri yapısına dönüştürür ve ve w üzerinde çift toplamı gerçekleştirir . İşte binom katsayıları ( Mmw ve ( W(Mm) hesaplanır ve çoğaltılır.(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)))
}
Bu çözümü deneyelim ve giderken zamanlayalım. Aşağıdaki test @Rasmus Bååth tarafından yapılan simülasyonlarda kullanılan girişlerin aynısını kullanır :
system.time(x <- sapply(c("boot", "red", "axe", "zoology"), scrabble))
Bu makine toplam geçen süreyi saniye olarak bildirir : oldukça hızlı. Sonuçlar?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
Arasında "çizme" için olasılık tam değer eşittir 2381831 / 333.490.850 elde benim diğer yanıt (sembolik cebir hesaplama platformu gerektiren daha güçlü bir çerçeveye benzer bir yöntem ama kanepe bunu kullanır). Dört kelime olasılıkları (dolayı onun ihtimali olduğu için "zooloji" için doğru bir değer vermesi bekleniyor edilemedi makul yakın Baas simülasyonları için vardır 11840 / 16007560800 , az milyonda biri daha).114327888/160075608002381831/33349085011840/16007560800,