Gạch lát độc đáo trong một hình chữ nhật


13

Tôi đang xem Stackoverflow và thấy câu hỏi này về việc xếp hình chữ nhật MxN, và tôi nghĩ nó sẽ rất tuyệt khi chơi gôn. Đây là nhiệm vụ.

Với kích thước M và N, hãy viết chương trình xuất ra bao nhiêu cách duy nhất một hình chữ nhật MxN (N là số lượng hàng, không phải cột. Không phải là nó thực sự quan trọng) có thể được xếp theo các ràng buộc này.

  1. Tất cả các gạch là 2x1 hoặc 3x1
  2. Tất cả các ô nằm trong hàng của họ (tức là tất cả đều nằm ngang)
  3. Giữa hai hàng liền kề không nên được xếp thẳng hàng, ngoại trừ ở hai đầu
  4. M và N được đảm bảo ít nhất là 1

Ví dụ, một lát xếp hợp lệ của ma trận 8x3 sẽ là

  2    3     3
  |    |     |
  v    v     v
 _______________
|___|_____|_____| 
|_____|_____|___|
|___|_____|_____|

Nhưng sau đây sẽ không hợp lệ, vì các hàng thẳng hàng

  2    3     3
  |    |     |
  v    v     v
 _______________
|___|_____|_____| 
|_____|___|_____|
|_____|_____|___|

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

8x3: 4

3x1: 1

1x1: 0

9x4: 10

Mã golf, vì vậy câu trả lời ngắn nhất chiến thắng.


2
Mô tả của bạn về kích thước của gạch dường như sử dụng một quy ước khác với kích thước của hình chữ nhật. Là gạch thực sự 2x1hay 3x1? Ngoài ra là đầu ra cho 4x1số không?
FryAmTheEggman

1
Chào mừng bạn Khái niệm thử thách đẹp, tuy nhiên, tốt nhất là sử dụng hộp cát để dập tắt các ý tưởng thử thách trước khi đăng chúng lên chính.
Beefster

@FryAmTheEggman Có vẻ như OP đã cố gắng làm cho |s không đóng góp vào chiều dài của hàng, bằng cách sử dụng một đại diện như thế này (trong đó, nếu không có ống ( |), có một khoảng trắng).
Erik the Outgolfer


1
Câu hỏi tham khảo về SO không còn nữa.
Arnauld ngày

Câu trả lời:


5

Thạch , 20 byte

2*ḃ€2‘ÄṪ⁼¥Ƈ⁸ṗfƝẸ$€ċ0

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


Tôi biết tốc độ không phải là một phần của thông số kỹ thuật, nhưng điều này đã hết thời gian trên 11x10 khi chạy trên tio. Tôi muốn được giải thích để hiểu lý do tại sao.
Nick Kennedy

@NickKennedy Đó là một đầu vào quá lớn. Đối với chiều rộng 11, mỗi hàng có thể có một trong 9 độ nghiêng khác nhau. Đối với chiều rộng 11 và chiều cao 10, có 9¹⁰ = 3486784401 tường có thể, bao gồm cả những bức tường không hợp lệ. Đó là cách mà sức mạnh của Cartesian hoạt động. Rõ ràng, TIO không có thời gian để cho giải pháp của tôi tính toán toàn bộ mảng tường (thời gian hết sau 60 giây). Tôi sẽ thêm một lời giải thích khi tôi có thời gian.
Erik the Outgolfer

cảm ơn. Tôi đã xem thạch một chút, nhưng tại thời điểm này, tôi phụ thuộc vào các giải thích được nhận xét để hiểu mã của mọi người làm gì. Tôi đã giả sử đưa ra vấn đề thời gian rằng mã vũ phu của bạn buộc giải pháp, đó là một cách hợp lý để giảm thiểu các yêu cầu mã.
Nick Kennedy

