Con rắn đó đi đâu?


35

Viết hàm (sử dụng càng ít byte càng tốt) lấy một mảng hai chiều của bất kỳ số lượng cột và hàng nào trong đó:

  • 0 đại diện cho khối trống,
  • 1 đại diện cho khối rắn.

Hàm phải trả về số đường có thể mà con rắn đi được.

Ví dụ 1:

Đầu vào:

[
  [1,1,1,1,1],
  [0,0,0,0,1],
  [0,0,0,0,1],
]

Đầu ra: 2

Trong ví dụ trên, hàm sẽ trả về 2vì câu trả lời là một trong những:

nhập mô tả hình ảnh ở đây

Ví dụ 2:

Đầu vào:

[
  [1,1,1,1],
  [0,0,1,1],
  [0,0,1,1],
]

Đầu ra: 6

Trong ví dụ này, hàm sẽ trả về 6vì câu trả lời là một trong những:

nhập mô tả hình ảnh ở đây

Chú thích:

Khi đánh giá đầu vào, bạn có thể giả sử rằng:

  • Các mảng đại diện cho các cột sẽ luôn có cùng kích thước (vì vậy các mảng là hình chữ nhật);
  • Có ít nhất 1 đường dẫn hợp lệ;
  • Con rắn không thể đi qua các cạnh (như có thể xảy ra trong một số phiên bản của con rắn);
  • Con rắn sẽ luôn có ít nhất 2 khối;
  • Con rắn không thể di chuyển theo đường chéo;
  • Các đường dẫn được định hướng. (vì vậy, hai đường dẫn kết thúc tại các vị trí khác nhau nhưng nhìn khác giống hệt nhau không phải là cùng một đường dẫn, nó sẽ cộng vào tổng số)

13
Chào mừng đến với PPCG! Thử thách đầu tiên tốt đẹp.
Laikoni

5
Lưu ý nhỏ: "Sẽ luôn có ít nhất một hàng và một cột" là dự phòng, với điều kiện là con rắn sẽ luôn có ít nhất 2 khối.
Stewie Griffin

2
Các trường hợp thử nghiệm được đề xuất: một trường hợp được đưa ra bởi @StewieGriffin và [[0,0,1,1],[0,0,1,1],[0,0,1,1]]. Hầu hết các câu trả lời cho 16, nhưng một cho 15
Kevin Cruijssen

2
Có vẻ như tất cả mọi người cho đến nay (bao gồm cả tôi) đã đưa ra giả định rằng 2 đường dẫn kết thúc ở các vị trí khác nhau nhưng nhìn khác giống hệt nhau không phải là cùng một đường dẫn. Tôi nghĩ rằng điều này cần phải được xác định rõ ràng.
Arnauld

2
@Arnauld - đúng vậy. Hai đường dẫn kết thúc tại các vị trí khác nhau nhưng mặt khác trông giống hệt nhau không phải là cùng một đường dẫn , nó sẽ cộng vào tổng số. Trong ví dụ của bạn, tổng số phải là 16 nếu tôi không nhầm - Tôi không thể tính toán chính xác ngay bây giờ nhưng bạn có được điểm
Adelin

Câu trả lời:


11

Ngôn ngữ Wolfram (Mathicala) , 16 + 83 = 99 byte

Câu lệnh nhập thư viện (16 byte):

