Cờ Trung Quốc di chuyển lâu nhất


12

Trong Cờ đam Trung Quốc , một mảnh có thể di chuyển bằng cách nhảy qua bất kỳ mảnh nào khác, hoặc bằng cách tạo ra một chuỗi các bước nhảy như vậy. Nhiệm vụ của bạn là tìm ra chuỗi hoa bia dài nhất có thể.

Đầu vào

Một chuỗi gồm 121 số không hoặc số 0, mỗi số đại diện cho một vị trí trên bảng. Số không có nghĩa là nơi trống rỗng; một trong những có nghĩa là nơi bị chiếm đóng. Các vị trí được liệt kê từ trái sang phải; từ trên xuống dưới. Ví dụ: đầu vào của thiết lập này sẽ là

1011110011000001000000000000000000000000100000000001000000000000000000000000000001000000000000000000000001000001100111111

Giải trình:

Vị trí trên cùng được chiếm bởi một mảnh màu xanh lá cây, vì vậy chữ số đầu tiên trong đầu vào là 1. Hàng thứ hai có một vị trí trống và sau đó một vị trí chiếm đóng, do đó 01tiếp theo. Hàng thứ ba là tất cả chiếm, vì vậy 111. Hàng thứ tư có hai khoảng trống và hai khoảng trống (đi từ trái sang phải), vì vậy 0011. Sau đó đến năm 0, một 1và bảy 0cho hàng tiếp theo, v.v.

Giống như trong thiết lập đó, có một góc chỉ thẳng lên. Có thể có bất kỳ số lượng các mảnh trên bảng (từ 1 đến 121). Lưu ý rằng các mảnh màu khác nhau không được đại diện khác nhau.

Đầu ra

Độ dài tối đa của một bước nhảy hợp pháp, sử dụng bất kỳ mảnh nào trên bảng. Bạn không thể truy cập cùng một địa điểm nhiều lần (bao gồm cả vị trí bắt đầu và kết thúc). Tuy nhiên, bạn có thể nhảy qua cùng một mảnh nhiều lần. Nếu không có hop hợp pháp, đầu ra0 . Không xem xét liệu có tồn tại một động thái phi hop hợp pháp.

Ví dụ: đầu ra cho thiết lập được mô tả ở trên là 3 .

Đầu vào và đầu ra có thể được thực hiện thông qua stdin và stdout, thông qua các đối số dòng lệnh, thông qua các lệnh gọi hàm hoặc bất kỳ phương thức tương tự nào.

Các trường hợp thử nghiệm

Đầu vào:

0100000010000000000000000100000000000000000000000000000001010010000000000000000000000101000000000000000000100000000100001

Đầu ra: 0(không có hai mảnh nằm cạnh nhau)


Đầu vào:

0000000000111100000000011100000000011000000000100000000000000000000000000000000000000000000000000000000000000000000000000

Đầu ra: 1(thiết lập ban đầu cho một người chơi ở góc trên bên trái)


Tôi chơi cái này với người dì tuyệt vời của tôi; cả hai chúng tôi đều tốt Đây là một thử thách thú vị.
cjfaure

1
Có lẽ bạn nên xác định rõ hơn về cách lưu trữ đầu vào / bit nào đi đến đâu.
TheDoctor

Những mảnh nào bạn có thể "nhảy qua"? Cách mà mẹ tôi và tôi thường chơi, bạn có thể nhảy qua bất kỳ mảnh nào ở một trong 6 hướng ở bất kỳ khoảng cách nào (đến vị trí đối diện của mảnh mà bạn nhảy qua) miễn là không có mảnh nào cản đường con đường cho hop đó. Những người khác chơi mà bạn chỉ có thể nhảy qua các mảnh liền kề.
Joe Z.

1
@TheDoctor Tôi đã thêm một lời giải thích chi tiết hơn.
Ypnypn

Bạn có thể làm rõ một chi tiết: tôi có được phép chiếm cùng một vị trí hai lần không? Tôi giả sử tôi không thể lặp vô hạn, nhưng nếu tôi có thể đánh một vị trí di chuyển sang trái sang phải và sau đó đánh lại nó di chuyển lên trái sang phải xuống thì nó sẽ mở ra các khả năng.
Pars Parsons

Câu trả lời:


1

Perl, 345 322

Biên tập: đánh golf, hơi.

Nhiều trường hợp thử nghiệm sẽ tốt hơn, nhưng bây giờ có vẻ như nó hoạt động. Tôi sẽ thêm ý kiến ​​sau nếu cần thiết. Với dòng mới và thụt lề cho dễ đọc:

$_=<>;
$s=2x185;
substr$s,(4,22,unpack'C5(A3)*','(:H[n129148166184202220243262281300')[$i++],0,$_ 
    for unpack A.join A,1..4,13,12,11,10,9..13,4,3,2,1;