Không quan tâm Tôi đã tạo lại trong Jelly phương thức trong mã R của tôi bằng cách sử dụng phần đầu tiên của mã. Đó là tại Dùng thử trực tuyến! và trong khi nó dài hơn đáng kể so với của bạn, nó xử lý số lượng lớn hơn. Lưu ý rằng hiện tại nó không xử lý đúng 1 hàng. Tôi nghi ngờ nó có thể ngắn gọn hơn nhiều, nhưng tôi chưa quen với Jelly.
Nick Kennedy

4

JavaScript (ES6),  119 110 106 96  91 byte

(N,M)

f=(n,m,p=0,g=(w,h=x=>g(p[g[w-=x]=1,w]||w)*g[w]--)=>w>3?h(2)+h(1):w>1&&f(n,m-1,g))=>m?g(n):1

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

Đã bình luận

gfhg

f = (                    // f is a recursive function taking:
  n,                     //   n = number of columns
  m,                     //   m = number of rows
  p = 0,                 //   p = object holding the previous row
  g = (                  //   g = recursive function taking:
    w,                   //     w = remaining width that needs to be filled in the
                         //         current row
    h = x =>             //     h = helper function taking x
                         // h body:
      g(                 //   recursive call to g:
        p[g[w -= x] = 1, //     subtract either 2 or 1 from w and mark this width as used
          w              //     test p[w]
        ]                //     pass p[w] if p[w] = 1 (which will force the next iteration
                         //     to fail immediately)
        || w             //     otherwise, pass w
      )                  //   end of recursive call
      * g[w]--           //   then restore g[w] to 0
  ) =>                   // g body:
    w > 3 ?              //   if w > 3, we need to insert at least 2 more bricks:
      h(2) + h(1)        //     invoke h with x = 2 and x = 1
    :                    //   else:
      w > 1              //     this is the last brick; we just check if it can be inserted
      &&                 //     abort if w is equal to 1 (a brick does not fit in there)
      f(                 //     otherwise, do a recursive call to f:
        n,               //       n is unchanged
        m - 1,           //       decrement m
        g                //       pass g as the new reference row
      )                  //     end of recursive call
) =>                     // f body:
  m ? g(n) : 1           //   yield 1 if we made it to the last row or call g otherwise

1

R , 243 231 byte

function(m,n,i=2*0:(m%/%6)+m%%2,j=i+(m-3*i)/2,M=Map)`if`(m<2,0,sum((e=eigen(lengths(outer(p<-unlist(M(M,list(function(x,y)cumsum(2+1:y%in%x)),M(combn,j,i,s=F),j),F),p,Vectorize(intersect)))<2))$ve%*%diag(e$va^(n-1))%*%solve(e$ve)))

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

Phiên bản có ngắt dòng:

function(m,n,i=2*0:(m%/%6)+m%%2,j=i+(m-3*i)/2,M=Map)`if`(m<2,0,
sum((e=eigen(lengths(outer(p<-unlist(M(M,list(function(x,y)cumsum(2+1:y%in%x)),
M(combn,j,i,s=F),j),F),p,Vectorize(intersect)))<2))$ve%*%diag(e$va^(n-1))%*%solve(e$ve)))

Lưu ý không có đệ quy và xử lý các giá trị khá lớn của m và n (ví dụ: 24x20 -> 3,3e19)

Đây là một câu trả lời được nhận xét hoạt động ít nhiều giống như trên, nhưng tôi đã không kiểm tra tất cả các chức năng để nó thực sự có thể đọc được:

