원환 체의 사이클


20

도전

이 문제는 두 정수에 걸리는 프로그램을 작성해야합니다 nm과의 숫자 교차하지 않는 루프를 출력 n으로 m부터 다음과 같은 방법으로 만든 원환 체 (0,0)만 단계를 복용하고 오른쪽에 있습니다. 원환 체 는 상단과 하단 및 측면에 랩 어라운드가 있는 그리드로 생각할 수 있습니다 .

이것은 이므로 가장 적은 바이트가 이깁니다.

예를 들어, 입력이 인 경우 n=m=5유효한 도보는

(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)

그림과 같이.

원환 체에 루프.

입 / 출력 예

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
=

나는 원환 체에도 왼쪽 오른쪽 랩 어라운드가 있다고 생각합니다. 대신 상향식 랩 어라운드 만 있다고 가정해야합니까? 예제 이미지는 그렇게 암시하지 않는 것 같습니다.
아웃 골퍼 에릭

@EriktheOutgolfer 이미지는 오른쪽에서 왼쪽으로 주황색 경로를 감 쌉니다. 그렇지 않습니까?
Arnauld

예 @Arnauld하지만 도전의 설명과 일치 보이지 않는 ( "당신은 랩 어라운드 상단과 하단 모두 그리드와 같은 토러스 생각할 수 있습니다.")
에릭 Outgolfer

@EriktheOutgolfer 사실입니다. 그리고 당신이 그것을 언급 했으므로, 푸른 길은 잘못되었습니다. 먼저 오른쪽에서 왼쪽으로, 그 다음 위에서 아래로 줄 바꿈해야합니다.
Arnauld

답변:


4

젤리 , 28 바이트

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

[m,n]카운트를 산출 하는리스트를 수락하는 모나드 링크 .

TIO-jt1qe1v9 ... 점은 적지 만 너무 비효율적입니다.
([2,3]16GB 램으로 로컬에서도 실행할 수 없습니다)!

방법?

무차별-타일 버전의 좌표를 충분히 크게 생성 한 다음이 점들의 전력 세트를 단일 방향으로 1 씩만 증가하는 이웃 경로로 필터링 한 다음 최소 좌표 (예 : 원점)로 시작하는 경로로 필터링하고, 동시에이 시작 좌표를 각각 제거합니다. 그런 다음 모듈러스 산술을 사용하여 원환 체로 다시 랩핑하고 중복 좌표를 포함하는 모든 것 (즉, 교차점을 포함하는 것)을 필터링하고 마지막으로 최소 좌표를 가진 것 (즉, 원점에서 끝나는 것)을 필터링하여 결과 길이를 산출합니다.

ạƝ§=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

파이썬 2 , 87 바이트

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))

온라인으로 사용해보십시오!

여기서 흥미로운 점은 복소수를 사용 z하여 현재 위치의 좌표를 저장하는 것입니다. 을 추가하여 위로 1이동하고을 추가하여 오른쪽으로 이동할 수 있습니다 1j. 놀랍게도 모듈로는 복잡한 차원에서 각 차원의 랩핑을 개별적으로 처리하는 방식으로 %m작동합니다. 실제 부분에 %(n*1j)작용하고 가상 부분에 작용합니다.


잘 했어요 FWIW, 복잡한 숫자를 사용하지 않는 최선의 시도 는 Python 3.8에서 91 바이트 입니다.
Arnauld

@Arnauld와 함께하는 흥미로운 아이디어 k:=x+y*m. k직접 (x,y)사용 x+y*m하는 것이 아니라 사용 하는 것이 더 짧은 지 궁금합니다 x+y*1j. 너무 나쁜 파이썬 3은 복잡한 계수를 허용하지 않습니다.
xnor


이 방법은 JS에서 5 바이트를 절약합니다. :)
Arnauld

7

자바 스크립트 (ES6), 67 바이트

×<32

로 입력을 (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))``

온라인으로 사용해보십시오!

모든 입력에서 작동하도록 73 바이트에 BigInts를 사용할 수 있습니다 .

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)

온라인으로 사용해보십시오!


자바 스크립트 (ES6),  76 73  72 바이트

로 입력을 (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)

온라인으로 사용해보십시오!

댓글

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

하스켈, 88 80 바이트

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$[]

온라인으로 사용해보십시오!

단순한 무차별 대입 : 모든 위 / 오른쪽 조합을 시도하고 교차하는 항목을 삭제하고 (방문한 모든 위치를 목록에 유지 a) 궁극적으로 (0,0)다시 양성에 도달 한 항목을 계산 합니다.

재귀의 기본 사례는 두 번째 위치를 방문 할 때입니다 ( elem(x,y)a). 결과는 0^0= 1위치 인 경우 (0,0)와 루프 또는 숫자쪽으로 계수 0( 0^x함께, x비 - 제로)와 달리 루프의 수를 증가시키지 않는다.

편집 : @xnor 덕분에 -8 바이트.


1
기본 케이스에 결합 될 수있다 |elem(x,y)a=0^(x+y), 그리고 (0!0)[]할 수 있습니다 0!0$[].
xnor



1

CJam (50 자)

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

온라인 데모 . 이것은 stdin에서 두 개의 입력을받는 프로그램입니다.

마지막으로 질문에 대한 답변이 있습니다

전쟁, 허, 뭐가 좋은가요?


해부

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

젤리 , 54 39 바이트

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

온라인으로 사용해보십시오!

나는 완전히 다른 방법이기 때문에 다른 젤리에 대한 별도의 답변으로 이것을 게시했습니다. 이것은 원칙적으로 @Arnauld의 답변에 더 가깝습니다. 그것은 이미 도달 한 지점에 도달 할 때까지 가능한 모든 경로를 통해 작동하는 재귀 함수를 사용하고 다시 시작 여부를 확인한 결과를 반환합니다. 몇 바이트가 더 잘릴 수있을 것 같습니다. 이제 슬라이스 연산자를 사용하도록 변경되었습니다. 최대 5x5까지 잘 작동합니다. 재귀 깊이는 최대 mx n이어야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.