Akhir-akhir ini saya telah memainkan game di iPhone saya yang disebut Scramble. Beberapa dari Anda mungkin tahu game ini sebagai Boggle. Intinya, saat permainan dimulai Anda mendapatkan matriks huruf-huruf seperti:
F X I E
A M L O
E W B X
A S T U
Tujuan permainan ini adalah untuk menemukan kata-kata sebanyak yang Anda bisa yang dapat dibentuk dengan merantai surat bersama. Anda bisa mulai dengan huruf apa saja, dan semua huruf yang mengelilinginya adalah permainan yang adil, dan kemudian setelah Anda beralih ke huruf berikutnya, semua huruf yang mengelilingi huruf itu adalah permainan yang adil, kecuali untuk huruf yang sebelumnya digunakan . Jadi dalam grid di atas, misalnya, saya bisa datang dengan kata-kata LOB
, TUX
, SEA
, FAME
, dll Kata-kata harus minimal 3 karakter, dan tidak lebih dari karakter NxN, yang akan 16 dalam game ini tetapi dapat bervariasi dalam beberapa implementasi . Meskipun permainan ini menyenangkan dan membuat ketagihan, saya tampaknya tidak terlalu ahli dalam hal itu dan saya ingin sedikit curang dengan membuat program yang akan memberi saya kata-kata terbaik (semakin lama kata semakin banyak poin yang Anda dapatkan).
(sumber: boggled.org )
Sayangnya, saya tidak terlalu bagus dengan algoritma atau efisiensinya dan sebagainya. Upaya pertama saya menggunakan kamus seperti ini (~ 2.3MB) dan melakukan pencarian linier yang mencoba mencocokkan kombinasi dengan entri kamus. Ini membutuhkan waktu yang sangat lama untuk menemukan kata-kata yang mungkin, dan karena Anda hanya mendapatkan 2 menit per putaran, itu sama sekali tidak memadai.
Saya tertarik untuk melihat apakah ada Stackoverflowers dapat datang dengan solusi yang lebih efisien. Saya kebanyakan mencari solusi menggunakan Big 3 Ps: Python, PHP, dan Perl, meskipun apa pun dengan Java atau C ++ juga keren, karena kecepatan sangat penting.
SOLUSI SAAT INI :
- Adam Rosenfield, Python, ~ 20s
- John Fouhy, Python, ~ 3s
- Kent Fredric, Perl, ~ 1s
- Darius Bacon, Python, ~ 1s
- rvarcher, VB.NET (tautan langsung) , ~ 1s
- Paolo Bergantino, PHP (tautan langsung) , ~ 5s (~ 2s lokal)
Jawaban:
Jawaban saya berfungsi seperti yang lain di sini, tetapi saya akan mempostingnya karena terlihat sedikit lebih cepat daripada solusi Python lainnya, dari mengatur kamus lebih cepat. (Saya memeriksa ini terhadap solusi John Fouhy.) Setelah pengaturan, waktu untuk menyelesaikannya turun dalam kebisingan.
Penggunaan sampel:
Sunting: Saring kata-kata yang panjangnya kurang dari 3 huruf.
Sunting 2: Saya ingin tahu mengapa solusi Perl Kent Fredric lebih cepat; ternyata menggunakan pencocokan ekspresi reguler alih-alih sekumpulan karakter. Melakukan hal yang sama dengan Python tentang menggandakan kecepatan.
sumber
def neighbors((x, y))
(sia-sia, sejauh yang saya bisa lihat). Juga membutuhkan tanda kurung di sekitar argumen untukprint
.Solusi tercepat yang akan Anda dapatkan mungkin melibatkan penyimpanan kamus Anda dalam sebuah trie . Kemudian, buat antrian triplet ( x , y , s ), di mana setiap elemen dalam antrian sesuai dengan awalan s kata yang bisa dieja dalam kisi, berakhir di lokasi ( x , y ). Inisialisasi antrian dengan N x N elemen (di mana N adalah ukuran kotak Anda), satu elemen untuk setiap kotak di kisi. Kemudian, algoritma melanjutkan sebagai berikut:
Jika Anda menyimpan kamus Anda dalam sebuah trie, menguji apakah s + c adalah sebuah kata atau awalan kata dapat dilakukan dalam waktu yang konstan (asalkan Anda juga menyimpan beberapa metadata tambahan di setiap datum antrian, seperti pointer ke node saat ini dalam trie), sehingga waktu berjalan dari algoritma ini adalah O (jumlah kata yang dapat dieja).
[Sunting] Berikut ini adalah implementasi dengan Python yang baru saja saya kodekan:
Contoh penggunaan:
Keluaran:
Catatan: Program ini tidak menghasilkan kata 1-huruf, atau menyaring berdasarkan panjang kata sama sekali. Itu mudah ditambahkan tetapi tidak benar-benar relevan dengan masalah tersebut. Ini juga menghasilkan beberapa kata beberapa kali jika mereka dapat dieja dalam beberapa cara. Jika kata yang diberikan dapat dieja dengan berbagai cara (kasus terburuk: setiap huruf dalam kisi adalah sama (misalnya 'A') dan kata seperti 'aaaaaaaaaa' ada di kamus Anda), maka waktu yang berjalan akan menjadi eksponensial yang mengerikan . Memfilter duplikat dan pengurutan sepele karena setelah algoritma selesai.
sumber
(x,y)
, pengikut yang mungkin adalah(x+1,y+1)
. Kemudian(x+1,y+1)
didorong ke antrian. Namun(x,y)
akan terlalu menjadi pengikut(x+1,y+1)
, jadi bukankah itu akan menyebabkan pantulan yang tak berkesudahan di antara mereka?Untuk mempercepat kamus, ada satu transformasi / proses umum yang dapat Anda lakukan untuk mengurangi perbandingan kamus sebelumnya.
Mengingat kisi di atas hanya berisi 16 karakter, beberapa di antaranya duplikat, Anda dapat sangat mengurangi jumlah kunci total dalam kamus Anda dengan hanya memfilter entri yang memiliki karakter yang tidak dapat dicapai.
Saya pikir ini adalah optimasi yang jelas tetapi melihat tidak ada yang melakukannya saya menyebutkannya.
Itu mengurangi saya dari kamus 200.000 kunci menjadi hanya 2.000 kunci hanya selama input masuk. Paling tidak ini mengurangi overhead memori, dan itu pasti akan memetakan ke peningkatan kecepatan di suatu tempat karena memori tidak terlalu cepat.
Implementasi Perl
Implementasi saya agak terlalu berat karena saya menempatkan pentingnya untuk mengetahui jalur yang tepat dari setiap string yang diekstraksi, bukan hanya validitas di dalamnya.
Saya juga punya beberapa adaptasi di sana yang secara teori akan mengizinkan sebuah grid dengan lubang di dalamnya berfungsi, dan grid dengan garis-garis berukuran berbeda (dengan asumsi Anda mendapatkan input yang benar dan berbaris entah bagaimana).
Filter awal sejauh ini merupakan hambatan paling signifikan dalam aplikasi saya, seperti yang diduga sebelumnya, mengomentari bahwa garis menggembungkannya dari 1,5s ke 7,5s.
Setelah dieksekusi tampaknya berpikir semua angka tunggal pada kata-kata mereka sendiri yang valid, tapi saya cukup yakin itu karena cara kerja file kamus.
Agak bengkak, tapi setidaknya saya menggunakan kembali Tree :: Trie from cpan
Beberapa di antaranya terinspirasi sebagian oleh implementasi yang ada, beberapa di antaranya sudah ada dalam pikiran saya.
Kritik Konstruktif dan cara-cara itu bisa diperbaiki, selamat datang (/ saya catat dia tidak pernah mencari CPAN untuk pemecah boggle , tapi ini lebih menyenangkan untuk dilakukan)
diperbarui untuk kriteria baru
Lengkungan / info eksekusi untuk perbandingan:
Mumblings lainnya tentang Regex Optimization
Optimasi regex yang saya gunakan tidak berguna untuk kamus multi-penyelesaian, dan untuk multi-pemecahan Anda ingin kamus lengkap, bukan kamus yang sudah dipangkas.
Namun demikian, untuk pemecahan sekali saja, ini sangat cepat. (Perl regex berada di C! :))
Berikut ini beberapa penambahan kode yang berbeda:
ps: 8.16 * 200 = 27 menit.
sumber
Anda dapat membagi masalah menjadi dua bagian:
Idealnya, (2) juga harus mencakup cara menguji apakah string merupakan awalan dari kata yang valid - ini akan memungkinkan Anda untuk memangkas pencarian Anda dan menghemat banyak waktu.
Adam Rosenfield's Trie adalah solusi untuk (2). Ini elegan dan mungkin apa yang lebih disukai oleh spesialis algoritme Anda, tetapi dengan bahasa modern dan komputer modern, kami bisa sedikit lebih malas. Juga, seperti yang disarankan Kent, kita dapat mengurangi ukuran kamus kita dengan membuang kata-kata yang tidak memiliki huruf di dalam kisi. Inilah beberapa python:
Wow; pengujian awalan waktu-konstan. Butuh beberapa detik untuk memuat kamus yang Anda tautkan, tetapi hanya beberapa :-) (perhatikan itu
words <= prefixes
)Sekarang, untuk bagian (1), saya cenderung berpikir dalam bentuk grafik. Jadi saya akan membuat kamus yang terlihat seperti ini:
yaitu
graph[(x, y)]
kumpulan koordinat yang dapat Anda jangkau dari posisi(x, y)
. Saya juga akan menambahkan simpul bonekaNone
yang akan terhubung ke semuanya.Membangunnya agak canggung, karena ada 8 posisi yang mungkin dan Anda harus melakukan pemeriksaan batas. Berikut adalah beberapa kode python yang canggung:
Kode ini juga membangun pemetaan kamus
(x,y)
ke karakter yang sesuai. Ini memungkinkan saya mengubah daftar posisi menjadi kata:Akhirnya, kami melakukan pencarian mendalam-pertama. Prosedur dasarnya adalah:
Python:
Jalankan kode sebagai:
dan periksa
res
untuk melihat jawabannya. Berikut daftar kata yang ditemukan untuk contoh Anda, diurutkan berdasarkan ukuran:Kode ini membutuhkan (secara harfiah) beberapa detik untuk memuat kamus, tetapi sisanya instan di mesin saya.
sumber
range(len(w)+1)
alih-alihrange(len(w))
. Saya mengklaim ituwords <= prefixes
tetapi ternyata saya tidak mengujinya: - /Usaha saya di Jawa. Dibutuhkan sekitar 2 detik untuk membaca file dan membangun trie, dan sekitar 50 ms untuk menyelesaikan teka-teki. Saya menggunakan kamus yang ditautkan dalam pertanyaan (ada beberapa kata yang saya tidak tahu ada dalam bahasa Inggris seperti fae, ima)
Kode sumber terdiri dari 6 kelas. Saya akan mempostingnya di bawah (jika ini bukan praktik yang tepat di StackOverflow, tolong beri tahu saya).
gineer.bogglesolver. Utama
gineer.bogglesolver.Solver
gineer.bogglesolver.trie.Node
gineer.bogglesolver.trie.Trie
gineer.bogglesolver.util.Constants
gineer.bogglesolver.util.Util
sumber
Saya pikir Anda mungkin akan menghabiskan sebagian besar waktu Anda mencoba mencocokkan kata-kata yang tidak mungkin dibangun oleh kotak surat Anda. Jadi, hal pertama yang akan saya lakukan adalah mencoba mempercepat langkah itu dan itu akan membuat Anda mendapatkan sebagian besar perjalanan ke sana.
Untuk ini, saya akan menyatakan kembali kotak sebagai tabel kemungkinan "bergerak" yang Anda indeks dengan transisi surat yang Anda lihat.
Mulailah dengan memberi setiap huruf suatu angka dari seluruh alfabet Anda (A = 0, B = 1, C = 2, ... dan seterusnya).
Mari kita ambil contoh ini:
Dan untuk sekarang, mari kita gunakan alfabet dari surat-surat yang kita miliki (biasanya Anda mungkin ingin menggunakan seluruh alfabet yang sama setiap waktu):
Kemudian Anda membuat array boolean 2D yang memberi tahu apakah Anda memiliki transisi huruf tertentu yang tersedia:
Sekarang, lihat daftar kata-kata Anda dan ubah kata-katanya menjadi transisi:
Kemudian periksa apakah transisi ini diizinkan dengan melihatnya di tabel Anda:
Jika mereka semua diizinkan, ada kemungkinan kata ini dapat ditemukan.
Misalnya kata "helm" dapat dikesampingkan pada transisi ke-4 (m ke e: helMEt), karena entri di tabel Anda salah.
Dan kata hamster dapat dikesampingkan, karena transisi pertama (h ke a) tidak diperbolehkan (bahkan tidak ada di meja Anda).
Sekarang, untuk kata-kata tersisa yang mungkin sangat sedikit yang tidak Anda hilangkan, cobalah untuk benar-benar menemukannya di grid seperti yang Anda lakukan sekarang atau seperti yang disarankan dalam beberapa jawaban lain di sini. Ini untuk menghindari kesalahan positif yang dihasilkan dari lompatan di antara huruf-huruf identik di kisi Anda. Misalnya kata "bantuan" diizinkan oleh tabel, tetapi tidak oleh grid.
Beberapa tips peningkatan kinerja lebih lanjut tentang ide ini:
Alih-alih menggunakan array 2D, gunakan array 1D dan cukup hitung sendiri indeks huruf kedua. Jadi, alih-alih array 12x12 seperti di atas, buat array 1D dengan panjang 144. Jika Anda selalu menggunakan alfabet yang sama (yaitu array 26x26 = 676x1 untuk alfabet bahasa Inggris standar), bahkan jika tidak semua huruf muncul di kisi Anda , Anda dapat melakukan pra-komputasi indeks ke dalam array 1D ini yang perlu Anda uji agar sesuai dengan kata-kata kamus Anda. Sebagai contoh, indeks untuk 'halo' pada contoh di atas adalah
Perluas ide ke tabel 3D (dinyatakan sebagai array 1D), yaitu semua kombinasi 3 huruf yang diizinkan. Dengan begitu Anda dapat menghilangkan lebih banyak kata dengan segera dan Anda mengurangi jumlah pencarian array untuk setiap kata sebanyak 1: Untuk 'halo', Anda hanya perlu 3 pencarian array: hel, ell, llo. Omong-omong, ini akan sangat cepat untuk membangun tabel ini, karena hanya ada 400 kemungkinan gerakan 3 huruf di kisi Anda.
Pra-hitung indeks gerakan di kisi Anda yang perlu Anda sertakan dalam tabel Anda. Untuk contoh di atas, Anda perlu mengatur entri berikut ke 'Benar':
Saya yakin jika Anda menggunakan pendekatan ini, Anda bisa membuat kode Anda berjalan sangat cepat, jika kamus Anda sudah dihitung sebelumnya dan sudah dimuat ke dalam memori.
BTW: Hal lain yang menyenangkan untuk dilakukan, jika Anda membangun game, adalah menjalankan hal-hal semacam ini segera di latar belakang. Mulai membuat dan menyelesaikan gim pertama saat pengguna masih melihat layar judul di aplikasi Anda dan memasukkan jari ke posisi untuk menekan "Mainkan". Kemudian hasilkan dan selesaikan game berikutnya saat pengguna memainkan yang sebelumnya. Itu akan memberi Anda banyak waktu untuk menjalankan kode Anda.
(Saya suka masalah ini, jadi saya mungkin akan tergoda untuk mengimplementasikan proposal saya di Jawa suatu hari nanti untuk melihat bagaimana itu benar-benar melakukan ... Saya akan memposting kode di sini setelah saya melakukannya.)
MEMPERBARUI:
Oke, saya punya waktu hari ini dan mengimplementasikan ide ini di Jawa:
Berikut ini beberapa hasilnya:
Untuk kisi-kisi dari gambar yang diposting dalam pertanyaan asli (DGHI ...):
Untuk surat-surat yang diposting sebagai contoh dalam pertanyaan asli (FXIE ...)
Untuk 5x5-grid berikut:
ini memberikan ini:
Untuk ini saya menggunakan TWL06 Tournament Scrabble Word List , karena tautan dalam pertanyaan awal tidak lagi berfungsi. File ini 1.85MB, jadi sedikit lebih pendek. Dan
buildDictionary
fungsinya membuang semua kata dengan kurang dari 3 huruf.Berikut adalah beberapa pengamatan tentang kinerja ini:
Ini sekitar 10 kali lebih lambat dari kinerja OCaml Victor Nicollet yang dilaporkan. Apakah ini disebabkan oleh algoritma yang berbeda, kamus pendek yang digunakannya, fakta bahwa kodenya dikompilasi dan milikku berjalan di mesin virtual Java, atau kinerja komputer kita (milikku adalah Intel Q6600 @ 2.4MHz yang menjalankan WinXP), Saya tidak tahu Tapi ini jauh lebih cepat daripada hasil untuk implementasi lain yang dikutip di akhir pertanyaan awal. Jadi, apakah algoritma ini lebih baik daripada kamus trie atau tidak, saya tidak tahu pada saat ini.
Metode tabel yang digunakan dalam
checkWordTriplets()
menghasilkan perkiraan yang sangat baik untuk jawaban yang sebenarnya. Hanya 1 dari 3-5 kata yang dilewati akan gagal dalamcheckWords()
ujian (Lihat jumlah kandidat vs. jumlah kata aktual di atas)Sesuatu yang tidak dapat Anda lihat di atas:
checkWordTriplets()
Fungsi ini membutuhkan waktu sekitar 3,65 ms dan karenanya sepenuhnya dominan dalam proses pencarian. ThecheckWords()
Fungsi memakan cukup banyak 0,05-0,20 ms tersisa.Waktu pelaksanaan
checkWordTriplets()
fungsi tergantung secara linear pada ukuran kamus dan hampir tidak tergantung pada ukuran papan!Waktu pelaksanaan
checkWords()
tergantung pada ukuran papan dan jumlah kata yang tidak dikesampingkan olehcheckWordTriplets()
.The
checkWords()
implementasi di atas adalah paling bodoh versi pertama saya datang dengan. Ini pada dasarnya tidak dioptimalkan sama sekali. Tetapi dibandingkan dengancheckWordTriplets()
itu tidak relevan untuk kinerja total aplikasi, jadi saya tidak khawatir tentang hal itu. Tetapi , jika ukuran papan semakin besar, fungsi ini akan semakin lambat dan lambat dan pada akhirnya akan mulai berarti. Maka, itu perlu dioptimalkan juga.Satu hal yang menyenangkan tentang kode ini adalah fleksibilitasnya:
initializeBoard()
.Ok, tapi saya pikir sekarang posting ini sudah cukup lama. Saya pasti bisa menjawab pertanyaan yang mungkin Anda miliki, tapi mari kita pindah ke komentar.
sumber
ok = possibleTriplets[entry.triplets[t]];
. hmm?entry.letters[i] = (byte) letter - 65;
Ini hanya mengambil nilai ASCII dan mengurangi 65 ("A"). Jika Anda memiliki Umlaut atau huruf kecil dalam kamus Anda, ini akan memberikan nilai lebih dari 31, yang tidak direncanakan oleh pengaturan ukuran alfabet di baris 9. Untuk mendukung huruf lain, Anda harus memperluas baris ini untuk memetakannya ke dalam rentang yang diizinkan oleh ukuran alfabet.Anehnya, tidak ada yang mencoba versi PHP ini.
Ini adalah versi PHP yang berfungsi dari solusi Python John Fouhy.
Meskipun saya mengambil beberapa petunjuk dari jawaban orang lain, ini sebagian besar disalin dari John.
Berikut ini tautan langsung jika Anda ingin mencobanya. Meskipun dibutuhkan ~ 2s di mesin lokal saya, dibutuhkan ~ 5s di server web saya. Dalam kedua kasus, itu tidak terlalu cepat. Meski begitu, itu cukup mengerikan sehingga saya bisa membayangkan waktu dapat dikurangi secara signifikan. Setiap petunjuk tentang bagaimana mencapai itu akan dihargai. Kurangnya tupel PHP membuat koordinat aneh untuk bekerja dengan dan ketidakmampuan saya untuk memahami apa yang sedang terjadi tidak membantu sama sekali.
EDIT : Beberapa perbaikan membuatnya butuh kurang dari 1s secara lokal.
sumber
Tidak tertarik dengan VB? :) Saya tidak bisa menolak. Saya telah memecahkan ini secara berbeda dari banyak solusi yang disajikan di sini.
Waktu saya adalah:
EDIT: Kamus memuat kali di server host web berjalan sekitar 1 hingga 1,5 detik lebih lama dari komputer di rumah saya.
Saya tidak tahu seberapa buruk waktu akan memburuk dengan beban di server.
Saya menulis solusi saya sebagai halaman web di .Net. myvrad.com/boggle
Saya menggunakan kamus yang dirujuk dalam pertanyaan asli.
Surat tidak digunakan kembali dalam satu kata. Hanya 3 kata atau lebih yang ditemukan.
Saya menggunakan hashtabel dari semua awalan dan kata-kata unik alih-alih sebuah trie. Saya tidak tahu tentang trie jadi saya belajar sesuatu di sana. Gagasan untuk membuat daftar awalan kata-kata di samping kata-kata lengkap adalah apa yang akhirnya membuat saya turun ke angka yang terhormat.
Baca komentar kode untuk detail tambahan.
Berikut kodenya:
sumber
Begitu saya melihat pernyataan masalah, saya berpikir "Trie". Tetapi melihat beberapa poster memanfaatkan pendekatan itu, saya mencari pendekatan lain hanya untuk menjadi berbeda. Sayangnya, pendekatan Trie berkinerja lebih baik. Saya menjalankan solusi Kent's Perl di mesin saya dan butuh 0,31 detik untuk berjalan, setelah mengadaptasinya untuk menggunakan file kamus saya. Implementasi perl saya sendiri membutuhkan 0,54 detik untuk berjalan.
Ini pendekatan saya:
Buat hash transisi untuk memodelkan transisi hukum.
Ulangi semua 16 ^ 3 kemungkinan kombinasi tiga huruf.
Kemudian putar semua kata dalam kamus.
Cetak kata-kata yang saya temukan.
Saya mencoba urutan 3 huruf dan 4 huruf, tetapi urutan 4 huruf memperlambat program.
Dalam kode saya, saya menggunakan / usr / share / dict / kata-kata untuk kamus saya. Muncul standar pada MAC OS X dan banyak sistem Unix. Anda dapat menggunakan file lain jika diinginkan. Untuk memecahkan puzzle yang berbeda, cukup ubah variabel @puzzle. Ini akan mudah untuk beradaptasi dengan matriks yang lebih besar. Anda hanya perlu mengubah hash% transisi dan% hash transisi legal.
Kekuatan dari solusi ini adalah bahwa kodenya pendek, dan struktur datanya sederhana.
Ini kode Perl (yang saya tahu terlalu banyak variabel global):
sumber
Saya tahu saya sangat terlambat tapi saya membuat ini beberapa saat yang lalu di PHP - hanya untuk bersenang-senang ...
http://www.lostsockdesign.com.au/sandbox/boggle/index.php?letters=fxieamloewbxastu Ditemukan 75 kata (133 poin) dalam 0,90108 detik
F.........X..I..............E............... A......................................M..............................L............................O............................... E....................W............................B..........................X A..................S..................................................T.................U....
Memberikan beberapa indikasi tentang apa yang sebenarnya dilakukan program - setiap huruf adalah di mana ia mulai melihat melalui pola sementara masing-masing '.' menunjukkan jalan yang telah dicoba untuk diambil. Lebih '.' ada lebih jauh yang telah dicari.
Beri tahu saya jika Anda menginginkan kode ... itu adalah campuran mengerikan antara PHP dan HTML yang tidak pernah dimaksudkan untuk melihat hari jadi saya tidak berani mempostingnya di sini: P
sumber
Saya menghabiskan 3 bulan mengerjakan solusi untuk masalah papan Boggle 10x5 titik padat terbaik.
Masalahnya sekarang dipecahkan dan ditata dengan pengungkapan penuh pada 5 halaman web. Silakan hubungi saya dengan pertanyaan.
Algoritma analisis papan menggunakan tumpukan eksplisit untuk pseudo-rekursif melintasi kotak papan melalui Grafik Kata Acyclic Directed dengan informasi anak langsung, dan mekanisme pelacakan cap waktu. Ini mungkin merupakan struktur data leksikon paling canggih di dunia.
Skema ini mengevaluasi sekitar 10.000 papan yang sangat baik per detik pada quad core. (9500+ poin)
Halaman Web Induk:
DeepSearch.c - http://www.pathcom.com/~vadco/deep.html
Halaman Web Komponen:
Papan Skor Optimal - http://www.pathcom.com/~vadco/binary.html
Struktur Lexicon Lanjutan - http://www.pathcom.com/~vadco/adtdawg.html
Algoritma Analisis Dewan - http://www.pathcom.com/~vadco/guns.html
Pemrosesan Batch Paralel - http://www.pathcom.com/~vadco/parallel.html
- Badan kerja komprehensif ini hanya akan menarik minat seseorang yang menuntut yang terbaik.
sumber
Apakah algoritma pencarian Anda terus mengurangi daftar kata saat pencarian Anda berlanjut?
Misalnya, dalam pencarian di atas hanya ada 13 huruf yang dapat diawali dengan kata-kata Anda (secara efektif berkurang menjadi setengah dari jumlah huruf awal).
Saat Anda menambahkan permutasi huruf lagi akan semakin mengurangi set kata yang tersedia mengurangi pencarian yang diperlukan.
Saya akan mulai dari sana.
sumber
Saya harus lebih memikirkan solusi lengkap, tetapi sebagai optimisasi praktis, saya bertanya-tanya apakah mungkin ada pra-komputasi tabel frekuensi digram dan trigram (kombinasi 2 dan 3 huruf) berdasarkan semua kata-kata dari kamus Anda, dan gunakan ini untuk memprioritaskan pencarian Anda. Saya akan menggunakan huruf awal kata-kata. Jadi jika kamus Anda berisi kata-kata "India", "Air", "Ekstrim", dan "Luar Biasa", maka tabel pra-perhitungan Anda mungkin:
Kemudian cari digram ini dalam urutan kesamaan (EX pertama, lalu WA / IN)
sumber
Pertama, baca bagaimana salah satu perancang bahasa C # memecahkan masalah terkait: http://blogs.msdn.com/ericlippert/archive/2009/02/04/a-nasality-talisman-for-the-sultana-analyst.aspx .
Seperti dia, Anda bisa mulai dengan kamus dan kata-kata yang dikanonalkan dengan membuat kamus dari berbagai huruf yang diurutkan secara alfabetis ke daftar kata yang dapat dieja dari huruf-huruf itu.
Selanjutnya, mulailah membuat kata-kata yang mungkin dari papan tulis dan cari. Saya menduga itu akan membuat Anda cukup jauh, tetapi tentu saja ada lebih banyak trik yang dapat mempercepat.
sumber
Saya sarankan membuat pohon surat berdasarkan kata-kata. Pohon akan terdiri dari struct surat, seperti ini:
Kemudian Anda membangun pohon, dengan setiap kedalaman menambahkan huruf baru. Dengan kata lain, pada tingkat pertama akan ada alfabet; lalu dari masing-masing pohon itu, akan ada 26 entri lagi, dan seterusnya, sampai Anda mengucapkan semua kata. Gantung ke pohon yang diurai ini, dan itu akan membuat semua jawaban yang mungkin lebih cepat untuk mencari.
Dengan pohon yang diuraikan ini, Anda dapat dengan cepat menemukan solusi. Inilah pseudo-code:
Ini bisa dipercepat dengan sedikit pemrograman dinamis. Misalnya, dalam sampel Anda, kedua 'A' adalah di sebelah 'E' dan 'W', yang (dari titik mereka memukulnya) akan identik. Saya tidak punya cukup waktu untuk benar-benar menguraikan kode untuk ini, tetapi saya pikir Anda dapat mengumpulkan idenya.
Juga, saya yakin Anda akan menemukan solusi lain jika Anda Google untuk "pemecah Boggle".
sumber
Hanya untuk bersenang-senang, saya menerapkannya di bash. Ini tidak super cepat, tetapi masuk akal.
http://dev.xkyle.com/bashboggle/
sumber
Lucu sekali. Saya hampir memposting pertanyaan yang sama beberapa hari yang lalu karena permainan yang sama! Namun saya tidak melakukannya karena hanya mencari google untuk boggle solver python dan mendapatkan semua jawaban yang saya inginkan.
sumber
Saya menyadari waktu pertanyaan ini telah datang dan pergi, tetapi karena saya sendiri sedang mengerjakan solver, dan menemukan ini sambil mencari-cari di sekitar, saya pikir saya harus memposting referensi ke saya karena tampaknya sedikit berbeda dari beberapa yang lain.
Saya memilih untuk pergi dengan array datar untuk papan permainan, dan untuk melakukan perburuan rekursif dari setiap huruf di papan, melintasi dari tetangga yang valid ke tetangga yang valid, memperpanjang perburuan jika daftar huruf saat ini jika awalan yang valid dalam indeks. Sementara melintasi gagasan kata saat ini adalah daftar indeks ke papan tulis, bukan huruf yang membentuk kata. Saat memeriksa indeks, indeks diterjemahkan ke huruf dan pemeriksaan selesai.
Indeks adalah kamus brute force yang sedikit mirip trie, tetapi memungkinkan untuk query Pythonic dari indeks. Jika kata 'cat' dan 'cater' ada dalam daftar, Anda akan mendapatkan ini di kamus:
Jadi jika current_word adalah 'ca' Anda tahu bahwa itu adalah awalan yang valid karena
'ca' in d
mengembalikan True (jadi teruskan board traversal). Dan jika current_word adalah 'cat' maka Anda tahu bahwa itu adalah kata yang valid karena merupakan awalan dan valid'cat' in d['cat']
mengembalikan True juga.Jika merasa seperti ini diperbolehkan untuk beberapa kode yang dapat dibaca yang sepertinya tidak terlalu lambat. Seperti orang lain, pengeluaran dalam sistem ini adalah membaca / membangun indeks. Memecahkan papan cukup berisik.
Kode ini ada di http://gist.github.com/268079 . Itu sengaja vertikal dan naif dengan banyak pengecekan validitas eksplisit karena saya ingin memahami masalahnya tanpa merapikannya dengan sekelompok sihir atau ketidakjelasan.
sumber
Saya menulis solver saya di C ++. Saya menerapkan struktur pohon kustom. Saya tidak yakin itu bisa dianggap sebagai trie tetapi mirip. Setiap node memiliki 26 cabang, 1 untuk setiap huruf alfabet. Saya melintasi cabang-cabang papan boggle secara paralel dengan cabang-cabang kamus saya. Jika cabang tidak ada di kamus, saya berhenti mencari di papan Boggle. Saya mengubah semua huruf di papan tulis menjadi int. Jadi 'A' = 0. Karena ini hanya array, pencarian selalu O (1). Setiap node menyimpan jika ia menyelesaikan satu kata dan berapa banyak kata yang ada pada anak-anaknya. Pohon itu dipangkas karena kata-kata ditemukan berkurang berulang kali mencari kata yang sama. Saya percaya pemangkasan juga O (1).
CPU: Pentium SU2700 1.3GHz
RAM: 3gb
Memuat kamus 178.590 kata dalam <1 detik.
Memecahkan Boggle 100x100 (boggle.txt) dalam 4 detik. ~ 44.000 kata ditemukan.
Memecahkan Boggle 4x4 terlalu cepat untuk memberikan tolok ukur yang berarti. :)
Fast Boggle Solver GitHub Repo
sumber
Diberi papan Boggle dengan kolom N rows dan M, mari kita asumsikan yang berikut:
Berdasarkan asumsi ini, kompleksitas dari solusi ini adalah O (N * M).
Saya pikir membandingkan waktu berjalan untuk papan contoh yang satu ini dalam banyak hal tidak tepat tetapi, demi kelengkapan, solusi ini selesai dalam <0,2 detik pada MacBook Pro modern saya.
Solusi ini akan menemukan semua jalur yang mungkin untuk setiap kata dalam korpus.
sumber
Solusi ini juga memberikan arahan untuk mencari di papan yang diberikan
Algo:
Keluaran:
Kode:
sumber
Saya telah mengimplementasikan solusi di OCaml . Ini pra-kompilasi kamus sebagai trie, dan menggunakan frekuensi urutan dua huruf untuk menghilangkan tepi yang tidak pernah bisa muncul dalam sebuah kata untuk lebih mempercepat pemrosesan.
Ini memecahkan papan contoh Anda dalam 0,35 ms (dengan tambahan waktu 6ms start-up yang sebagian besar terkait dengan memuat trie ke dalam memori).
Solusi yang ditemukan:
sumber
/usr/share/dict
kamus lokal saya , dan beberapa kata memang hilang (seperti EMBOLE).Solusi JavaScript Node.JS. Hitung semua 100 kata unik dalam waktu kurang dari satu detik yang termasuk membaca file kamus (MBA 2012).
Keluaran:
["FAM", "TUX", "TUB", "FAE", "ELI", "ELM", "ELB", "TWA", "TWA", "SAW", "AMI", "AMI", "SWA" , "SWA", "AME", "SEA", "SEW", "AES", "AWL", "AWE", "AWA", "AWA", "MIX", "MILX", "MIL", "AST", " ASE "," MAX "," MAE "," MAW "," MEW "," AWE "," MES "," AWL "," LIE "," LIM "," AWA "," AA "," AES "," TAPI " , "BLO", "WAS", "WAE", "WEA", "LEI", "LEO", "LOB", "LOX", "WEM", "OIL", "OLM", "OLM", "WEA", " WAE "," WAX "," WAF ","MILO", "EAST", "WAME", "TWAS", "TWAE", "EMIL", "WEAM", "OIME", "AXIL", "AXIL", "WEST", "TWAE", "LIMB", "WASE "," WAST "," BLEO "," STUB "," BOIL "," BOLE "," LIME "," SAWT "," LIMA "," MESA "," MEWL "," AXLE "," AXLE "," FAME ", "ASEM", "MILE", "AMIL", "SEAX", "SEAM", "SEMI", "SWAM", "AMBO", "AMLI", "AXILE", "AMBLE", "SWAMI", "AWEST "," AWEST "," LIMAX "," LIMES "," LIMBU "," LIMBO "," EMBOX "," SEMBLE "," EMBOLE "," WAMBLE "," FAMBLE "]TIMUR "," WAME "," TWAS "," TWAE "," EMIL "," WEAM "," OIME "," AXIL "," WEST "," TWAE "," LIMB "," WASE "," WASE "," WAST " , "BLEO", "STUB", "BOIL", "BOLE", "LIME", "SAWT", "LIMA", "MESA", "MEWL", "AXLE", "AXLE", "FAME", "ASEM", " MILE "," AMIL "," SEAX "," SEAM "," SEMI "," SWAM "," AMBO "," AMLI "," AXILE "," AMBLE "," SWAMI "," AWEST "," AWEST "," AWEST " , "LIMAX", "LIMES", "LIMBU", "LIMBO", "EMBOX", "SEMBLE", "EMBOLE", "WAMBLE", "FAMBLE"]TIMUR "," WAME "," TWAS "," TWAE "," EMIL "," WEAM "," OIME "," AXIL "," WEST "," TWAE "," LIMB "," WASE "," WASE "," WAST " , "BLEO", "STUB", "BOIL", "BOLE", "LIME", "SAWT", "LIMA", "MESA", "MEWL", "AXLE", "AXLE", "FAME", "ASEM", " MILE "," AMIL "," SEAX "," SEAM "," SEMI "," SWAM "," AMBO "," AMLI "," AXILE "," AMBLE "," SWAMI "," AWEST "," AWEST "," AWEST " , "LIMAX", "LIMES", "LIMBU", "LIMBO", "EMBOX", "SEMBLE", "EMBOLE", "WAMBLE", "FAMBLE"]"TWAE", "EMIL", "WEAM", "OIME", "AXIL", "WEST", "TWAE", "LIMB", "WASE", "WAST", "BLEO", "STUB", "STIL", "BOIL" "," BOLE "," LIME "," SAWT "," LIMA "," MESA "," MEWL "," AXLE "," FAME "," ASEM "," MILE "," AMIL "," AMIL "," SEAX ", "SEAM", "SEMI", "SWAM", "AMBO", "AMLI", "AXILE", "AMBLE", "SWAMI", "AWEST", "AWEST", "LIMAX", "LIMES", "LIMBU" "," LIMBO "," EMBOX "," SEMBLE "," EMBOLE "," WAMBLE "," FAMBLE "]"TWAE", "EMIL", "WEAM", "OIME", "AXIL", "WEST", "TWAE", "LIMB", "WASE", "WAST", "BLEO", "STUB", "STIL", "BOIL" "," BOLE "," LIME "," SAWT "," LIMA "," MESA "," MEWL "," AXLE "," FAME "," ASEM "," MILE "," AMIL "," AMIL "," SEAX ", "SEAM", "SEMI", "SWAM", "AMBO", "AMLI", "AXILE", "AMBLE", "SWAMI", "AWEST", "AWEST", "LIMAX", "LIMES", "LIMBU" "," LIMBO "," EMBOX "," SEMBLE "," EMBOLE "," WAMBLE "," FAMBLE "]"WEST", "TWAE", "LIMB", "WASE", "WAST", "BLEO", "STUB", "BOIL", "BOLE", "LIME", "SAWT", "LIMA", "MESA "," MEWL "," AXLE "," FAME "," ASEM "," MILE "," AMIL "," SEAX "," SEAM "," SEAM "," SEMI "," SWAM "," AMBO "," AMLI ", "AXILE", "AMBLE", "SWAMI", "AWEST", "AWEST", "LIMAX", "LIMES", "LIMBU", "LIMBO", "EMBOX", "SEMBLE", "EMBOLE", "WAMBLE "," FAMBLE "]"WEST", "TWAE", "LIMB", "WASE", "WAST", "BLEO", "STUB", "BOIL", "BOLE", "LIME", "SAWT", "LIMA", "MESA "," MEWL "," AXLE "," FAME "," ASEM "," MILE "," AMIL "," SEAX "," SEAM "," SEAM "," SEMI "," SWAM "," AMBO "," AMLI ", "AXILE", "AMBLE", "SWAMI", "AWEST", "AWEST", "LIMAX", "LIMES", "LIMBU", "LIMBO", "EMBOX", "SEMBLE", "EMBOLE", "WAMBLE "," FAMBLE "]SAWT "," LIMA "," MESA "," MEWL "," AXLE "," FAME "," ASEM "," MILE "," AMIL "," SEAX "," SEAM "," SEAM "," SEMI "," SWAM " , "AMBO", "AMLI", "AXILE", "AMBLE", "SWAMI", "AWEST", "AWEST", "LIMAX", "LIMES", "LIMBU", "LIMBO", "EMBOX", " SEMBLE "," EMBOLE "," WAMBLE "," FAMBLE "]SAWT "," LIMA "," MESA "," MEWL "," AXLE "," FAME "," ASEM "," MILE "," AMIL "," SEAX "," SEAM "," SEAM "," SEMI "," SWAM " , "AMBO", "AMLI", "AXILE", "AMBLE", "SWAMI", "AWEST", "AWEST", "LIMAX", "LIMES", "LIMBU", "LIMBO", "EMBOX", " SEMBLE "," EMBOLE "," WAMBLE "," FAMBLE "]LIMAX "," LIMES "," LIMBU "," LIMBO "," EMBOX "," SEMBLE "," EMBOLE "," WAMBLE "," FAMBLE "]LIMAX "," LIMES "," LIMBU "," LIMBO "," EMBOX "," SEMBLE "," EMBOLE "," WAMBLE "," FAMBLE "]
Kode:
sumber
Jadi saya ingin menambahkan cara lain penyelesaian PHP, karena semua orang menyukai PHP. Ada sedikit refactoring yang ingin saya lakukan, seperti menggunakan kecocokan regexpression terhadap file kamus, tapi saat ini saya hanya memuat seluruh file kamus ke dalam wordList.
Saya melakukan ini menggunakan ide daftar tertaut. Setiap Node memiliki nilai karakter, nilai lokasi, dan penunjuk berikutnya.
Nilai lokasi adalah bagaimana saya mengetahui jika dua node terhubung.
Jadi menggunakan kisi itu, saya tahu dua node terhubung jika lokasi node pertama sama dengan lokasi node kedua +/- 1 untuk baris yang sama, +/- 9, 10, 11 untuk baris di atas dan di bawah.
Saya menggunakan rekursi untuk pencarian utama. Dibutuhkan satu kata dari wordList, menemukan semua titik awal yang mungkin, dan kemudian secara rekursif menemukan koneksi berikutnya yang mungkin, mengingat bahwa itu tidak dapat pergi ke lokasi yang sudah digunakan (itulah sebabnya saya menambahkan $ notInLoc).
Ngomong-ngomong, saya tahu ini memerlukan beberapa refactoring, dan akan senang mendengar pemikiran tentang cara membuatnya lebih bersih, tetapi itu menghasilkan hasil yang benar berdasarkan pada file kamus yang saya gunakan. Bergantung pada jumlah vokal dan kombinasi di papan tulis, dibutuhkan sekitar 3 hingga 6 detik. Saya tahu bahwa setelah saya preg_match hasil kamus, itu akan berkurang secara signifikan.
sumber
Saya tahu saya benar-benar terlambat di pesta tetapi saya telah menerapkan, sebagai latihan pengkodean, pemecah boggle dalam beberapa bahasa pemrograman (C ++, Java, Go, C #, Python, Ruby, JavaScript, Julia, Lua, PHP, Perl) dan Saya pikir seseorang mungkin tertarik pada hal itu, jadi saya meninggalkan tautan di sini: https://github.com/AmokHuginnsson/boggle-solvers
sumber
Berikut adalah solusinya Menggunakan kata-kata yang ditentukan sebelumnya di NLTK toolkit NLTK memiliki paket nltk.corpus di mana kami memiliki paket yang disebut kata-kata dan berisi lebih dari 2Lakh kata-kata bahasa Inggris yang dapat Anda gunakan dengan mudah ke dalam program Anda.
Setelah membuat matriks Anda, ubah menjadi array karakter dan lakukan kode ini
Keluaran:
Saya harap kamu mengerti.
sumber
Berikut ini adalah implementasi java saya: https://github.com/zouzhile/interview/blob/master/src/com/interview/algorithms/tree/BoggleSolver.java
Membangun trie membutuhkan waktu 0 jam, 0 menit, 1 detik, 532 milidetik
Pencarian kata memakan waktu 0 jam, 0 menit, 0 detik, 92 milidetik
Catatan: Saya menggunakan kamus dan matriks karakter di awal utas ini. Kode dijalankan di MacBookPro saya, di bawah ini adalah beberapa informasi tentang mesin.
Nama Model: MacBook Pro
Identifier Model: MacBookPro8, 1
Nama Prosesor: Intel Core i5
Kecepatan Prosesor: 2,3 GHz
Jumlah Prosesor: 1
Jumlah
Inti : 2 L2 Cache (per inti): 256 KB
L3 Cache: 3 MB
Memori: 4 GB
Versi Boot ROM: MBP81.0047.B0E
Versi SMC (sistem): 1.68f96
sumber
Saya memecahkan ini juga, dengan Java. Implementasi saya panjangnya 269 baris dan cukup mudah digunakan. Pertama, Anda perlu membuat instance baru dari kelas Boggler dan kemudian memanggil fungsi penyelesaian dengan grid sebagai parameter. Diperlukan sekitar 100 ms untuk memuat kamus 50.000 kata di komputer saya dan ia menemukan kata-kata itu dalam sekitar 10-20 ms. Kata-kata yang ditemukan disimpan dalam ArrayList
foundWords
,.sumber
Saya memecahkan masalah ini di c. Dibutuhkan sekitar 48 ms untuk berjalan di mesin saya (dengan sekitar 98% dari waktu yang dihabiskan memuat kamus dari disk dan membuat trie). Kamusnya adalah / usr / share / dict / american-english yang memiliki 62886 kata.
Kode sumber
sumber
Saya menyelesaikan ini dengan sempurna dan sangat cepat. Saya memasukkannya ke dalam aplikasi android. Lihat video di tautan play store untuk melihatnya beraksi.
Word Cheats adalah sebuah aplikasi yang "memecahkan" setiap permainan kata gaya matriks. Aplikasi ini dibuat untuk membantu saya melakukan cheat di word scrambler. Ini dapat digunakan untuk pencarian kata, ruzzle, kata-kata, pencari kata, crack kata, merusakkan, dan banyak lagi!
Itu dapat dilihat di sini https://play.google.com/store/apps/details?id=com.harris.wordcracker
Lihat aplikasi dalam aksi di video https://www.youtube.com/watch?v=DL2974WmNAI
sumber