Catur endgame: Putih ke Mate dalam Satu

19

Dengan kisi 8x8 huruf yang mewakili kondisi permainan catur saat ini, tugas program Anda adalah menemukan langkah selanjutnya untuk warna putih yang menghasilkan skakmat (jawabannya akan selalu menjadi pasangan dalam satu langkah).

Memasukkan

Masukan akan di STDIN - 8 baris masing-masing 8 karakter. Arti masing-masing karakter adalah sebagai berikut:

K/k - king
Q/q - queen
B/b - bishop
N/n - knight
R/r - rook
P/p - pawn
- - empty square

Huruf besar mewakili potongan putih, dan huruf kecil mewakili hitam. Papan akan berorientasi sehingga putih diputar dari bawah dan hitam diputar turun dari atas.

Keluaran

Langkah untuk putih yang menghasilkan skakmat, notasi aljabar . Anda tidak perlu memberi tahu kapan sebuah karya telah diambil, Anda juga tidak perlu khawatir tentang disambiguasi antara dua bagian yang identik yang dapat membuat langkah yang sama.

Masukan sampel

Contoh 1

Memasukkan:

------R-
--p-kp-p
-----n--
--PPK---
p----P-r
B-------
--------
--------

Keluaran:

c6

Contoh 2

Memasukkan:

--b-r--r
ppq-kp-p
-np-pn-B
--------
---N----
--P----P
PP---PP-
R--QRBK-

Keluaran:

Nf5

Contoh 3

Memasukkan:

---r-nr-
-pqb-p-k
pn--p-p-
R-------
--------
-P-B-N-P
-BP--PP-
---QR-K-

Keluaran:

Rh5

Anda dapat mengasumsikan bahwa solusinya tidak akan melibatkan castling atau en-passant.

Ini adalah kode-golf - solusi terpendek menang.

(Contoh diambil dari mateinone.com - puzzle 81, 82 dan 83)

Gareth
sumber
Tidak. Saya pikir untuk keperluan pertanyaan ini Anda dapat mengasumsikan bahwa jawabannya tidak akan melibatkan castling atau en-passant. Saya akan memperbarui pertanyaan.
Gareth
Bagaimana seharusnya kita menangani posisi dengan lebih dari satu pasangan?
Rob
@Rob Hanya diperlukan satu solusi, jadi output solusi mana yang Anda temukan terlebih dahulu.
Gareth
Apakah aman untuk mengasumsikan bahwa solusinya tidak melibatkan promosi?
Peter Taylor
@ Peter Ya, saya tidak ingin terlalu mempersulit masalah.
Gareth

Jawaban:

7

Ruby, 589 512 510 499 493 karakter

R=0..7
a=->b{o=[];R.map{|r|R.map{|c|v=Hash[?K,[6,7,8,11,13,16,17,18],?R,s=[157,161,163,167],?B,t=[156,158,166,168],?Q,s+t,?N,[1,3,5,9,15,19,21,23],?P,[32,181,183]][z=b[r][c]];v&&v.map{|s|k=2!=l=s/25+1;u=r;v=c;l.times{u+=s/5%5-2;v+=s%5-2;R===u&&R===v||break;t=b[u][v];j=t<?.&&l<8;(j||t=~/[a-z]/&&k)&&o<<=(h=b.map &:swapcase;h[u][v]=h[r][c];h[r][c]=?-;[z+"%c%d"%[97+v,8-u],h.reverse]);j&&(k||r==6)||break}}}};o}
a[$<.map{|l|l}].map{|m,b|a[b].any?{|f,x|a[x].all?{|g,y|y*""=~/K/}}||$><<m[/[^P]+/]}

Input diberikan melalui stdin, misalnya:

> ruby mateinone.rb
--------
--------
--------
-k------
b-------
-N-P----
--------
-----K-Q
^Z
Qb7

Outputnya bukan hanya satu gerakan yang memaksa pasangan dalam satu gerakan tetapi setiap gerakan yang melakukannya.

Sunting 1: Fungsi ehanya digunakan sekali jadi saya sebaris itu. Kedua, pengkodean sekarang didasarkan pada nomor 5 bukan 10. Dan refactoring kloning papan menghemat beberapa karakter.

Sunting 2: Masih tidak sebanyak perbaikan yang saya inginkan. Mengubah hash dari {a=>b,c=>d}menjadi Hash[a,b,c,d]. Biaya ini 4 karakter tetapi menyimpan satu per pasangan nilai kunci.

Sunting 3: Hanya pengurangan kecil: inlining M (4 karakter), t==?--> t<?.(2), menghapus Gadai dalam notasi aljabar di akhir (2), menggantikan put (3). Program ini sekarang kurang dari 500 karakter.

Sunting 4: Sangat menarik betapa banyak yang masih bisa ditemukan dalam program semacam itu. Memindahkan invarian di luar loop dan menemukan perhitungan duplikat lain.

Howard
sumber
Dengan "bukan satu, tetapi ada" maksud Anda "tidak harus satu, tetapi setiap"?
Matius Baca
@ Matius Anda benar. Maksud saya "setiap".
Howard
Anda bisa menggunakan [*$<]bukan $<.map{|l|l}.
Lowjacker