f <- function(m,n) {
  # First work out what potential combinations of 2s and 3s add up to m
  i <- 2*0:(m %/% 6) + m %% 2 # Vector with numbers of possible 3s
  j <- i + (m - 3 * i) / 2 # Vector with total number of 2s and 3s
  if (m < 2) {
    0 # If wall less than 2 wide, no point in continuing because answer is 0
  } else {
    # Work out all possible positions of threes for each set
    positions_of_threes <- Map(combn, j, i, simplify = FALSE)
    # Function to work out the cumulative distance along the wall for a given
    # Set of three positions and number of bricks
    make_cumulative_bricks <- function(pos_threes, n_bricks) {
      bricks <- 1:n_bricks %in% pos_threes
      cumsum(2 + bricks)
    }
    # Find all possible rows with cumulative width of wall
    # Note because this is a `Map` with depth two that needs to be vectorised
    # for both `positions_of_threes` and `j`, and we're using base R, the
    # function `make_cumulative_bricks` needs to be placed in a list
    cum_bricks <- Map(Map, list(make_cumulative_bricks), positions_of_threes, j)
    # Finally we have the list of possible rows of bricks as a flat list
    cum_bricks_unlisted <- unlist(cum_bricks, recursive = FALSE)
    # Vectorise the intersect function
    intersect_v <- Vectorize(intersect, SIMPLIFY = FALSE)
    # Find the length of all possible intersects between rows
    intersections <- outer(cum_bricks_unlisted, cum_bricks_unlisted, intersect_v)
    n_intersections <- lengths(intersections)
    # The ones not lined up will only have a single intersect at `m`
    not_lined_up <- n_intersections == 1
    # Now use method described at /programming//a/9459540/4998761
    # to calculate the (matrix of TRUE/FALSE for lined-up) to the power of `n`
    eigen_nlu <- eigen(not_lined_up)
    final_mat <- eigen_nlu$vectors %*%
      diag(eigen_nlu$values ^ (n - 1)) %*%
      solve(eigen_nlu$vectors)
    # The sum of this matrix is what we're looking for
    sum(final_mat)
  }
}
f(20,20)

Phương pháp lấy một ma trận và liên tục nhân nó với một câu hỏi trên stackoverflow . Cách tiếp cận này hoạt động ở đây vì nó tính toán hiệu quả số lượng nhánh tích lũy thông qua các hàng gạch có thể khác nhau.

Nếu các gói bên ngoài được cho phép, tôi có thể giảm xuống còn 192:

function(m,n,i=2*0:(m%/%6)+m%%2,j=i+(m-3*i)/2,M=purrr::map2)`if`(m<2,0,sum(expm::`%^%`(lengths(outer(p<-unlist(M(M(j,i,combn,s=F),j,M,~cumsum(2+1:.y%in%.)),F),p,Vectorize(intersect)))<2,n-1)))

1

Thạch , 26 byte

2*ḃ€2‘ÄṪ⁼¥Ƈ⁸œ&L¬ɗþ`æ*⁴’¤SS

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

Hỏng:

Tạo một danh sách các bức tường có thể dưới dạng tổng tích lũy với phần cuối bị xóa:

2*ḃ€2‘ÄṪ⁼¥Ƈ⁸

Tìm bảng bên ngoài của tất cả các bức tường có thể với nhau mà không có bất kỳ giao điểm nào:

œ&L¬ɗþ`

Đưa ma trận này lên sức mạnh của (N-1) và sau đó tổng hợp lại:

æ*⁴’¤SS

Sử dụng bit đầu tiên từ câu trả lời của @ EriktheOutgolfer để tạo danh sách các bức tường có thể, sau đó sử dụng giao điểm ma trận và phương pháp lũy thừa ma trận từ câu trả lời R của tôi. Như vậy, nó hoạt động tốt ngay cả với chữ N. Đây là câu trả lời Jelly đầu tiên của tôi và tôi nghi ngờ nó có thể được đánh gôn nhiều hơn. Tôi cũng lý tưởng muốn thay đổi phần đầu tiên để các yêu cầu về thời gian và bộ nhớ không tăng theo cấp số nhân với M.


0

05AB1E , 42 byte

