Sebuah rumus diminta. Sayangnya, situasinya sangat rumit sehingga tampaknya formula apa pun hanya akan menjadi jalan memutar untuk menyebutkan semua kemungkinan. Alih-alih, jawaban ini menawarkan algoritma yang (a) sama dengan formula yang melibatkan jumlah produk dari koefisien binomial dan (b) dapat diangkut ke banyak platform.
Untuk mendapatkan formula seperti itu, bagi kemungkinan menjadi kelompok-kelompok yang saling terpisah dalam dua cara: menurut berapa banyak huruf tidak dalam kata yang dipilih di rak (biarkan ini m ) dan menurut berapa banyak wildcard (kosong) yang dipilih ( biarkan ini w ). Ketika ada r=7 petak di rak, N petak tersedia, M petak tersedia dengan huruf tidak ada dalam kata, dan W=2 kosong tersedia, jumlah pilihan yang mungkin diberikan oleh (m,w) adalah
(Mm)(Ww)(N−M−Wr−m−w)
karena pilihan huruf non-kata, kosong, dan kata-kata bersyarat independen pada (m,w,r).
Ini mengurangi masalah untuk menemukan sejumlah cara untuk mengeja kata ketika memilih hanya dari petak yang mewakili huruf kata, mengingat bahwa kosong tersedia dan r - m - w petak akan dipilih. Situasinya berantakan dan tidak ada formula tertutup yang tersedia. Misalnya, dengan w = 0 kosong dan m = 3 huruf di luar kata ditarik, akan ada empat huruf tersisa untuk mengeja "boot" yang diambil dari ubin "b", "o", dan "t" . Mengingat ada 2 "b", 8 "o", dan 6wr−m−ww=0m=3286"t" ada di set ubin Scrabble, ada kemungkinan positif menggambar (multiset) "bboo", "bbot", "bbtt", "booo", "boot", "bott", "bttt", "oooo "," ooot "," oott "," ottt ", dan" tttt ", tetapi hanya satu dari mantra ini" boot ". Dan itu adalah kasus yang mudah! Misalnya, seandainya rak berisi lima ubin yang dipilih secara acak dari ubin "o", "b", dan "t", bersama dengan keduanya, ada banyak lagi cara untuk mengeja "boot" - dan bukan mengeja. Misalnya, "boot" dapat dieja dari "__boott" dan "__bbttt", tetapi tidak dari "__ttttt".
Penghitungan ini - inti dari masalah - dapat ditangani secara rekursif. Saya akan menggambarkannya dengan sebuah contoh. Misalkan kita ingin menghitung cara mengeja "boot" dengan satu ubin kosong dan empat ubin lagi dari koleksi ubin "b", "o", dan "t" (di mana dua ubin yang tersisa menunjukkan huruf-huruf tidak kosong yang tidak dalam { "b", "o", "t"}). Pertimbangkan huruf pertama, "b":
A "b" dapat ditarik ke dalam cara dari dua ubin "b" yang tersedia. Ini mengurangi masalah untuk menghitung jumlah cara mengeja akhiran "oot" menggunakan kedua kosong dan hanya tiga ubin lagi dari koleksi ubin "o" dan "t".(21)
Satu kosong dapat ditetapkan sebagai "b". Ini mengurangi masalah untuk menghitung jumlah cara mengeja "oot" menggunakan kosong yang tersisa dan hanya tiga ubin lagi dari koleksi ubin "o" dan "t".
Secara umum, langkah (1) dan (2) - yang terpisah dan karena itu berkontribusi secara positif pada perhitungan probabilitas - dapat diimplementasikan sebagai loop atas kemungkinan jumlah kosong yang mungkin digunakan untuk huruf pertama. Pengurangan masalah diselesaikan secara rekursif. Kasing dasar terjadi ketika ada satu huruf tersisa, ada sejumlah ubin dengan surat itu tersedia, dan mungkin ada beberapa kosong di rak juga. Kami hanya perlu memastikan bahwa jumlah kosong di rak ditambah jumlah ubin yang tersedia akan cukup untuk mendapatkan jumlah yang diinginkan dari surat terakhir.
Berikut ini adalah R
kode untuk langkah rekursif. rack
biasanya sama ,adalah array jumlah huruf (seperti),adalah struktur yang sama memberikan jumlah ubin yang tersedia dengan huruf-huruf itu, danjumlah kosong yang diasumsikan terjadi di rak.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))
}
Antarmuka untuk fungsi ini menentukan ubin Scrabble standar, mengubah kata yang diberikan ke dalam struktur data multisetnya, dan melakukan jumlah ganda di atas dan w . Di sinilah koefisien binomialmw dan ( W(Mm) dihitung dan dikalikan.(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)))
}
Mari kita coba solusi ini dan tentukan waktunya. Tes berikut menggunakan input yang sama yang digunakan dalam simulasi oleh @Rasmus Bååth :
system.time(x <- sapply(c("boot", "red", "axe", "zoology"), scrabble))
Mesin ini melaporkan total waktu berlalu detik: cukup cepat. Hasil?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
Probabilitas untuk "boot" dari persis sama dengan nilai 2381831 / 333490850 diperoleh dalam jawaban saya yang lain (yang menggunakan metode yang sama tapi sofa itu dalam kerangka yang lebih kuat membutuhkan platform aljabar komputasi simbolik). Probabilitas untuk semua empat kata yang cukup dekat dengan simulasi Baath (yang tidak bisa diharapkan untuk memberikan nilai yang akurat untuk "zoologi" karena probabilitas rendah dari 11840 / 16007560800 , yang kurang dari satu dalam satu juta).114327888/160075608002381831/33349085011840/16007560800,