Chu kỳ trên hình xuyến


20

Thử thách

Thách thức này sẽ giúp bạn viết một chương trình mà mất trong hai số nguyên nmvà kết quả đầu ra số vòng không giao nhau trên nbằng mhình xuyến làm bằng cách bắt đầu tại (0,0)và chỉ tiến hành các bước lên và sang phải. Bạn có thể nghĩ về hình xuyến như lưới với vòng bao quanh ở phía trên và phía dưới và ở hai bên.

Đây là nên ít byte nhất sẽ thắng.

Thí dụ

Ví dụ: nếu đầu vào là n=m=5, một bước hợp lệ là

(0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (2,3) -> (2,4) -> 
(2,0) -> (3,0) -> (4,0) -> (4,1) -> (4,2) -> (4,3) -> 
(0,3) -> (1,3) -> (1,4) -> 
(1,0) -> (1,1) -> (2,1) -> (3,1) -> (3,2) -> (3,3) -> (3,4) -> (4,4) -> 
(0,4) -> (0,0)

như thể hiện trong hình.

Một vòng lặp trên hình xuyến.

Một số ví dụ đầu vào / đầu ra

f(1,1) = 2 (up or right)
f(1,2) = 2 (up or right-right)
f(2,2) = 4 (up-up, up-right-up-right, right-right, right-up-right-up)
f(2,3) = 7
f(3,3) = 22
f(2,4) = 13
f(3,4) = 66
f(4,4) = 258

1
Tôi đã sẵn sàng đặt cược rằng chuỗi này đã có trên OEIS ít nhất là , nhưng dường như nó chưa (chưa). m= =n
Arnauld

Tôi nghĩ rằng một hình xuyến cũng có một vòng tròn bên trái. Thay vào đó chúng ta có nên giả sử nó chỉ có hướng lên xuống không? Hình ảnh ví dụ dường như không ngụ ý như vậy.
Erik the Outgolfer

@EriktheOutgolfer Hình ảnh hiển thị đường dẫn màu cam bao quanh từ phải sang trái phải không?
Arnauld

@Arnauld Có, nhưng nó không phù hợp với mô tả của thử thách ("Bạn có thể nghĩ hình xuyến như lưới với vòng bao quanh ở phía trên và phía dưới.")
Erik the Outgolfer

@EriktheOutgolfer Đó là sự thật. Và bây giờ bạn đề cập đến nó, con đường màu xanh là sai. Đầu tiên nên quay vòng từ phải sang trái và sau đó từ trên xuống dưới.
Arnauld

Câu trả lời:


4

Thạch , 28 byte

ạƝ§=1Ȧ
²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL

Một liên kết đơn âm chấp nhận một danh sách, [m,n]mang lại số lượng.

TIO-jt1qe1v9 ... mặc dù có rất ít điểm, nhưng nó quá kém hiệu quả.
(Tôi thậm chí không thể chạy[2,3]cục bộ với ram 16 GB)!

Làm sao?

Brute force - tạo tọa độ của phiên bản lát gạch đủ lớn sau đó lọc tập hợp sức mạnh của các điểm này cho các đường dẫn đó với các đường lân cận chỉ tăng một theo một hướng, sau đó lọc đến các điểm bắt đầu ở tọa độ tối thiểu (ví dụ gốc) và, đồng thời, loại bỏ tọa độ bắt đầu này từ mỗi. Sau đó, sử dụng số học modulo để bọc lại hình xuyến và lọc ra bất kỳ tọa độ trùng lặp nào (nghĩa là các tọa độ có chứa giao điểm) và cuối cùng, lọc đến các tọa độ có tọa độ kết thúc tối thiểu (nghĩa là kết thúc ở gốc) và mang lại độ dài kết quả.

ạƝ§=1Ȧ - Link 1: all neighbours differ by 1 in exactly one direction
 Ɲ     - for neighbours:
ạ      -   absolute difference
  §    - sum each
   =1  - equal to one (vectorises)
     Ȧ - any and all? (falsey if empty or contains a falsey value when flattened)

²‘p/’ŒPÇƇḢÐṂ%⁸QƑƇṪÐṂL - Main Link: list of integers, [m,n]
²                     - square (vectorises) -> [m*m, n*n]
 ‘                    - increment (vectorises) -> [m*m+1, n*n+1]
   /                  - reduce with:
  p                   -   Cartesian product
    ’                 - decrement (vectorises) -> all the coordinates of an m*m by n*n grid
                      -                           including [0, 0] and [m*m, n*n] 
     ŒP               - power-set -> all paths going either up OR right at each step, but not
                      -              necessarily by only 1, and
                      -              necessarily both up and right (e.g. [...[1,3],[5,7],[6,2],...])
        Ƈ             - filter keep those for which:
       Ç              -   call last Link (1) as a monad
                      -              ...now all remaining paths do only go in steps
                      -              of one up or one right
          ÐṂ          - filter keep those minimal under:
         Ḣ            -   head - removes the 1st coordinate from each and yields them for the filter
                      -          ...so only those which started at [0,0] but without it
            %⁸        - modulo by the left argument ([m,n]) (vectorises)
                Ƈ     - filter keep those for which:
               Ƒ      -   is invariant when:
              Q       -     de-duplicated
                      -          ...so no repetitions of torus coordinates (and we already removed
                      -          the first [0,0] which must be present exactly twice)
                  ÐṂ  - filter keep those minimal under:
                 Ṫ    -   tail
                      -          ...so only those which ended at [0,0] 
                    L - length

12

Python 2 , 87 byte

f=lambda m,n,z=0,l=[]:z==0if z in l else sum(f(m,n,(z+d)%m%(n*1j),l+[z])for d in(1,1j))

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

Điều thú vị ở đây là sử dụng một số phức zđể lưu trữ tọa độ của vị trí hiện tại. Chúng ta có thể di chuyển lên bằng cách thêm 1và di chuyển sang phải bằng cách thêm 1j. Thật ngạc nhiên, modulo hoạt động trên các số phức theo cách cho phép chúng ta xử lý gói riêng cho từng chiều: thực hiện %mcác hành động trên phần thực và %(n*1j)hành động trên phần ảo.


Hoàn thành tốt FWIW, nỗ lực tốt nhất của tôi mà không sử dụng số phức là 91 byte trong Python 3.8.
Arnauld

@Arnauld Ý tưởng thú vị với k:=x+y*m. Nó làm cho tôi tự hỏi nếu nó sẽ ngắn hơn để sử dụng ktrực tiếp cho (x,y), sử dụng x+y*mchứ không phải là x+y*1j. Quá tệ Python 3 không cho phép mô đun phức tạp.
xnor


Cách tiếp cận này tiết kiệm 5 byte trong JS. :)
Arnauld

