Objektif
Diberikan daftar kata sandi tiga kata, pecahkan semuanya. Setiap kali Anda menebak, Anda akan diberi petunjuk dalam gaya Mastermind , menggambarkan berapa banyak karakter yang cocok dengan kata sandi, dan berapa banyak yang berada di posisi yang benar. Tujuannya adalah untuk meminimalkan jumlah tebakan dari semua kasus uji.
Frasa sandi
Dari daftar kata default sistem saya, saya secara acak memilih 10.000 kata yang berbeda untuk membuat kamus untuk tantangan ini. Semua kata a-z
hanya terdiri dari . Kamus ini dapat ditemukan di sini ( mentah ).
Dari kamus ini, saya menghasilkan 1000 frasa sandi yang masing-masing terdiri dari tiga kata yang dipisahkan ruang secara acak ( apple jacks fever
, misalnya). Setiap kata dapat digunakan kembali dalam setiap frasa sandi ( hungry hungry hippos
). Anda dapat menemukan daftar frasa sandi di sini ( mentah ), dengan satu frasa per baris.
Program Anda dapat menggunakan / menganalisis file kamus seperti yang Anda inginkan. Anda tidak dapat menganalisis frasa sandi untuk mengoptimalkan untuk daftar khusus ini. Algoritme Anda harus tetap berfungsi mengingat daftar frasa yang berbeda
Menebak
Untuk menebak, Anda mengirimkan string ke pemeriksa. Seharusnya mengembalikan hanya :
- Jumlah karakter dalam string Anda juga di frasa sandi ( tidak pada posisi yang benar)
- Jumlah karakter di posisi yang benar
Jika string Anda sangat cocok, string tersebut dapat menampilkan sesuatu yang menunjukkan (tambang menggunakan -1
nilai pertama).
Misalnya, jika frasa sandi adalah the big cat
dan Anda tebak tiger baby mauling
, pemeriksa harus kembali 7,1
. 7 karakter ( ige<space>ba<space>
) berada di kedua string tetapi posisi berbeda, dan 1 ( t
) berada di posisi yang sama di keduanya. Perhatikan bahwa spasi dihitung.
Saya telah menulis contoh (baca: tidak dioptimalkan) fungsi di Jawa, tetapi jangan ragu untuk menulis sendiri selama hanya memberikan informasi yang diperlukan.
int[] guess(String in){
int chars=0, positions=0;
String pw = currentPassword; // set elsewhere, contains current pass
for(int i=0;i<in.length()&&i<pw.length();i++){
if(in.charAt(i)==pw.charAt(i))
positions++;
}
if(positions == pw.length() && pw.length()==in.length())
return new int[]{-1,positions};
for(int i=0;i<in.length();i++){
String c = String.valueOf(in.charAt(i));
if(pw.contains(c)){
pw = pw.replaceFirst(c, "");
chars++;
}
}
chars -= positions;
return new int[]{chars,positions};
}
Mencetak gol
Skor Anda hanyalah jumlah tebakan yang Anda kirim ke pemeriksa (menghitung final, yang benar) untuk semua frasa uji. Skor terendah menang.
Anda harus memecahkan semua frasa dalam daftar. Jika program Anda gagal pada salah satu dari mereka, itu tidak valid.
Program Anda harus bersifat deterministik. Jika dijalankan dua kali pada kumpulan frasa sandi yang sama, ini harus mengembalikan hasil yang sama.
Dalam kasus seri pertama, saya akan menjalankan entri terikat di komputer saya masing-masing empat kali, dan waktu rata-rata terendah untuk menyelesaikan semua 1.000 kasus menang. Komputer saya menjalankan Ubuntu 14.04, dengan i7-3770K dan 16GB semacam RAM, dalam kasus yang membuat perbedaan pada program Anda. Untuk alasan itu, dan untuk memudahkan pengujian, jawaban Anda harus dalam bahasa yang memiliki kompiler / juru bahasa yang dapat diunduh dari web gratis (tidak termasuk uji coba gratis) dan tidak memerlukan pendaftaran / pendaftaran.
Judul diadaptasi dari XKCD
sumber
9 0
. Ini mungkin memakan waktu cukup lama: PJawaban:
Scala 9146 (min 7, maks 15, rata-rata 9,15) waktu: 2000 detik
Seperti banyak entri saya mulai dengan mendapatkan total panjang, kemudian menemukan spasi, mendapatkan informasi lebih banyak, mengurangi ke kandidat yang tersisa dan kemudian menebak frasa.
Terinspirasi oleh komik xkcd asli, saya mencoba menerapkan pemahaman mendasar saya tentang teori informasi. Ada satu triliun frase yang mungkin atau hanya di bawah 40 bit entropi. Saya menetapkan sasaran di bawah 10 tebakan per frasa uji, yang berarti kita harus belajar rata-rata hampir 5 bit per kueri (karena yang terakhir tidak berguna). Dengan setiap tebakan kami mendapatkan kembali dua angka dan secara kasar berbicara tentang kisaran potensial yang lebih besar dari angka-angka itu, semakin banyak yang kami harapkan untuk dipelajari.
Untuk menyederhanakan logika, saya menggunakan setiap kueri secara efektif dua pertanyaan terpisah sehingga setiap string tebakan adalah dua bagian, sisi kiri tertarik pada jumlah posisi yang benar (pasak hitam di dalang) dan sisi kanan tertarik pada jumlah karakter yang benar ( pasak total). Ini adalah permainan khas:
Menebak spasi
Setiap ruang menebak dapat mengembalikan paling banyak 2 pasak hitam; Saya mencoba membuat tebakan untuk mengembalikan 0,1, dan 2 pasak dengan probabilitas 1 / 4,1 / 2, dan 1/4 masing-masing. Saya percaya ini adalah yang terbaik yang dapat Anda lakukan untuk 1,5bits informasi yang diharapkan. Saya memilih string yang bergantian untuk tebakan pertama diikuti oleh tebakan yang dibuat secara acak, meskipun ternyata biasanya bermanfaat untuk mulai menebak pada percobaan kedua atau ketiga, karena kita tahu frekuensi panjang kata.
Mempelajari himpunan karakter
Untuk tebakan di sebelah kanan, saya memilih set karakter acak (selalu 2 dari huruf / huruf / huruf) sehingga jumlah yang diharapkan dikembalikan setengah dari panjang frasa. Varian yang lebih tinggi berarti lebih banyak informasi dan dari halaman wikipedia pada distribusi binomial, saya memperkirakan sekitar 3,5 bit per kueri (setidaknya untuk beberapa pertama sebelum informasi menjadi redundan). Setelah spasi diketahui, saya menggunakan string acak dari huruf yang paling umum di sisi kiri, dipilih agar tidak bertentangan dengan sisi kanan.
Menggabungkan kandidat yang tersisa
Game ini adalah penghitungan kecepatan / kueri efisiensi tradeoff dan penghitungan kandidat yang tersisa dapat memakan waktu sangat lama tanpa informasi terstruktur seperti karakter tertentu. Saya mengoptimalkan bagian ini dengan terutama mengumpulkan informasi yang tidak tetap dengan urutan kata, yang memungkinkan saya menghitung jumlah set karakter untuk setiap kata individual dan membandingkannya dengan jumlah yang dipelajari dari query. Saya mengemas penghitungan ini menjadi bilangan bulat panjang, menggunakan komparator dan penambah kesetaraan mesin untuk menguji semua jumlah karakter saya di parralel. Ini adalah kemenangan besar. Saya dapat mengemas hingga 9 hitungan di Long, tetapi saya menemukan mengumpulkan informasi tambahan tidak layak dan diselesaikan pada 6 sampai 7.
Setelah sisa kandidat diketahui, jika set cukup kecil saya memilih satu dengan log yang diharapkan terendah dari kandidat yang tersisa. Jika set cukup besar untuk membuat ini memakan waktu, saya memilih dari set sampel kecil.
Terimakasih semuanya. Ini adalah permainan yang menyenangkan dan membujuk saya untuk mendaftar ke situs.
Pembaruan: Kode yang dibersihkan untuk kesederhanaan dan keterbacaan, dengan sedikit perubahan pada algoritma, menghasilkan skor yang ditingkatkan.
Skor asli: 9447 (min 7, maks 13, rata-rata 9,45) waktu: 1876 detik
Kode baru adalah 278 baris Scala, di bawah ini
sumber
C - total: 37171, min: 24, maks: 55, waktu: sekitar 10 detik
Saya meminjam ide Ray untuk menemukan panjang setiap kata dengan menebak spasi, kecuali saya melakukan pencarian biner daripada linear, yang menyelamatkan saya dari banyak tebakan.
Setelah saya menentukan panjang kata, saya kira dengan kata pertama yang cocok dengan panjangnya dan saya mencatat jumlah posisi yang benar. Kemudian saya memilih kata pertama dari himpunan semua kata yang memiliki jumlah posisi yang sama dengan tebakan pertama saya sebagai kata misteri. Untuk tebakan ketiga saya, saya memilih kata pertama dari himpunan semua kata yang memiliki jumlah posisi yang sama dengan tebakan pertama saya sebagai kata misteri dan jumlah posisi yang sama dengan tebakan kedua saya dengan kata misteri, dll.
Dengan menggunakan metode ini saya dapat menebak setiap kata, satu per satu, dalam sekitar 5-10 tebakan. Jelas kata ketiga yang harus saya lakukan sedikit berbeda karena saya tidak tahu panjangnya, tetapi metodenya mirip. Saya menggunakan file yang berisi matriks dari jumlah posisi yang setiap kata bagikan secara umum yang telah saya perhitungan sebelumnya. Mayoritas run-time terjadi saat memuat data yang dihitung sebelumnya. Anda dapat mengunduh semuanya di sini .
Sangat menyenangkan menontonnya dengan kata-kata:
sumber
Python 3.4 - min: 21, maks: 29, total: 25146, waktu: 20 menit
min: 30, maks: 235, total: 41636, waktu: 4 menitMemperbarui:
Metode ini tidak menggunakan keacakan sehingga skor tidak akan berubah.
Pertama menggunakan tebakan seperti berikut untuk menemukan spasi pertama dan kedua dalam jawabannya.
Kemudian, ia menghitung kemunculan setiap huruf dengan menebak
aaaaa...
,bbbbb....
... Setelah ini biayanya sekitar 40 langkah. Faktanya, kita tidak perlu mencoba semua surat dan kita dapat mencobanya dalam urutan arbiter. Dalam kebanyakan kasus, mencoba sekitar 20 huruf sudah cukup. Di sini saya memilih 21.Sekarang ia tahu panjang kata pertama dan kata kedua sehingga bisa menyaring daftar kandidat untuk dua kata ini. Biasanya akan ada sekitar 100 kandidat yang tersisa untuk masing-masing.
Kemudian hanya menyebutkan kata pertama dan kedua. Setelah dua kata pertama disebutkan, kita dapat menyimpulkan semua kata ketiga yang valid karena kita tahu jumlah karakternya.
Untuk mengoptimalkan kecepatan, saya menggunakan
concurrent.futures
untuk menambahkan multiprosesing ke program. Jadi Anda perlu Python 3 untuk menjalankannya dan saya mengujinya dengan Python 3.4 pada kotak Linux saya. Anda juga harus menginstalnumpy
.sumber
Java 13.923 (min: 11, maks: 17)
Pembaruan: peningkatan skor (pecahkan <14 / crack avg!), Kode baru
Pos asli
Saya telah memutuskan untuk sepenuhnya berfokus pada jumlah tebakan daripada kinerja (mengingat aturan). Ini menghasilkan program pintar yang sangat lambat.
Alih-alih mencuri dari program yang dikenal saya memutuskan untuk menulis semuanya dari awal, tetapi ternyata beberapa / kebanyakan ide adalah sama.
Algoritma
Beginilah cara kerja saya:
Contoh tebakan
Ini adalah contoh aktual:
Karena kode saya tidak pernah benar-benar fokus pada satu kata dan hanya mengumpulkan informasi tentang frasa lengkap, itu harus menghasilkan banyak frasa sehingga sangat lambat.
Kode
Dan akhirnya di sini adalah kode (jelek), jangan coba-coba memahaminya, maaf:
sumber
Java -
18.708 Permintaan; 2,4 detik11,077 Pertanyaan; 125 mnt.Min: 8, Maks: 13, Kueri Efektif: 10.095
Saya menghabiskan waktu terlalu lama untuk ini. : P
Kode tersedia di http://pastebin.com/7n9a50NMRev 1. tersedia di http://pastebin.com/PSXU2bgaRev 2. tersedia di http://pastebin.com/gRJjpbbu
Revisi kedua saya. Saya berharap untuk memecahkan rintangan 11K untuk memenangkan hadiah, tapi saya kehabisan waktu untuk mengoptimalkan binatang ini.
Ini beroperasi pada prinsip yang sepenuhnya terpisah dari dua versi sebelumnya (dan memakan waktu sekitar 3.500 kali lebih lama untuk dijalankan). Prinsip umum adalah menggunakan ruang dan genap / karakter ganjil untuk mengurangi daftar kandidat menjadi ukuran yang dapat dikelola (biasanya antara 2-8 juta), dan kemudian melakukan kueri berulang dengan kekuatan diskriminasi maksimum (yaitu distribusi keluaran yang telah memaksimalkan entropi).
Bukan kecepatan tetapi memori adalah batasan utama. VM Java saya tidak akan membiarkan saya memesan tumpukan lebih dari 1.200 MB untuk alasan yang tidak jelas (mungkin Windows 7), dan saya menyetel parameter untuk memberi saya solusi terbaik yang tidak menghabiskan batas ini. Ini mengganggu saya bahwa menjalankan yang tepat dengan parameter yang tepat akan merusak 11K tanpa peningkatan waktu eksekusi yang berarti. Saya membutuhkan komputer baru. : P
Yang paling mengganggu saya adalah bahwa 982 pertanyaan dalam implementasi ini adalah pertanyaan "validasi" yang tidak berguna. Mereka tidak memiliki tujuan selain untuk memenuhi aturan bahwa oracle harus mengembalikan nilai "Anda mendapatkannya" di beberapa titik, meskipun dalam implementasi saya jawaban yang benar telah dikurangkan dengan pasti sebelum kueri ini dalam 98,2% kasus. Sebagian besar kiriman sub-11K lainnya mengandalkan teknik penyaringan yang menggunakan string kandidat sebagai string kueri dan karenanya tidak mengalami penalti yang sama.
Untuk alasan ini, meskipun jumlah permintaan resmi saya adalah 11.077 (kurang dari pemimpin, asalkan kode mereka terbukti sesuai, benar-untuk-spek, dll.), Saya dengan berani menyatakan bahwa kode saya membuat 10.095 kueri efektif , artinya hanya 10.095 kueri yang sebenarnya perlu untuk menentukan semua frasa lulus dengan kepastian 100%. Saya tidak yakin implementasi lainnya akan cocok dengan itu, maka saya akan menganggapnya sebagai kemenangan saya. ;)
sumber
.
."perpetually exhausting pool"
Java - min: 22, maks: 41, total: 28353, waktu: 4 detik
Program menebak kata sandi dalam 3 langkah:
Itu juga menangani satu set "karakter buruk" yang mengembalikan hasil nol dalam pencarian, dan satu set "karakter baik" yang ditempatkan di tempat lain di frasa sandi.
Di bawah ini adalah contoh nilai yang dikirimkan secara berturut-turut untuk menebak, Anda dapat melihat 3 langkah:
Kode:
sumber
PYTHON 2,7 - 156821 menebak, 0,6 detik
Saya mencari kecepatan daripada jumlah tebakan terendah, meskipun saya pikir jumlah tebakan saya masih lebih rendah daripada misalnya serangan kamus langsung. Saya tidak menghitung jumlah huruf dalam kata sandi tetapi di tempat yang salah, karena metode saya tidak menggunakannya, tetapi jika Anda merasa ini memberi saya keuntungan yang tidak adil, saya akan menerapkannya. Saya cukup mulai dengan string tebakan kosong, dan tambahkan akhiran karakter tunggal di atasnya yang menambah daftar karakter saya, memeriksa hasil 'centang' untuk melihat apakah jumlah karakter yang benar sama dengan panjang tebakan. Misalnya, jika kata sandi 'buruk', saya kira:
a, b
Sebuah
a, b, c, d
Saya juga mencoba mengurutkan huruf berdasarkan frekuensi huruf bahasa Inggris, yang mencukur sekitar 35% dari jumlah tebakan, dan juga waktu. Saya memecahkan semua kata sandi dalam 0,82 detik. Statistik dicetak di akhir.
EDIT: Menghapus satu nyasar +1 dan -1 dari dua sementara loop dari iterasi pengujian sebelumnya, juga menambahkan statistik tambahan untuk tebakan paling sedikit dan tebakan terbanyak untuk satu kata sandi.
EDIT2: menambahkan tabel pencarian untuk huruf 'berikutnya' yang paling umum, per huruf. Kecepatan meningkat pesat dan jumlah tebakan menurun
sumber
C ++ -
1138310989 Cocok!Memperbarui
Memperbaiki kebocoran memori, dan menghapus 1 upaya lagi untuk mengurangi ukuran kamus kata individual. Memakan waktu sekitar 50 menit pada mac pro saya. Kode yang diperbarui ada di github.
Saya beralih ke strategi pencocokan frasa, dan menyusun ulang kode, dan memperbaruinya di github https://github.com/snjyjn/mastermind
Dengan pencocokan berbasis Frasa, kami berupaya sebanyak 11383! Itu mahal dalam hal menghitung! Saya juga tidak suka struktur kode! Dan masih jauh di belakang yang lain :-(
Inilah yang saya lakukan:
Secara paralel, tambahkan string uji 'dibuat' untuk mendapatkan informasi lebih lanjut tentang frasa. Strategi saat ini adalah sebagai berikut:
Sebuah. Gunakan karakter sesuai frekuensi mereka dalam kamus.
b. Kita sudah tahu hitung untuk yang paling sering
c. String Tes 1 = 5 karakter berikutnya. Ini memberi kita hitungan karakter ini dalam frasa.
d. 3 string tes berikutnya = masing-masing 5 karakter berikutnya, mencakup total 20 karakter dalam 4 upaya sebagai tambahan dari 1 karakter pertama. Ini memberi kami hitungan untuk 5 karakter terakhir ini juga. set dengan 0 hitungan sangat bagus untuk mengurangi ukuran kamus!
e. Sekarang untuk pengujian sebelumnya yang memiliki jumlah terkecil, bukan nol, pisahkan string menjadi 2, dan gunakan 1 untuk pengujian. Hitungan yang dihasilkan memberi tahu kita tentang pemisahan lainnya juga.
f. Sekarang ulangi tes dengan karakter (berbasis 0),
Setelah spasi diidentifikasi, gunakan kendala sejauh ini (sebanyak mungkin tes yang bisa dilakukan dalam upaya ini) untuk mengurangi ukuran kamus. Juga buat 3 sub kamus, 1 untuk setiap kata.
Sekarang lakukan beberapa tebakan untuk setiap kata, dan ujilah.
Gunakan hasil ini untuk mengurangi ukuran kamus individu.
Hiasi ini dengan karakter uji juga (setelah panjang) untuk mendapatkan lebih banyak kendala pada frasa! Saya menggunakan 3 tebakan di versi final - 2 untuk kata 1, dan 1 untuk kata 2
Ini membawa kamus ke ukuran yang dapat dikelola. Lakukan lintas produk, terapkan semua kendala seperti sebelumnya untuk membuat kamus frasa.
Pecahkan kamus frasa melalui serangkaian tebakan - kali ini menggunakan informasi kecocokan posisi dan karakter.
Pendekatan ini membawa kita ke bawah upaya 11383:
Posting Sebelumnya
Saya telah membersihkan kode, dan mengunggahnya ke https://github.com/snjyjn/mastermind Dalam prosesnya, saya memperbaikinya, dan masih punya 1 ide lagi untuk dicoba. Ada satu perbedaan besar dari apa yang saya lakukan kemarin:
Statistik sekarang terlihat seperti:
Pos Asli
Permintaan maaf untuk 'jawaban', tapi saya baru saja membuat akun, dan tidak memiliki reputasi yang cukup untuk menambahkan komentar.
Saya memiliki program c ++, yang memakan waktu sekitar 6,5 detik, dan 24107 upaya pencocokan. Ini adalah sekitar 1400 baris c ++. Saya tidak senang dengan kualitas kode, dan akan membersihkannya sebelum saya memasangnya di lain hari. Tetapi demi kepentingan komunitas dan berkontribusi dalam diskusi, inilah yang saya lakukan:
Baca kamus, dapatkan beberapa info dasar tentangnya - panjang kata minimum, frekuensi karakter, dll.
Identifikasi spasi pertama - Ini memiliki 2 bagian, yang pertama adalah seperangkat kueri yang terus mempartisi ruang (mirip dengan satu C. Chafouin):
Ini tidak sepenuhnya akurat, karena saya menggunakan panjang kata min / maks, dan saya menggunakan jumlah kecocokan pada setiap tahap, tetapi Anda mendapatkan idenya. Pada titik ini, masih belum ada informasi yang cukup untuk mendapatkan 2 ruang, tetapi saya memiliki cukup untuk menguranginya menjadi sejumlah kecil kombinasi. Dari kombinasi itu, saya bisa membuat beberapa pertanyaan spesifik, yang akan mempersempitnya menjadi 1 kombinasi.
Kata Pertama - Dapatkan Subdictionary, yang memiliki kata-kata dengan panjang yang tepat. Subictionary memiliki statistik sendiri. Lakukan beberapa tebakan dengan karakter paling sering, sehingga Anda mendapatkan jumlah karakter ini dalam kata. Kurangi kamus lagi berdasarkan informasi ini. Buat kata tebakan, yang memiliki karakter paling berbeda, dan gunakan itu. Setiap respons menyebabkan pengurangan kamus hingga kami memiliki kecocokan yang tepat, atau kamus berukuran 1.
Kata Kedua - mirip dengan Kata pertama
Kata ketiga - ini sangat berbeda dari yang lain 2. Kami tidak memiliki informasi ukuran untuk ini, tetapi kami memiliki semua pertanyaan sebelumnya (yang telah kami simpan). Kueri ini memungkinkan Anda untuk mengurangi kamus. Logikanya ada pada baris:
Gunakan kamus yang diperkecil untuk menebak, dengan karakter yang paling beragam, dan terus mengurangi kamus hingga ukuran 1 (seperti dalam kata 1 dan 2).
Statistiknya terlihat seperti:
sumber
Go - Total: 29546
Mirip dengan yang lain, dengan beberapa optimasi.
AAAAAAAABBBBBBBBCCCCCCCC...ZZZZZZZZ
Ini tidak terlalu cepat.
sumber
passphases
danallWords
tidak terdefinisi.Jawa: 58.233
(program referensi)
Bot sederhana untuk dikalahkan semua orang. Ini menggunakan 26 tebakan awal untuk setiap frasa untuk menetapkan jumlah karakter. Maka itu menghilangkan semua kata yang mengandung huruf tidak ditemukan dalam frasa.
Kemudian muncul lingkaran O (n 3 ) yang masif di atas kata-kata yang tersisa. Pertama ia memeriksa setiap frase kandidat untuk melihat apakah itu anagram. Jika demikian, tebakanlah, abaikan hasilnya kecuali itu adalah pasangan yang sempurna. Saya telah melihatnya menggunakan antara 28-510 tebakan untuk frasa yang diberikan sejauh ini.
Ini lambat , dan sepenuhnya tergantung pada berapa banyak kata yang bisa dihilangkan langsung dari 26 tebakan awal. Sebagian besar waktu menyisakan antara 1000-4000 kata untuk diulang. Saat ini sudah berjalan sekitar 14 jam, dengan kecepatan ~ 180s / frase. Saya perkirakan akan selesai 50 jam, dan akan memperbarui skor pada saat itu. Anda mungkin harus melakukan sesuatu yang lebih pintar atau lebih dari ini.
(pembaruan) Akhirnya selesai, dengan tebakan di bawah 60k.
sumber
Java:
28.34026.185Min 15, Maks 35, Waktu 2,5s
Karena bot bodohku akhirnya selesai berjalan, aku ingin mengirimkan sesuatu yang sedikit lebih cepat. Ini berjalan hanya dalam beberapa detik, tetapi mendapat skor bagus (tidak cukup menang> <).
Pertama menggunakan string pad besar untuk mendapatkan panjang total frasa. Kemudian pencarian biner untuk menemukan spasi, mirip dengan yang lain. Saat melakukan ini, ia juga mulai memeriksa huruf satu per satu (dalam urutan pivot) sehingga dapat menghilangkan kata-kata yang mengandung lebih banyak huruf apa pun daripada seluruh frasa.
Setelah panjang kata, ia menggunakan langkah reduksi biner untuk mempersempit pilihan untuk daftar kata. Itu memilih daftar terbesar dan surat yang kira-kira setengah dari kata-kata. Itu menebak pad panjang kata dari surat itu untuk menentukan bagian mana yang dibuang. Ini juga menggunakan hasil untuk menghilangkan kata-kata di daftar lain yang memiliki terlalu banyak surat.
Setelah daftar hanya terdiri dari anagram, ini tidak berfungsi. Pada saat itu saya hanya mengulanginya sampai tinggal dua yang tersisa (atau satu jika kata-kata lainnya tidak diketahui).
Jika saya memiliki jumlah kata total empat (dua dikenal dan satu dengan dua opsi), saya melewatkan pengecekan pengurangan dan anagram dan hanya menebak salah satu opsi sebagai frase penuh. Jika tidak berhasil, maka itu pasti yang lain, tapi saya menghemat 50% dari waktu.
Berikut ini contohnya, menunjukkan frasa pertama sedang di-crack:
Dan tentu saja, kodenya:
sumber
C # - 10649 (min 8, maks 14, rata-rata: 10.6) waktu: ~ 12 jam
Seperti inilah tampilannya:
Solver
Ia menggunakan pemecah berwawasan ke depan. Sebelum membuat perkiraan, ia memperkirakan jumlah nilai berbeda yang dikembalikan dari dalang mengingat frasa sandi yang saat ini mungkin. Tebakan yang memaksimalkan jumlah hasil berbeda adalah yang digunakan.
Untuk tahap menebak ruang, ia hanya mempertimbangkan kombinasi yang mungkin dari "" dan "." Untuk fase menebak frase, itu menciptakan seluruh daftar frasa sandi yang saat ini mungkin (itulah sebabnya sangat lambat).
Jumlah Surat
Hitungan surat dilemparkan dengan temuan ruang. Set surat dipilih oleh pencarian serakah, menambahkan satu huruf pada satu waktu dan sampel frase uji acak untuk melihat seberapa efektif set itu.
Kode ada di sini: https://github.com/Tyler-Gelvin/MastermindContest
Tidak ada antarmuka yang ditentukan, sehingga semua input hardcode dan unit test adalah satu-satunya antarmuka. Tes "utama" adalah SolverFixture.SolveParallelAll.
sumber
Main
fungsi dalam kode Anda. Apakah ada satu?SolverFixture.SolveSerialAll
adalah apa yang saya gunakan untuk mendapatkan hasil tes yang diposting di atas danSolver.Solve
merupakan inti dari program ini. Ini adalah proyek uji unit tanpa titik masuk resmi tunggal, jadi tidak adamain
fungsi.C # - Total: 1000, Durasi: 305 Detik, Rata-rata: 24, Min: 14, Maks: 32
Wow rata-rata <15 itu cukup bagus, well saya tidak bisa mengalahkan itu tetapi saya benar-benar menusuknya jadi inilah pendekatan saya. Saya memecahkannya kata demi kata lalu memecahkannya secara berurutan. Dengan menentukan panjang dua kata pertama dan kemudian membuat beberapa tebakan strategis (setiap kali disaring oleh kata tebakan sebelumnya) saya bisa mendapatkan jawabannya dengan jumlah tebakan yang relatif kecil. Selama periode yang saya kembangkan ini, saya dapat mengoptimalkan sebagian besar dari itu untuk membentuk sebelumnya secara efisien (dalam jumlah tebakan) tetapi kesalahannya terletak pada keputusan desain awal untuk secara logis menyelesaikan satu kata pada suatu waktu, ini menyebabkan saya membuang bagian dari menebak dan / atau tidak menjalankan tebakan seefisien mungkin, yang pada gilirannya berarti saya tidak memenangkan yang ini;
Masih desain yang menarik (setidaknya saya pikir begitu), satu hal yang perlu diperhatikan dengan kode yang disertakan, dalam kasus-kasus tertentu saya dapat menentukan jawabannya tanpa pernah menjalankan tebakan yang mengembalikan -1, jika itu diperlukan tanda komentar sederhana, baris kode berlabel "TAMBAHKAN GUESS DI SINI (jika diperlukan)" (dan tambahkan hingga +1 ke semua skor saya :()
Algoritma (My Sudo Code Thinking)
Jadi benar-benar ada dua bagian untuk ini, dua kata pertama, dan kata terakhir. Ini mungkin tidak masuk akal bagi siapa pun selain saya, tetapi saya sudah mencoba menambahkan komentar yang cukup ke kode sehingga mungkin itu lebih masuk akal:
NextWord (salah satu dari dua kata pertama)
{
var lengthOfPossibleWord = Tentukan panjang kata (Dalam kode lihat: cara efisien untuk menemukan panjang)
Daftar kemungkinan = Semua Kata dengan panjang itu (lengthOfPossibleWord)
Tebaklah
Kemungkinan = kemungkinan di mana (untuk semua tebakan) {Jumlah karakter di posisi yang sama sama dengan kata yang mungkin
(jika outOfPlace karakter sama dengan 0) maka di mana semua karakter berbeda dari kata yang mungkin}
}
LastWord (Setelah dua yang pertama diselesaikan)
{
Daftar kemungkinan = Semua Kata difilter dengan jumlah karakter offPosisi di kata kedua (Dalam kode lihat: helperWords)
Tebaklah
kemungkinan = kemungkinan di mana (untuk semua tebakan) {
Jumlah karakter di posisi yang sama sama dengan kata yang mungkin
Jumlah karakter masuk dan keluar dari posisi == kata yang mungkin (untuk semua tebakan)
Panjangnya sama dengan lebih besar dari (Jumlah karakter masuk dan keluar dari posisi) panjang kata yang mungkin
(jika outOfPlace karakter sama dengan 0) maka di mana semua karakter berbeda dari kata yang mungkin
}
}
Kode
Catatan agar ini berfungsi, Anda harus menyertakan ppcg_mastermind_dict.txt dan ppcg_mastermind_passes.txt dalam direktori yang sedang berjalan (atau dalam VS di direktori yang sama dan set "Salin ke Direktori Output" menjadi true). Saya benar-benar minta maaf atas kualitas kode masih ada banyak pekerjaan yang harus dilakukan pada ini, itu harus bekerja.
sumber
Python - min: 87, maks: 108, total: 96063, waktu: 4s
Ini posting kedua saya. Metode ini menggunakan lebih sedikit waktu tetapi skor lebih buruk. Dan itu dapat dijalankan menggunakan:
Langkah:
. ....
,.. ...
...Harganya sekitar 90 tebakan untuk setiap kata sandi.
sumber
Perl (masih berjalan ... sampai sekarang min / rata-rata / maks 8 / 9,2 / 11, perkirakan pada
1500300 jam total runtime)Pembaruan: Mengubah tebakan awal untuk mempercepatnya. Memperbaiki bug.
Mungkin tidak akan selesai sebelum kontes ini selesai, tapi saya mungkin juga mempostingnya. Tidak menentukan panjang kata individual, sehingga harus memeriksa seluruh kamus, yang ... membutuhkan waktu.
Dengan dua tebakan pertama itu menentukan panjang total, jumlah 'e', dan berapa banyak karakter yang berbeda.
Kemudian ia mencoba semua kombinasi yang mencukupi statistik tersebut serta semua tebakan sebelumnya.
Versi terbaru (dan terakhir) ini telah menambahkan mp dan saat ini berjalan pada sistem 24 inti.
sumber
Java 10.026 (dalam 2,5 jam)
Ini kode saya yang dioptimalkan, sekarang multi-utas untuk meningkatkan kecepatan:
sumber