Åœʒ23yåP}€œ€`Ùε.¥¦¨}IиI.ÆÙεøyíø‚€€üQOO_P}O

Tôi gần như quá xấu hổ khi đăng bài này, và nó chắc chắn có thể được chơi bởi A RẤT bằng một cách tiếp cận khác, nhưng vì phải mất một thời gian để hoàn thành, tôi quyết định đăng nó xuống và chơi golf từ đây. Thử thách có vẻ dễ hơn so với imo, nhưng tôi chắc chắn đang sử dụng một cách tiếp cận sai ở đây và tôi có cảm giác 05AB1E có thể thực hiện khoảng 25 byte ..

Hãy thử trực tuyến. LƯU Ý: Không chỉ dài, nó còn không hiệu quả, vì 9x4trường hợp thử nghiệm chạy trong khoảng 40 giây trên TIO ..

Giải trình:

Ŝ             # Get all possible ways to sum to the (first) implicit input
               #  i.e. 8 → [[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,2],[1,1,1,1,1,3],[1,1,1,1,2,2],[1,1,1,1,4],[1,1,1,2,3],[1,1,1,5],[1,1,2,2,2],[1,1,2,4],[1,1,3,3],[1,1,6],[1,2,2,3],[1,2,5],[1,3,4],[1,7],[2,2,2,2],[2,2,4],[2,3,3],[2,6],[3,5],[4,4],[8]]
  ʒ23yåP}      # Only leave those consisting of 2s and/or 3s
               #  → [[2,2,2,2],[2,3,3]]
         €œ    # For each: get all permutations
           €`  # Flatten this list of lists once
             Ù # And uniquify it (leaving all possible distinct rows of bricks)
               #  → [[2,2,2,2],[3,3,2],[3,2,3],[2,3,3]]
ε    }         # For each:
             #  Get the cumulative sum
   ¦¨          #  With the leading 0 and trailing first input removed
               #   → [[2,4,6],[3,6],[3,5],[2,5]]
      Iи       # Repeat this list the second input amount of times
               #  i.e. 3 → [[2,4,6],[3,6],[3,5],[2,5],[2,4,6],[3,6],[3,5],[2,5],[2,4,6],[3,6],[3,5],[2,5]]
        I    # Get all combinations of lists the size of the second input
           Ù   # And uniquify the result (leaving all possible distinct walls)
               #  → [[[2,4,6],[3,6],[3,5]],[[2,4,6],[3,6],[2,5]],[[2,4,6],[3,6],[2,4,6]],[[2,4,6],[3,6],[3,6]],[[2,4,6],[3,5],[2,5]],[[2,4,6],[3,5],[2,4,6]],[[2,4,6],[3,5],[3,6]],[[2,4,6],[3,5],[3,5]],[[2,4,6],[2,5],[2,4,6]],[[2,4,6],[2,5],[3,6]],[[2,4,6],[2,5],[3,5]],[[2,4,6],[2,5],[2,5]],[[2,4,6],[2,4,6],[3,6]],[[2,4,6],[2,4,6],[3,5]],[[2,4,6],[2,4,6],[2,5]],[[2,4,6],[2,4,6],[2,4,6]],[[3,6],[3,5],[2,5]],[[3,6],[3,5],[2,4,6]],[[3,6],[3,5],[3,6]],[[3,6],[3,5],[3,5]],[[3,6],[2,5],[2,4,6]],[[3,6],[2,5],[3,6]],[[3,6],[2,5],[3,5]],[[3,6],[2,5],[2,5]],[[3,6],[2,4,6],[3,6]],[[3,6],[2,4,6],[3,5]],[[3,6],[2,4,6],[2,5]],[[3,6],[2,4,6],[2,4,6]],[[3,6],[3,6],[3,5]],[[3,6],[3,6],[2,5]],[[3,6],[3,6],[2,4,6]],[[3,6],[3,6],[3,6]],[[3,5],[2,5],[2,4,6]],[[3,5],[2,5],[3,6]],[[3,5],[2,5],[3,5]],[[3,5],[2,5],[2,5]],[[3,5],[2,4,6],[3,6]],[[3,5],[2,4,6],[3,5]],[[3,5],[2,4,6],[2,5]],[[3,5],[2,4,6],[2,4,6]],[[3,5],[3,6],[3,5]],[[3,5],[3,6],[2,5]],[[3,5],[3,6],[2,4,6]],[[3,5],[3,6],[3,6]],[[3,5],[3,5],[2,5]],[[3,5],[3,5],[2,4,6]],[[3,5],[3,5],[3,6]],[[3,5],[3,5],[3,5]],[[2,5],[2,4,6],[3,6]],[[2,5],[2,4,6],[3,5]],[[2,5],[2,4,6],[2,5]],[[2,5],[2,4,6],[2,4,6]],[[2,5],[3,6],[3,5]],[[2,5],[3,6],[2,5]],[[2,5],[3,6],[2,4,6]],[[2,5],[3,6],[3,6]],[[2,5],[3,5],[2,5]],[[2,5],[3,5],[2,4,6]],[[2,5],[3,5],[3,6]],[[2,5],[3,5],[3,5]],[[2,5],[2,5],[2,4,6]],[[2,5],[2,5],[3,6]],[[2,5],[2,5],[3,5]],[[2,5],[2,5],[2,5]]]