7

JavaScript (ES6), 67 byte

m×n<32

Đưa đầu vào là (m)(n).

m=>n=>(g=(k,l)=>l>>k&1?!k:g((k+m)%(m*n),l|=1<<k)+g(k-~k%m-k%m,l))``

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

Để nó hoạt động cho mọi đầu vào, chúng ta có thể sử dụng BigInt cho 73 byte :

m=>n=>(g=(k,l=k)=>l&(b=1n<<k)?!k:g((k+m)%(m*n),l|=b)+g(k-~k%m-k%m,l))(0n)

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


JavaScript (ES6),  76 73  72 byte

Đưa đầu vào là (m)(n).

m=>n=>(g=(x,y)=>g[x+=y*m]?!x:g(-~x%m,y,g[x]=1)+g(x%m,-~y%n)+--g[x])(0,0)

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

Đã bình luận

m => n => (         // m = width; n = height
  g = (             // g is a recursive function taking:
        x, y        //   the current coordinates (x, y) on the torus
      ) =>          //
    g[              // the surrounding object of g is also used for storage
      x += y * m    // turn x into a key for the current coordinates
    ] ?             // if this cell was already visited:
      !x            //   return 1 if we're back to (0, 0), or 0 otherwise
    :               // else:
      g(            //   first recursive call:
        -~x % m,    //     move to the right
        y,          //     leave y unchanged
        g[x] = 1    //     mark the current cell as visited by setting the flag g[x]
      ) +           //   add the result of
      g(            //   a second recursive call:
        x % m,      //     restore x in [0...m-1]
        -~y % n     //     move up
      ) +           //
      --g[x]        //   clear the flag on the current cell
)(0, 0)             // initial call to g with (x, y) = (0, 0)

