Pertimbangkan kotak dengan grafik kotak yang terlihat seperti ini.
Penting untuk diperhatikan bahwa grafik ini adalah 11 oleh 11 .
Pada titik tertentu, seorang pria berdiri di persimpangan dan dia hanya pernah bergerak secara vertikal atau horizontal satu langkah pada satu waktu ke persimpangan berikutnya. Sayangnya dia terlalu banyak minum sehingga dia memilih arah yang dia bergerak secara acak dari hingga 4 kemungkinan arah (atas, bawah, kiri, kanan). Ini hingga 4 seolah-olah dia berdiri di dinding dia hanya memiliki 3 pilihan saja dan di sudut dia hanya memiliki 2.
Dia mulai di sudut kiri bawah dan tujuannya adalah untuk pulang yang merupakan sudut kanan atas. Waktu hanyalah jumlah langkah yang dibutuhkannya.
Namun, Anda adalah musuh jahat yang ingin dia pulang selambat mungkin. Anda dapat menghapus sejumlah tepi dari grafik kapan saja selama perjalanannya. Satu-satunya batasan adalah bahwa Anda harus selalu meninggalkan beberapa cara baginya untuk pulang dan Anda tidak dapat menghapus tepi yang telah ia gunakan.
Tantangannya adalah untuk merancang musuh yang jahat sebanyak mungkin dan kemudian mengujinya pada grafik
100 x 10020 x 20 dengan walker mabuk secara acak. Skor Anda hanyalah waktu rata-rata yang dibutuhkan walker acak untuk pulang lebih dari101000 kali jalan.
Anda dapat menggunakan bahasa dan perpustakaan apa saja yang Anda suka asalkan tersedia secara bebas dan mudah diinstal di Linux.
Apa yang perlu saya terapkan?
Anda harus menerapkan kode untuk walker acak dan juga untuk musuh dan kode harus digabungkan sehingga output saat dijalankan hanyalah rata-rata 1000 berjalan menggunakan kode musuh Anda. Kode walker acak harus sangat sederhana untuk ditulis karena ia hanya memilih dari (x-1, y), (x + 1, y), (x, y-1), dan (x, y + 1) memastikan bahwa tidak ada yang telah dihapus atau berada di luar jangkauan.
Kode musuh tentu saja lebih sulit dan juga perlu mengingat sisi-sisi pemabuk yang telah dilalui sehingga ia tidak mencoba untuk menghapus salah satu dari mereka dan untuk memastikan masih ada rute pulang ke pemabuk, yang sedikit rumit harus dilakukan dengan cepat.
Adendum 10 lari tidak cukup tetapi saya tidak ingin menghukum orang yang berhasil berjalan sangat lama. Saya sekarang telah meningkatkannya menjadi 1000 karena permintaan populer. Namun, jika perjalanan Anda begitu lama sehingga Anda tidak dapat melakukan 1000 lari dalam jumlah waktu yang realistis, harap laporkan saja untuk jumlah lari maksimum yang Anda bisa.
Tabel skor tinggi untuk 100 oleh 100.
- 976124.754 oleh Optimizer.
- 103000363.218 oleh Peter Taylor.
Sunting 1. Mengubah ukuran grafik menjadi 20 dengan 20 untuk membantu waktu pengujian orang berjalan. Saya akan membuat skor tabel tinggi baru untuk ukuran itu ketika orang mengirimkan skor.
Tabel skor tinggi untuk 20 dengan 20.
230,794.38 (100k runs) by justhalf
227,934 by Sparr
213,000 (approx) by Peter Taylor
199,094.3 by stokastic
188,000 (approx) by James_pic
64,281 by Geobits
Jawaban:
230.794,38 pada 20x20, 100rb berjalan
Pembaruan Terbaru: Saya akhirnya membangun solusi 2-path dinamis yang sempurna. Saya mengatakan sempurna karena versi sebelumnya sebenarnya tidak simetris, lebih mudah untuk mendapatkan jalur yang lebih panjang jika pemabuk mengambil satu jalur di atas yang lain. Yang saat ini simetris, sehingga bisa mendapatkan jumlah langkah yang diharapkan lebih tinggi. Setelah beberapa uji coba, tampaknya sekitar 230rb, peningkatan dari yang sebelumnya sekitar 228rb. Tetapi secara statistik angka-angka itu masih dalam penyimpangan besar mereka, jadi saya tidak mengklaim bahwa ini secara signifikan lebih baik, tetapi saya percaya ini harus lebih baik daripada versi sebelumnya.
Kode di bagian bawah posting ini. Ini diperbarui sehingga jauh lebih cepat daripada versi sebelumnya, menyelesaikan 1000 berjalan dalam 23 detik.
Di bawah ini adalah contoh dijalankan dan sampel labirin:
Kiriman sebelumnya
Akhirnya saya bisa mencocokkan hasil Sparr! = D
Berdasarkan percobaan saya sebelumnya (lihat bagian bawah posting ini), strategi terbaik adalah memiliki jalur ganda dan menutup satu ketika pemabuk mencapai salah satu dari mereka, dan variabel berasal dari seberapa baik kita dapat secara dinamis memprediksi ke mana pemabuk akan pergi ke tingkatkan peluang dia masuk ke jalur yang lebih panjang.
Jadi berdasarkan
DOUBLE_PATH
strategi saya , saya membangun yang lain, yang mengubah labirin (DOUBLE_PATH
labirin saya mudah dimodifikasi) tergantung pada gerakan pemabuk. Ketika ia mengambil jalan dengan lebih dari satu opsi yang tersedia, saya akan menutup jalan sehingga hanya menyisakan dua opsi yang mungkin (satu dari mana ia datang, yang lain yang tidak terurai).Ini terdengar mirip dengan apa yang telah dicapai Sparr, seperti yang ditunjukkan hasilnya. Perbedaannya dengan dia terlalu kecil untuk dianggap lebih baik, tetapi saya akan mengatakan bahwa pendekatan saya lebih dinamis daripada dia, karena labirin saya lebih dapat dimodifikasi daripada Sparr's =)
Hasil dengan labirin akhir sampel:
Bagian Eksperimen
Yang terbaik ternyata menjadi strategi yang sama dengan stokastic, saya bangga bereksperimen menggunakan berbagai strategi dan mencetak output yang bagus :)
Masing-masing labirin tercetak di bawah adalah labirin terakhir setelah pemabuk mencapai rumah, sehingga mereka mungkin sedikit berbeda dari berlari untuk berlari karena keacakan dalam gerakan pemabuk dan dinamika musuh.
Saya akan menjelaskan setiap strategi:
Jalur Tunggal
Ini adalah pendekatan paling sederhana, yang akan membuat satu jalur dari entri ke keluar.
Pulau (level 0)
Ini adalah pendekatan yang mencoba menjebak pemabuk di pulau yang hampir terisolasi. Tidak berfungsi sebaik yang saya harapkan, tetapi ini adalah salah satu ide pertama saya, jadi saya memasukkannya.
Ada dua jalan menuju ke pintu keluar, dan ketika si pemabuk mendekati salah satu dari mereka, musuh menutupnya, memaksanya untuk menemukan jalan keluar yang lain (dan mungkin terjebak lagi di pulau itu)
Jalan Ganda
Ini adalah strategi yang paling banyak dibahas, yaitu memiliki dua jalur panjang yang sama ke pintu keluar, dan tutup salah satunya saat pemabuk mendekati salah satunya.
Pulau (level 1)
Terinspirasi oleh beberapa jalur pulau dan jumlah langkah jalan tinggi dalam jalur tunggal, kami menghubungkan pulau ke pintu keluar dan membuat jalur tunggal labirin di pulau itu, menciptakan total tiga jalur untuk keluar, dan mirip dengan kasus sebelumnya, tutup semua keluar saat pemabuk mendekat.
Ini bekerja sedikit lebih baik daripada jalur tunggal murni, tetapi masih tidak mengalahkan jalur ganda.
Pulau (level 2)
Mencoba untuk memperluas ide sebelumnya, saya membuat pulau bersarang, menciptakan total lima jalur, tetapi tampaknya tidak berhasil dengan baik.
Pulau (level 3)
Memperhatikan bahwa jalur ganda sebenarnya bekerja lebih baik daripada jalur tunggal, mari kita buat pulau di jalur ganda!
Hasilnya adalah peningkatan di atas Pulau (level 1), tetapi masih belum mengalahkan jalur ganda murni.
Sebagai perbandingan, hasil untuk jalur ganda ukuran pulau adalah 131.134,42 bergerak rata-rata. Jadi ini menambah jumlah gerakan yang cukup signifikan (sekitar 40k), tetapi tidak cukup untuk mengalahkan jalur ganda.
Pulau (level 4)
Sekali lagi, bereksperimen dengan pulau bersarang, dan sekali lagi itu tidak berfungsi dengan baik.
Kesimpulan
Secara keseluruhan, ini membuktikan bahwa memiliki jalur panjang tunggal dari posisi pemabuk saat ini ke jalan keluar paling baik, yang dicapai oleh strategi jalur ganda, karena setelah menutup jalan keluar, pemabuk harus menempuh jarak maksimum yang mungkin untuk sampai ke keluar.
Ini lebih lanjut mengisyaratkan bahwa strategi dasar masih harus berupa jalur ganda, dan kita hanya dapat memodifikasi seberapa dinamis jalur tersebut dibuat, yang telah dilakukan oleh Sparr. Jadi saya percaya strateginya adalah cara untuk pergi!
Kode
sumber
227934 (20x20)
Upaya ketiga saya. Menggunakan pendekatan umum yang sama dengan @stokastic dengan dua jalur keluar. Ketika walker mencapai ujung satu jalan, itu menutup, mengharuskan dia untuk kembali ke ujung jalan lain untuk keluar. Peningkatan saya adalah menghasilkan jalur saat pejalan maju, sehingga jalur mana pun yang ia laju lebih jauh di paruh pertama proses akan berakhir lebih lama dari jalur lainnya.
output (dengan waktu):
contoh labirin saya, dengan panjang kira-kira sama panjang dengan jalan, menunjukkan jalan kiri / bawah terputus dari pintu keluar (kanan bawah):
PS: Saya menyadari peningkatan yang sangat kecil untuk algoritma ini yang membutuhkan kode yang lebih pintar untuk menghasilkan bentuk yang berbeda untuk dua jalur, tangga bukannya tinggi zig zag yang konsisten.
sumber
135.488.307,9 untuk 98x98
199094.3 untuk 20x20
Saya telah menerapkan solusi yang menciptakan dua jalur ke garis finish, dan menutup salah satu dari mereka begitu pemabuk mencapai itu. Ini mensimulasikan panjang lintasan yang setidaknya 1,5 kali panjang lintasan tunggal dari awal sampai akhir. Setelah 27 berjalan saya mencapai rata-rata sekitar 135 juta. Sayangnya dibutuhkan beberapa menit per berjalan, jadi saya harus menjalankannya selama beberapa jam ke depan. Satu peringatan - generator jalur ganda saya hanya berfungsi jika ukuran grafik dalam bentuk 4 * n + 2, artinya yang terdekat yang bisa saya dapatkan dengan 100 adalah 102 atau 98. Saya akan memposting hasil menggunakan 98, yang saya harapkan masih melampaui metode jalur zigzag. Saya akan bekerja pada sistem jalur yang lebih baik nanti. Saat ini hasil keluaran dalam bentuk (numSteps, currentAverage) setelah setiap berjalan.
EDIT: diperbaiki jadi kode sekarang bekerja pada ukuran grafik yang merupakan kelipatan dari 2, bukan 4 * n + 2.
Kode: (tambahkan argumen 'Benar' ke konstruktor walker on line 187 untuk menggambar grafik penyu).
Data mentah: (numSteps saat ini, rata-rata berjalan)
sumber
Pendekatan 4 jalur, 213k
Pendekatan satu jalur adalah
dan skor rata-rata
N^2
.Pendekatan dua jalur adalah
tetapi kemudian saat pemabuk pertama kali mencapai titik akhir, ia terpotong:
Ini skor rata-rata
(N/2)^2 + N^2
.Pendekatan empat jalur menggunakan dua pemotongan:
Asumsikan bahwa loop luar panjang
xN
dan loop dalam panjang(1-x)N
. Untuk kesederhanaan, saya akan menormalkanN=1
.Dari mulai hingga skor cut pertama rata-rata
(x/2)^2
. Dari potongan pertama ke potongan kedua memiliki dua opsi, panjangx
dan1-x
; ini memberikan rata-rata(1-x)x^2 + x(1-x)^2 = x-x^2
. Akhirnya jalan yang tersisa memberi1
. Jadi skor totalnya adalahN^2 (1 + x - 3/4 x^2)
.Saya awalnya berasumsi bahwa menjaga jalur yang tersedia dengan panjang yang sama di setiap langkah akan optimal, jadi pendekatan awal saya digunakan
x = 1/2
memberikan skor1.3125 N^2
. Tetapi setelah melakukan analisis di atas ternyata pembagian optimal diberikan ketikax = 2/3
dengan skor1.3333 N^2
.dengan kode
sumber
f
kec
dalam kode Anda adalah tentangN/2
, baik melaluie
(dand
) atau tidak, kan?N^2
, bukan2^N
. Dan ya, membuat dinamika ini akan menjadikannya yang terbaik, tantangannya adalah bagaimana membuatnya dinamis sambil mempertahankan properti empat jalur. @PeterTaylor: Gambar yang bagus!Saya bereksperimen dengan mengiris grid hampir seluruhnya di setiap
k
baris. Ini secara efektif mengubahnya menjadi sesuatu yang mirip dengan acak berjalan padak
olehN * N/k
jaringan. Opsi yang paling efektif adalah mengiris setiap baris sehingga kami memaksa pemabuk ke zigzag.Untuk kasus 20x20 (
SIZE=19
) saya punyadengan kode
sumber
Bagi mereka yang tidak ingin menemukan kembali roda
Jangan khawatir! Saya akan menciptakannya untuk Anda :)
Omong-omong, ini di Jawa.
Saya membuat kelas Walker yang berhubungan dengan berjalan secara acak. Ini juga mencakup metode yang bermanfaat untuk menentukan apakah suatu langkah valid (jika sudah berjalan di atas).
Saya berasumsi kalian semua orang pintar bisa mencari untuk memasukkan angka acak untuk konstruktor, saya menyerahkannya kepada Anda sehingga Anda dapat menguji kasus-kasus tertentu. Juga, panggil saja fungsi walk () untuk (Anda dapat menebaknya!) Membuat pemabuk tersebut berjalan (secara acak).
Saya akan mengimplementasikan fungsi canComeHome () di lain waktu. Lebih disukai setelah saya mencari cara terbaik untuk melakukan itu.
sumber
previouslyTraveled.add(new int[]{x,y,move[0],move[1]})
harusx+move[0]
dany+move[1]
. TheWidth-1
danHeight-1
, dan ketidakefisienan dalam memeriksa jalur yang dihapus. Saya telah mengedit kode Anda (dengan fungsi tambahan untuk mencetak labirin). Jangan ragu untuk mengembalikan jika Anda pikir itu tidak pantas.Edge
tidak menerapkan dengan benarComparable<Edge>
. Jika Anda ingin tepi membandingkan sebagai sama bahkan jika Anda membalikkannya, Anda perlu memperhitungkan pembalikan juga dalam kasus yang tidak sama. Cara termudah untuk melakukan ini adalah mengubah konstruktor untuk menjaga agar poin tetap tertata.Comparable
?A
danB
adalah ujung yang sama terbalik danC
berbeda, Anda bisa mendapatkanA.compareTo(B) == B.compareTo(A) == 0
tetapiA.compareTo(C) < 0
danB.compareTo(C) > 0
.canComeHome()
)64.281
Memperbarui sejak kisi diubah dari 100x100 ke 20x20 (1000 tes). Skor 100x100 (100 tes) kira-kira 36M.
Meskipun ini tidak akan mengalahkan jalan 1D, saya ingin bermain dengan ide yang saya miliki.
Ide dasarnya adalah bahwa grid dibagi menjadi ruang-ruang persegi, dengan hanya satu jalur yang menuju 'rumah' dari masing-masing. Jalur terbuka adalah yang mana pun pemabuk itu mendekati yang terakhir , artinya dia harus menjelajahi setiap kemungkinan keluar, hanya untuk memiliki semua kecuali satu dari mereka yang terbanting di wajahnya.
Setelah bermain dengan ukuran kamar, saya sampai pada kesimpulan yang sama dengan Peter, mengirisnya menjadi lebih kecil lebih baik. Skor terbaik datang dengan ukuran kamar 2.
Kode ini ceroboh, tidak masalah berantakan. Anda dapat menyalakan
SHOW
sakelar dan itu akan menampilkan gambar jalur setiapSHOW_INT
langkah sehingga Anda dapat melihatnya beraksi. Proses yang selesai terlihat seperti:(Ini adalah gambar dari kisi 100x100 sebelumnya. 20x20 persis seperti ini, tetapi, yah, lebih kecil. Kode di bawah ini telah diperbarui untuk ukuran / proses baru.)
sumber
188k, dengan 2 jalur
Entri terbaik semua tampaknya mengambil pendekatan menghasilkan 2 jalur, dan kemudian memotong satu ketika mabuk mendekati akhir jalan. Saya tidak berpikir saya bisa mengalahkan entri justhalf, tetapi saya bertanya-tanya: Mengapa 2 jalur? Kenapa tidak 3, atau 5, atau 20?
TL; DR : 2 jalur tampaknya optimal
Jadi saya melakukan percobaan. Berdasarkan kerangka Stretch Maniac, saya menulis entri untuk menguji berbagai jumlah jalur. Anda dapat mengubah
featureSize
parameter untuk memvariasikan jumlah jalur. AfeatureSize
dari 20 memberi 1 jalur, 10 memberi 2 jalur, 7 memberi 3, 5 memberi 4, dan seterusnya.Ada beberapa optimisasi yang bisa saya lakukan tetapi belum, dan itu tidak mendukung tipu daya adaptif yang hanya digunakan.
Bagaimanapun, inilah hasil untuk berbagai
featureSize
nilai:Dan inilah peta dengan 3 jalur:
sumber
N
lintasan panjang (yaitun^2-1
), lintasan tunggal rata-rata akan memerlukanN^2
gerakan, sedangkan tiga lintasan(N/3)^2 + (2N/3)^2 + (2N/3)^2 = N^2
ditambah beberapa nilai yang relatif kecil, sehingga tiga jalur tidak memiliki keuntungan signifikan atas jalur tunggal, apalagi jalur ganda. (Perhitungan didasarkan pada hasil probabilitas yang menyatakan bahwa gerakan acak pada lintasan 1-DN
membutuhkanN^2
gerakan rata-rata dari satu ujung ke ujung lainnya.)131r (20x20)
Upaya pertama saya adalah untuk menghapus semua tepi horisontal kecuali baris atas dan bawah, maka setiap kali walker mencapai bagian bawah kolom saya akan menghapus tepi di depannya, sampai dia mengunjungi bagian bawah setiap kolom dan akhirnya akan dapat mencapai pintu keluar. Ini menghasilkan rata-rata 1/8 langkah dari pendekatan berjalan 1d @ PeterTaylor.
Selanjutnya saya memutuskan untuk mencoba sesuatu yang sedikit lebih berputar-putar. Saya telah membagi labirin menjadi serangkaian chevron berongga bersarang, dan mengharuskannya untuk melintasi perimeter setiap chevron setidaknya 1,5 kali. Ini memiliki waktu rata-rata sekitar 131 ribu langkah.
sumber
Tidak melakukan apapun
Karena pria itu bergerak secara acak, orang mungkin berpikir bahwa menghapus simpul apa pun hanya akan meningkatkan peluangnya untuk pulang dalam jangka panjang.
Pertama, mari kita lihat kasus satu dimensi, ini dapat dicapai dengan menghapus node sampai Anda berakhir dengan jalan berlekuk, tanpa tenggat waktu atau siklus, yang mengunjungi (hampir) setiap titik jaringan. Pada
N x N
kisi, panjang maksimal jalur tersebut adalahL = N*N - 2 + N%2
(98 untuk kisi 10x10). Berjalan di sepanjang jalan dapat digambarkan oleh matriks transisi seperti yang dihasilkan olehT1d
.(Asimetri yang sedikit membuat sulit untuk menemukan solusi analitis, kecuali untuk matriks yang sangat kecil atau tidak terbatas, tetapi kami memperoleh solusi numerik lebih cepat daripada yang dibutuhkan untuk mendiagonisasi matriks itu).
Vektor state memiliki satu
1
di posisi awal dan setelahK
langkah(T1d**K) * state
memberi kita distribusi probabilitas berada pada jarak tertentu dari awal (yang setara dengan rata-rata atas semua2**K
jalan yang mungkin di sepanjang jalan!)Menjalankan simulasi untuk
10*L**2
langkah - langkah dan menyimpan elemen terakhir dari vektor keadaan setelah setiap langkah yang memberi kita kemungkinan berhasil mencapai tujuan setelah sejumlah langkah tertentu - distribusi probabilitas kumulatifcd(t)
. Membedakannya memberi kita kemungkinanp
untuk mencapai tujuan tepat pada waktu tertentu. Untuk menemukan waktu rata-rata yang kami integrasikan,t*p(t) dt
Waktu rata-rata untuk mencapai tujuan adalah proporsional
L**2
dengan faktor yang berjalan sangat cepat ke 1. Deviasi standar hampir konstan pada sekitar 79% dari waktu rata-rata.Grafik ini menunjukkan waktu rata-rata untuk mencapai tujuan untuk panjang jalur yang berbeda (sesuai dengan ukuran kisi 5x5 hingga 15x15)
Di sini terlihat seperti kemungkinan mencapai tujuan. Kurva kedua terlihat terisi karena pada setiap timestep ganjil posisi ganjil dan karenanya tidak dapat mencapai tujuan.
Dari situ kita dapat melihat bahwa strategi jalur ganda seimbang bekerja paling baik di sini. Untuk grid yang lebih besar, di mana biaya overhead untuk membuat lebih banyak jalur dapat diabaikan dibandingkan dengan ukurannya, kita mungkin lebih baik meningkatkan jumlah jalur, mirip dengan cara Peter Taylor menggambarkannya, tetapi menjaga panjangnya seimbang
Bagaimana jika kita tidak menghapus node sama sekali?
Maka kita akan memiliki dua kali lebih banyak walkable node, ditambah empat kemungkinan arah, bukan dua. Tampaknya itu membuatnya sangat tidak mungkin untuk pergi ke mana pun. Namun, simulasi menunjukkan sebaliknya, setelah hanya 100 langkah pada grid 10x10, pria tersebut kemungkinan besar akan mencapai tujuannya, jadi menjebaknya di pulau-pulau adalah upaya yang sia-sia, karena Anda berdagang
N**2
jalur berliku panjang yang potensial dengan waktu penyelesaian rata-rataN**4
untuk sebuah pulau yang dilewati secaraN**2
bertahapsumber