Sejarah
Perusahaan saya mengirimkan buletin mingguan kepada semua orang di dalam perusahaan. Termasuk dalam buletin ini adalah teka-teki, bersama dengan teriakan kepada siapa pun di perusahaan adalah orang pertama yang mengirim email / memberikan solusi untuk teka-teki minggu lalu. Sebagian besar teka-teki ini cukup sepele, dan sejujurnya cukup membosankan untuk sebuah perusahaan teknologi, tetapi ada satu, beberapa bulan yang lalu, yang menarik perhatian saya.
Teka-teki Asli:
Diberikan bentuk di bawah ini:
Anda memiliki Bilangan Alami dari 1 hingga 16. Paskan semuanya ke dalam bentuk ini, sehingga semua baris dan kolom yang berdekatan berjumlah hingga 29.
Misalnya, salah satu solusi untuk teka-teki ini (yang merupakan solusi "kanonik" yang saya kirimkan ke buletin) adalah sebagai berikut:
Namun, dalam penyelesaiannya, saya menemukan beberapa informasi yang agak menarik:
- Ada jauh lebih banyak solusi daripada hanya satu itu; sebenarnya, ada 9.368 Solusi.
- Jika Anda memperluas aturan hanya mensyaratkan bahwa baris dan kolom sama satu sama lain, belum tentu 29, Anda mendapatkan 33.608 solusi:
- 4.440 Solusi dengan jumlah 27.
- 7.400 Solusi dengan jumlah 28.
- 9.368 Solusi dengan jumlah 29.
- 6.096 Solusi dengan jumlah 30.
- 5.104 Solusi dengan jumlah 31.
- 1.200 Solusi dengan jumlah 32.
Jadi saya dan rekan kerja saya (meskipun sebagian besar hanya manajer saya, karena ia adalah satu-satunya orang selain saya yang memiliki keterampilan pemrograman "Tujuan Umum") memulai sebuah tantangan, yang berlangsung hampir sepanjang bulan — kami memiliki pekerjaan lain yang sebenarnya - kewajiban terkait yang harus kami hadiri — untuk mencoba menulis sebuah program yang akan menemukan setiap solusi dengan cara tercepat yang mungkin.
Statistik Asli
Program pertama yang saya tulis untuk memecahkan masalah cukup memeriksa solusi acak berulang-ulang, dan berhenti ketika menemukan solusi. Jika Anda sudah melakukan analisis matematika pada masalah ini, Anda mungkin sudah tahu bahwa ini seharusnya tidak berhasil; tapi entah bagaimana saya beruntung, dan butuh program hanya satu menit untuk menemukan solusi tunggal (yang saya posting di atas). Pengulangan program seringkali memakan waktu 10 atau 20 menit, jadi jelas ini bukan solusi yang tepat untuk masalah ini.
Saya beralih ke Solusi Rekursif yang berulang melalui setiap permutasi yang mungkin dari teka-teki, dan membuang banyak solusi sekaligus dengan menghilangkan jumlah yang tidak bertambah. Yaitu jika baris / kolom pertama yang saya bandingkan sudah tidak sama, saya bisa berhenti memeriksa cabang itu segera, mengetahui bahwa tidak ada hal lain yang dimasukkan ke dalam puzzle akan mengubah itu.
Dengan menggunakan algoritma ini, saya mendapatkan kesuksesan "layak" pertama: program ini dapat menghasilkan dan mengeluarkan semua 33.608 solusi dalam waktu sekitar 5 menit.
Manajer saya memiliki pendekatan yang berbeda: mengetahui berdasarkan pekerjaan saya bahwa satu-satunya solusi yang mungkin memiliki jumlah 27, 28, 29, 30, 31, atau 32, ia menulis solusi multi-utas yang memeriksa jumlah yang mungkin hanya untuk nilai-nilai spesifik tersebut. Dia berhasil menjalankan programnya hanya dalam 2 menit. Jadi saya mengulangi lagi; Saya hash semua kemungkinan jumlah 3/4 digit (pada awal program; ini dihitung dalam runtime total) dan menggunakan "jumlah parsial" dari sebuah baris untuk mencari nilai yang tersisa berdasarkan pada baris yang sebelumnya diselesaikan, daripada menguji semua nilai yang tersisa, dan membawa waktu ke 72 detik. Kemudian dengan beberapa logika multi-threading, saya mendapatkannya hingga 40 detik. Manajer saya membawa pulang program, melakukan beberapa optimasi tentang bagaimana program berjalan, dan menurunkannya menjadi 12 detik. Saya memesan kembali evaluasi baris dan kolom,
Yang tercepat dari kami mendapatkan program kami setelah sebulan adalah 0,15 detik untuk manajer saya, dan 0,33 detik untuk saya. Saya akhirnya mengklaim bahwa program saya lebih cepat, karena program manajer saya, sementara itu menemukan semua solusi, tidak mencetaknya ke dalam file teks. Jika dia menambahkan logika itu ke kodenya, seringkali butuh waktu 0,4-0,5 detik.
Sejak itu kami membiarkan tantangan intra-pribadi kami bertahan, tetapi tentu saja, pertanyaannya tetap: bisakah program ini dibuat lebih cepat?
Itulah tantangan yang akan saya ajukan kepada kalian.
Tantangan Anda
Parameter yang kami kerjakan melonggarkan aturan "jumlah 29" sebagai gantinya "jumlah semua baris / kolom sama", dan saya akan menetapkan aturan itu juga untuk kalian. Tantangannya, oleh karena itu, adalah: Menulis program yang menemukan (dan Mencetak!) Semua solusi untuk teka-teki ini dalam waktu sesingkat mungkin. Saya akan menetapkan batas pada solusi yang diajukan: Jika program membutuhkan lebih dari 10 detik pada komputer yang relatif baik (<8 tahun), mungkin terlalu lambat untuk dihitung.
Juga, saya punya beberapa Bonus untuk puzzle:
- Bisakah Anda menggeneralisasi solusi sehingga berfungsi untuk set angka 16, bukan hanya
int[1,16]
? Skor waktu akan dievaluasi berdasarkan set angka prompt yang asli, tetapi melewati codepath ini. (-10%) - Bisakah Anda menulis kode dengan cara yang anggun menangani dan menyelesaikan dengan angka duplikat? Ini tidak semudah kelihatannya! Solusi yang "identik secara visual" harus unik dalam set hasil. (-5%)
- Bisakah Anda menangani angka negatif? (-5%)
Anda juga dapat mencoba menghasilkan solusi yang menangani Angka Titik Apung, tetapi tentu saja, jangan kaget jika itu gagal total. Jika Anda menemukan solusi yang kuat, itu mungkin bernilai bonus besar!
Untuk semua maksud dan tujuan, "Rotasi" dianggap sebagai solusi unik. Jadi solusi yang hanya merupakan rotasi dari solusi yang berbeda dianggap sebagai solusi sendiri.
IDE yang saya kerjakan di komputer saya adalah Java dan C ++. Saya dapat menerima jawaban dari bahasa lain, tetapi Anda mungkin juga perlu memberikan tautan ke tempat saya bisa mendapatkan lingkungan runtime yang mudah diatur untuk kode Anda.