<<Combinatorica`

Thân hàm thực tế (83 byte):

Length@HamiltonianCycle[MakeGraph[#~Position~1~Join~{1>0},##||Norm[#-#2]==1&],All]&

Hãy thử trực tuyến!


Lưu ý rằng câu hỏi chỉ cần hỏi số lượng đường dẫn Hamilton trong biểu đồ.

Tuy nhiên, (vì một số lý do) HamiltonianPathhàm không thực sự hoạt động với đồ thị có hướng ( ví dụ ). Vì vậy, tôi đã sử dụng cách giải quyết được mô tả trong câu hỏi Mathicala.SE này :

  • Thêm một đỉnh (được gọi True) được kết nối với tất cả các đỉnh khác.
  • Đếm số chu kỳ Hamilton trên biểu đồ kết quả.

Biểu đồ được xây dựng bằng cách sử dụng MakeGraph(thật khó chịu là không có tích hợp tương đương trực tiếp), sử dụng hàm boolean ##||Norm[#-#2]==1&, trả về Truekhi và chỉ khi một trong các đối số là Truehoặc khoảng cách giữa hai đỉnh là 1.


Tr[1^x]không thể được sử dụng thay thế Length@x<2không thể được sử dụng thay thế ==1.


HamiltonianPathcó thể được sử dụng nếu đồ thị không bị ảnh hưởng, với thân hàm mất 84 byte (chính xác hơn 1 byte so với đệ trình hiện tại):

Length@HamiltonianPath[MakeGraph[#~Position~1,Norm[#-#2]==1&,Type->Undirected],All]&

Hãy thử trực tuyến!


10

JavaScript (ES6), 154 134 byte

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>r&&r[x]&&[-1,0,1,2].map(d=>r[r[x]=0,/1/.test(m)?g(_,x+d%2,y+~-d%2):++n,x]=1)),n=0)|n/4

Hãy thử trực tuyến!

Làm sao?

phương pháp

Bắt đầu từ mỗi ô có thể, chúng tôi lấp đầy ma trận, xóa tất cả các ô trên đường đi của chúng tôi. Bất cứ khi nào ma trận không chứa nhiều hơn 1 , chúng ta sẽ tăng số n của các đường dẫn có thể.

Mỗi đường dẫn hợp lệ được tính 4 lần vì hướng được chọn trên ô cuối cùng, điều này thực sự không quan trọng. Do đó, kết quả cuối cùng là n / 4 .

Hàm đệ quy

Thay vì gọi hàm đệ quy g () từ hàm gọi lại của bản đồ thứ hai () như thế này ...

m=>m.map((r,y)=>r.map((_,x)=>(g=(x,y,r=m[y])=>...g(x+dx,y+dy)...)(x,y)))

... chúng tôi xác định hàm đệ quy g () trực tiếp là hàm gọi lại của map () :

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>...g(_,x+dx,y+dy)...))

Mặc dù công thức khá dài y=1/y?y:Ycần thiết để đặt giá trị ban đầu của y , nhưng điều này sẽ tiết kiệm được 2 byte tổng thể.

Mã nhận xét

m =>                           // given the input matrix m[][]
  m.map((r, Y) =>              // for each row r[] at position Y in m[][]:
    r.map(g = (                //   for each entry in r[], use g() taking:
      _,                       //     - the value of the cell (ignored)
      x,                       //     - the x coord. of this cell
      y,                       //     - either the y coord. or an array (1st iteration),
                               //       in which case we'll set y to Y instead
      r = m[y = 1 / y ? y : Y] //     - r = the row we're currently located in
    ) =>                       //       (and update y if necessary)
      r && r[x] &&             //     do nothing if this cell doesn't exist or is 0
      [-1, 0, 1, 2].map(d =>   //     otherwise, for each direction d,
        r[                     //     with -1 = West, 0 = North, 1 = East, 2 = South:
          r[x] = 0,            //       clear the current cell
          /1/.test(m) ?        //       if the matrix still contains at least one '1':
            g(                 //         do a recursive call to g() with:
              _,               //           a dummy first parameter (ignored)
              x + d % 2,       //           the new value of x
              y + ~-d % 2      //           the new value of y
            )                  //         end of recursive call
          :                    //       else (we've found a valid path):
            ++n,               //         increment n
          x                    //       \_ either way,
        ] = 1                  //       /  do r[x] = 1 to restore the current cell to 1
      )                        //     end of map() over directions
    ),                         //   end of map() over the cells of the current row
    n = 0                      //   start with n = 0
  ) | n / 4                    // end of map() over the rows; return n / 4

10

Thạch , 12 11 byte

ŒṪŒ!ạƝ€§ÐṂL

Hãy thử trực tuyến!


Giải trình.

ŒṪ               Positions of snake blocks.
  Œ!             All permutations.
                 For each permutation:
    ạƝ€             Calculate the absolute difference for each neighbor pair
       §            Vectorized sum.
                 Now we have a list of Manhattan distance between snake
                    blocks. Each one is at least 1.
        ÐṂL      Count the number of minimum values.
                    Because it's guaranteed that there exists a valid snake,
                    the minimum value is [1,1,1,...,1].

Các tính năng mới chứng tỏ là vô cùng hữu ích.
dùng202729

Làm thế nào về §ỊMLthay vì §ỊP€Sđể tiết kiệm một byte - tôi nghĩ rằng nó nên hoạt động?
Jonathan Allan

... hoặc §ÐṂLnhanh hơn một chút.
Jonathan Allan

@Jonathan ALLan Chỉ hoạt động nếu kết quả là khác không.
dùng202729

@Jonathan ALLan Vì vậy, nó thực sự hoạt động.
dùng202729


5

Python 2, 158 byte

E=enumerate
g=lambda P,x,y:sum(g(P-{o},*o)for o in P if x<0 or abs(x-o[0])+abs(y-o[1])<2)+0**len(P)
lambda L:g({(x,y)for y,r in E(L)for x,e in E(r)if e},-1,0)

Hãy thử trực tuyến!


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.