Anda menemukan diri Anda di papan catur, seperti yang dilakukan orang. Anda dapat melihat pintu keluar tetapi sangat jauh dan Anda lebih suka tidak berjalan jauh-jauh. Untungnya beberapa penduduk setempat menawarkan tumpangan kepada Anda. Seorang Ksatria, seorang Benteng, seorang Uskup dan seorang Raja semua bersedia membawa Anda ke tujuan Anda, tetapi melihat bagaimana ini adalah papan catur mereka masing-masing harus mematuhi aturan catur dalam perjalanan ke tujuan Anda. Anda ingin keluar dari sini sesegera mungkin, penawaran siapa yang Anda terima?
Tugas
Dengan papan catur berbentuk dan berukuran sewenang-wenang dan dua titik di papan catur, hasilkan bidak catur yang dapat bergerak di antara dua lokasi dalam gerakan sesedikit mungkin. Papan tidak harus berarti terus menerus bahwa mungkin ada kesenjangan antara bagian-bagian papan. Masing-masing dari empat bagian (Raja, Benteng, Ksatria, dan Uskup) dapat bergerak sesuai dengan aturan standar mereka dalam catur. Sang Ratu dan bidak telah sengaja ditinggalkan dari tantangan ini.
I / O
Anda dapat mengambil input dalam format apa pun yang masuk akal dan Anda dapat menampilkan dalam format apa pun yang Anda pilih. Input dan output Anda harus konsisten. Jika beberapa bagian dapat mencapai tujuan dalam jumlah gerakan yang sama, Anda harus mengeluarkan semua bagian yang bisa sampai di sana dalam jumlah waktu minimum. Jika tidak satu pun dari empat bagian yang dapat mencapai akhir, Anda dapat mengeluarkan apa saja selama berbeda dari semua kemungkinan hasil lainnya. Ini bisa termasuk mengeluarkan apa-apa atau melempar kesalahan.
Uji Kasus
Kotak menunjukkan titik awal dan sebuah lingkaran menunjukkan titik akhir.
Uskup
Ksatria
Raja
Benteng
Raja, Ksatria
Tidak ada
Jawaban:
Haskell ,
447439437432 bytePanggilan menggunakan di
g <board> <start> <end>
mana<board> :: [(Int, Int)]
,<start> :: (Int, Int)
dan<end> :: (Int, Int)
. Mengembalikan daftar yang berisi1
untuk Ksatria,2
untuk Benteng,3
untuk Uskup, dan4
untuk Raja. Jika tidak ada solusi yang ditemukan, itu secara konsisten meluap tumpukan (yang dianggap sebagai melemparkan kesalahan, kan?).Inspirasi yang diambil dari bab-bab LYAH tentang Monad -
(%)
hanyalah sebuah generalisasi dan golfinMany
, dengan(&)
setara dengan(Control.Monad.<=<)
. Segala sesuatu yang lain harus lebih atau kurang jelas.Ini mungkin bisa bermain golf lebih banyak, tetapi saya sudah cukup bersenang-senang untuk saat ini.
Tidak Disatukan:
sumber
Mathematica,
326325 byteTerima kasih kepada masterX224 karena menunjukkan penghematan byte!
Mendefinisikan fungsi yang
f
mengambil tiga argumen:g
adalah daftar pasangan integer yang diurutkan yang mewakili dewan, danw
danx
pasangan yang diperintahkan mewakili kotak awal dan akhir. Outputnya adalah himpunan bagian{b, k, n, r}
(mewakili masing-masing uskup, raja, ksatria, dan benteng) yang memiliki jalur gerakan minimal antara dua kotak. Sebagai contoh, test case ketiga dipanggil olehf[{{0, 0}, {1, 1}, {1, 2}, {0, 3}}, {0, 0}, {0, 3}]
dan kembali{k}
; dua kasus uji terakhir kembali{k, n}
dan{}
masing-masing.Strateginya adalah menerjemahkan kuadrat papan ke dalam simpul grafik, di mana ujung-ujungnya ditentukan oleh gerakan masing-masing bagian, dan kemudian menggunakan rutinitas grafik bawaan.
Versi kode yang lebih mudah digunakan:
Pada baris 3,
Select[g~Tuples~2, # - #2 & @@ # == d
temukan semua pasangan simpul berurutan yang perbedaannya adalah vektord
;e
kemudian mengubah setiap pasangan yang dipesan tersebut menjadi tepi grafik yang tidak terarah. Jadia
adalah fungsi yang menciptakan tepi antara semua simpul yang berbeda dengan vektor tetap.Itu cukup untuk mendefinisikan, di jalur 4 dan 5, grafik raja
y@k
(yang mengambil penyatuan tepi yang dihasilkan oleh vektor{1, 1}
,{-1, 1}
,{0, 1}
, dan{-1, 0}
) dan grafik ksatriay@n
(yang melakukan hal yang sama dengan{1, 2}
,{2, 1}
,{-2, 1}
, dan{-1, 2}
).Pada baris 7,
ConnectedComponents@a@#
ambil salah satu dari grafik tetangga ini dan kemudian temukan komponen yang terhubung; ini sesuai dengan pengelompokan semua segmen garis simpul dalam arah yang diberikan (sehingga benteng atau uskup tidak harus bergerak melewatinya satu per satu). Kemudiane@t@#
pada baris 6 menempatkan tepi antara setiap pasangan simpul dalam komponen terhubung yang sama, yang kemudianFlatten
diedit menjadi satu grafik. Dengan demikian, baris 6 hingga 8 menentukan grafik rooky@r
dan grafik uskupy@b
.Akhirnya, garis 9 hingga 11 memilih elemen-elemen
{b, k, n, r}
yang menghasilkan jalur terpendek antara dua simpul target.FindShortestPath
akan melempar kesalahan dan mengembalikan yang tidak dievaluasi jika titik target tidak muncul dalam grafik (yang akan terjadi jika tidak ada tepi yang keluar dari itu), jadi kami gunakanh@__ -> 0
untuk kembali0
dalam kasus tersebut sebagai gantinya. Dan kurangnya jalur antara simpul yang valid mengembalikan daftar panjang0
, jadiMin[z~Complement~{0}]
hitung panjang jalur terkecil yang benar-benar ada, abaikan kasus buruk di atas.sumber
f
di sesi itu, tapi saya harus mengubahnya sebelum dikirim!