ε              # Map all walls `y` to:
 ø             #  Zip/transpose; swapping rows and columns
 yí            #  Reverse each row in a wall `y`
   ø           #  Also zip/transpose those; swapping rows and columns
              #  Pair both
              #  For both:
              #   For each column:
    ü          #    For each pair of bricks in a column:
     Q         #     Check if they are equal to each other (1 if truthy; 0 if falsey)
    O          #    Then take the sum of these checked pairs for each column
   O           #   Take the sum of that entire column
   _           #   Then check which sums are exactly 0 (1 if 0; 0 if anything else)
   P           #   And check for which walls this is only truthy by taking the product
}O             # After the map: sum the resulting list
               # (and output it implicitly as result)

0

Than , 89 byte

Nθ⊞υ⟦⟧≔⟦⟧ηFυF⟦²¦³⟧«≧⁺∧Lι§ι⁰κ¿⁼κθ⊞ηι¿‹κθ⊞υ⁺⟦κ⟧ι»≔Eη⟦ι⟧ζF⊖N«≔ζι≔⟦⟧ζFιFη¿¬⊙§κ⁰№λμ⊞ζ⁺⟦λ⟧κ»ILζ

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Hoạt động cho các hình chữ nhật có kích thước lên tới khoảng 12 trên TIO, nhưng có thể được thực hiện nhanh hơn khoảng ba lần với chi phí 2 byte bằng cách sử dụng phép xoay bit thay vì giao điểm danh sách. Giải trình:

Nθ

Nhập chiều rộng.

⊞υ⟦⟧

Bắt đầu với một hàng không có gạch.

≔⟦⟧η

Bắt đầu không có hàng hoàn thành.

Fυ

Vòng qua các hàng.

F⟦²¦³⟧«

Vòng qua các viên gạch.

≧⁺∧Lι§ι⁰κ

Thêm chiều rộng gạch cho chiều rộng hàng hiện tại.

¿⁼κθ⊞ηι

Nếu điều này dẫn đến chiều rộng đầu vào thì thêm hàng này vào danh sách các hàng đã hoàn thành.

¿‹κθ⊞υ⁺⟦κ⟧ι»

Mặt khác, nếu giá trị này vẫn nhỏ hơn chiều rộng đầu vào thì hãy thêm hàng mới vào danh sách các hàng, do đó làm cho nó được chọn bởi một lần lặp sau.

≔Eη⟦ι⟧ζ

Lập danh sách các bức tường của một hàng.

F⊖N«

Vòng lặp trên một ít hơn chiều cao.

≔ζι

Lưu danh sách các bức tường.

≔⟦⟧ζ

Xóa danh sách các bức tường.

Fι

Vòng qua danh sách các bức tường được lưu.

Fη

Vòng qua các hàng đã hoàn thành.

¿¬⊙§κ⁰№λμ⊞ζ⁺⟦λ⟧κ»

Nếu hàng có thể được thêm vào bức tường này thì hãy thêm nó vào danh sách các bức tường.

ILζ

Xuất chiều dài của danh sách cuối cùng của các bức tường.

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.