3

Haskell, 88 80 byte

n#m|let(x!y)a|elem(x,y)a=0^(x+y)|b<-(x,y):a=(mod(x+1)n!y)b+(x!mod(y+1)m)b=0!0$[]

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

Lực lượng vũ phu đơn giản: thử tất cả các kết hợp lên / xuống, thả những điểm giao nhau (chúng tôi giữ tất cả các vị trí chúng tôi đã truy cập trong danh sách a) và đếm những vị trí cuối cùng lại đạt được trạng thái tích cực (0,0).

Trường hợp cơ bản của đệ quy là khi chúng ta truy cập một vị trí lần thứ hai ( elem(x,y)a). Kết quả là 0^0= 1khi vị trí là (0,0)và được tính vào số vòng lặp hoặc 0( 0^x, với xkhác không) và không làm tăng số vòng lặp.

Chỉnh sửa: -8 byte nhờ @xnor.


1
Các trường hợp cơ sở có thể được kết hợp thành |elem(x,y)a=0^(x+y), và (0!0)[]có thể 0!0$[].
xnor



1

CJam (50 ký tự)

q~]:M:!a{9Yb2/\f{_W=@.+M.%a+_)a#g"WAR"=~}}:R~e_We=

Bản demo trực tuyến . Đây là một chương trình có hai đầu vào từ stdin.

Cuối cùng, chúng tôi có câu trả lời cho câu hỏi

Chiến tranh, huh, nó tốt cho cái gì?


Mổ xẻ

q~]:M        e# Parse input, collect in array, store in M (for moduli)
:!a          e# Zero and wrap in array for starting position (0, 0)
{            e# Define recursive block R
  9Yb2/      e#   Push [[1 0][0 1]], an array of movements
  \f{        e#   For each of those movements, with the current path,
    _W=@.+   e#     Add the movement to the last position in the path
    M.%      e#     Apply the wrapping
    a+       e#     Add to one copy of the path
    _)a#     e#     And find its index in another copy
    g"WAR"=~ e#     Switch on the sign of the index:
             e#       If the sign is -1, position not found, make a recursive call
             e#       If the sign is 0, found at start, push -1 to the stack
             e#       If the sign is 1, we have a self-intersection. We push 10 to
             e#       the stack for no other reason than to make the bad joke above
  }
}:R
~            e# Execute R
e_We=        e# Count the -1s which we pushed as sentinels

1

Thạch , 54 39 byte

ḣ2æ.2ị³¤+4
‘Ç;¥¦%³Ç=4ƊÑÇị$?
çⱮؽS
’Ñ0xÇ

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

Tôi đã đăng bài này như một câu trả lời riêng cho Jelly khác của tôi vì đây là một phương pháp hoàn toàn khác. Đây là nguyên tắc gần hơn với câu trả lời của @ Arnauld. Nó sử dụng một hàm đệ quy hoạt động thông qua mọi đường dẫn có thể cho đến khi đạt đến điểm mà nó đã đạt được, và sau đó trả về kết quả kiểm tra xem nó có trở lại điểm bắt đầu hay không. Tôi nghi ngờ một vài byte có thể được cạo đi. Bây giờ đổi thành sử dụng toán tử lát. Nó hoạt động tốt cho đến 5x5. Độ sâu đệ quy nên nhiều nhất là mx 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.