$_=$s;
sub f{
    my(@a,%h)=@_;
    $h{$_}++&&return for@a;
    $-+=$#a>$-;
    $s=~/^.{$a[0]}$_/&&f($+[1],@a)
        for map{("(?=.{$_}1.{$_}(0))","(?<=(0).{$_}1.{$_}.)")}0,17,18
}
f$+[0]while/1/g;
print$-

Tôi đã thêm một vài trường hợp thử nghiệm.
Ypnypn

Những cái đó hoạt động tốt, nhưng chúng quá dễ dàng :-).
dùng2846289

2

C, 262 260

Mã được đánh dấu ( gỡ lỗi và khoảng trắng không cần thiết đã bị xóa. Đã thay đổi từ đầu vào qua stdin sang đầu vào qua dòng lệnh và tận dụng cơ hội để khai báo biến i ở đó. Chỉnh sửa mới nhất: mã được chuyển vào ngoặc củafor để lưu hai dấu chấm phẩy.)

t[420],j,l,x,y;f(p,d){int z,q,k;for(k=6;k--;t[q]&!t[p+z]?t[q]=0,f(q,d+1),t[q]=1:0)z="AST?-,"[k]-64,q=p+z*2;l=d>l?d:l;}main(int i,char**s){for(i=840;i--;x>3&y>5&x+y<23|x<13&y<15&x+y>13?i>420?t[i-420]=49-s[1][j++]:t[i]||f(i,0):0)x=i%20,y=i/20%21;printf("%d",l);}

Giải trình

Điều này phụ thuộc vào một bảng 20x21 trông giống như thế này, ban đầu chứa đầy các số 0 khi chương trình bắt đầu (nghệ thuật ASCII này được tạo bởi một phiên bản sửa đổi của chương trình và khi ivòng lặp đếm xuống, số 0 nằm ở góc dưới bên phải):

....................
....................
...............#....
..............##....
.............###....
............####....
.......#############
.......############.
.......###########..
.......##########...
.......#########....
......##########....
.....###########....
....############....
...#############....
.......####.........
.......###..........
.......##...........
.......#............
....................
....................

Vòng i chạy qua bảng này hai lần, sử dụng x và y để tính xem một hình vuông có thực sự thuộc về bàn cờ hay không (điều này đòi hỏi 6 bất đẳng thức riêng biệt trong x và y.)

Nếu có, lần đầu tiên, nó sẽ điền vào các ô vuông, đặt một 0(giả) cho một 1(chiếm) và một 1(trung thực) cho một0 (không có người). Sự đảo ngược này rất quan trọng, bởi vì tất cả các ô vuông nằm ngoài đã có 0, có nghĩa là chúng giống với các ô vuông bị chiếm đóng và rõ ràng chúng không thể bị nhảy vào, mà không cần kiểm tra cụ thể.

Vòng thứ hai, nếu hình vuông bị chiếm (chứa 0), nó gọi hàm ftìm kiếm các bước di chuyển.

f tìm kiếm đệ quy theo 6 hướng có thể được mã hóa bởi +/- 1 (ngang), +/- 20 (dọc) và +/- 19 (đường chéo) được mã hóa trong biểu thức "AST?-,"[k]-64 . Khi tìm thấy một lần truy cập, nó đặt ô đó thành 0 (bị chiếm) trước khi tự gọi đệ quy, sau đó đặt lại thành 1 (trống) khi hàm được trả về. Giá trị ô phải được thay đổi trước lệnh gọi đệ quy để tránh nhảy vào ô đó nhiều lần.

Mã mã

char s[999];                           //input string.
t[420],i,j,l,x,y;                      //t=board. i=board counter, j=input counter. l=length of longest hop found so far.

f(p,d){                                //p=position, d= recursion depth.
  //printf("%d,%d ",p,d);              //debug code: uncomment to show the nodes visited.
  int k,z,q;                           //k=counter,z=displacement,q=destination
  for(k=6;k--;)                        //for each direction
    z="AST?-,"[k]-64,                  //z=direction
    q=p+z*2,                           //q=destination cell
    t[q]&!t[p+z]?                      //if destination cell is empty (and not out of bounds) and intervening cell is full
      t[q]=0,f(q,d+1),t[q]=1           //mark destination cell as full, recurse, then mark it as empty again.
      :0;
  l=d>l?d:l;                           //if d exceeds the max recorded recursion depth, update l
}

main(){
  gets(s);                             //get input
  for(i=840;i--;)                      //cycle twice through t
    x=i%20,                            //get x
    y=i/20%21,                         //and y coordinates
    x>3&y>5&x+y<23|x<13&y<15&x+y>13?   //if they are in the bounds of the board
      i>420?
        t[i-420]=49-s[j++]             //first time through the array put 0 for a 1 and a 1 for a 0 ('1'=ASCII49)
        :t[i]||f(i,0)                  //second time, if t[i]=0,call f(). 
       //,puts("")                     //puts() formats debug output to 1 line per in-bounds cell of the board
      :0;
  printf("%d",l);                      //print output
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.