Loo o p p 나는


22

참고 :이 질문의 제목은 "Loop It"이어야하지만 제목은 15 자 이상이어야하므로 보이지 않는 공백이 있습니다. 이 메모는 챌린지를 검색 할 수 있도록하는 것입니다.


도전

평면에 고유 한 적분 점의 유한 목록이 주어지면 꼭짓점이 정확히 그 점이고 그 자체가 교차하지 않는 다각형을 찾으십시오.

세부

  • 입력으로서, 예를 들어 각각 x 및 y 좌표 또는 한 쌍의리스트를 갖는 2 개의리스트를 취할 수 있습니다.
  • 입력 목록에는 3 점 이상이 포함됩니다.
  • 이는 고유 한 솔루션이 없음을 의미합니다.
  • 입력 목록은 동일 선상에 있지 않은 것으로 가정 할 수 있습니다 (점은 한 라인에 포함될 수 없음). 이는 실제로 자체 교차하지 않는 다각형이 있음을 의미합니다.
  • 각 정점의 각도는 임의적이며 여기에는 180 °가 포함됩니다.
  • 길이의 입력의 경우 n, 출력은 순열이어야 (p1,p2,p3,...,pn)(1,2,3,...,n)를 Where k번째 항목 pk나타내는 p입력리스트 번째 포인트. 이 방법은 우리가에서 선이 p1p2에서 선, p2p3등,뿐만 아니라에서 선 pn을을 p1. (0 기반 인덱스를 사용할 수도 있습니다.) 또는 입력 지점 목록을 올바른 순서로 출력 할 수도 있습니다.

우리가 요점을 가지고 있고 [(0,0),(0,1),(1,0),(-1,0),(0,-1)]다음과 같은 경로를 나타내고 싶다고 가정 해 봅시다 .

여기에 이미지 설명을 입력하십시오

이것은 우리가 목록을 출력한다는 것을 의미합니다 [5,1,4,2,3]

여기에 더 제안 할 것이 있습니다 (목표를 확인하기 위해 해당 플롯을 보는 것이 좋습니다.)

Triangle
[(0,0),(0,1),(1,0)]

S-Curve
[(0,0),(0,1),(0,2),(0,3),(0,4),(1,0),(2,0),(2,1),(2,2),(2,3),(2,4),(3,4),(4,0),(4,1),(4,2),(4,3),(4,4)]

L-Shape
[(4,0),(1,0),(3,0),(0,0),(2,0),(0,1)]

Menger Sponge
[(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,1),(12,1),(13,1),(14,1),(15,1),(16,1),(17,1),(18,1),(19,1),(20,1),(21,1),(22,1),(23,1),(24,1),(25,1),(26,1),(27,1),(1,2),(3,2),(4,2),(6,2),(7,2),(9,2),(10,2),(12,2),(13,2),(15,2),(16,2),(18,2),(19,2),(21,2),(22,2),(24,2),(25,2),(27,2),(1,3),(2,3),(3,3),(4,3),(5,3),(6,3),(7,3),(8,3),(9,3),(10,3),(11,3),(12,3),(13,3),(14,3),(15,3),(16,3),(17,3),(18,3),(19,3),(20,3),(21,3),(22,3),(23,3),(24,3),(25,3),(26,3),(27,3),(1,4),(2,4),(3,4),(7,4),(8,4),(9,4),(10,4),(11,4),(12,4),(16,4),(17,4),(18,4),(19,4),(20,4),(21,4),(25,4),(26,4),(27,4),(1,5),(3,5),(7,5),(9,5),(10,5),(12,5),(16,5),(18,5),(19,5),(21,5),(25,5),(27,5),(1,6),(2,6),(3,6),(7,6),(8,6),(9,6),(10,6),(11,6),(12,6),(16,6),(17,6),(18,6),(19,6),(20,6),(21,6),(25,6),(26,6),(27,6),(1,7),(2,7),(3,7),(4,7),(5,7),(6,7),(7,7),(8,7),(9,7),(10,7),(11,7),(12,7),(13,7),(14,7),(15,7),(16,7),(17,7),(18,7),(19,7),(20,7),(21,7),(22,7),(23,7),(24,7),(25,7),(26,7),(27,7),(1,8),(3,8),(4,8),(6,8),(7,8),(9,8),(10,8),(12,8),(13,8),(15,8),(16,8),(18,8),(19,8),(21,8),(22,8),(24,8),(25,8),(27,8),(1,9),(2,9),(3,9),(4,9),(5,9),(6,9),(7,9),(8,9),(9,9),(10,9),(11,9),(12,9),(13,9),(14,9),(15,9),(16,9),(17,9),(18,9),(19,9),(20,9),(21,9),(22,9),(23,9),(24,9),(25,9),(26,9),(27,9),(1,10),(2,10),(3,10),(4,10),(5,10),(6,10),(7,10),(8,10),(9,10),(19,10),(20,10),(21,10),(22,10),(23,10),(24,10),(25,10),(26,10),(27,10),(1,11),(3,11),(4,11),(6,11),(7,11),(9,11),(19,11),(21,11),(22,11),(24,11),(25,11),(27,11),(1,12),(2,12),(3,12),(4,12),(5,12),(6,12),(7,12),(8,12),(9,12),(19,12),(20,12),(21,12),(22,12),(23,12),(24,12),(25,12),(26,12),(27,12),(1,13),(2,13),(3,13),(7,13),(8,13),(9,13),(19,13),(20,13),(21,13),(25,13),(26,13),(27,13),(1,14),(3,14),(7,14),(9,14),(19,14),(21,14),(25,14),(27,14),(1,15),(2,15),(3,15),(7,15),(8,15),(9,15),(19,15),(20,15),(21,15),(25,15),(26,15),(27,15),(1,16),(2,16),(3,16),(4,16),(5,16),(6,16),(7,16),(8,16),(9,16),(19,16),(20,16),(21,16),(22,16),(23,16),(24,16),(25,16),(26,16),(27,16),(1,17),(3,17),(4,17),(6,17),(7,17),(9,17),(19,17),(21,17),(22,17),(24,17),(25,17),(27,17),(1,18),(2,18),(3,18),(4,18),(5,18),(6,18),(7,18),(8,18),(9,18),(19,18),(20,18),(21,18),(22,18),(23,18),(24,18),(25,18),(26,18),(27,18),(1,19),(2,19),(3,19),(4,19),(5,19),(6,19),(7,19),(8,19),(9,19),(10,19),(11,19),(12,19),(13,19),(14,19),(15,19),(16,19),(17,19),(18,19),(19,19),(20,19),(21,19),(22,19),(23,19),(24,19),(25,19),(26,19),(27,19),(1,20),(3,20),(4,20),(6,20),(7,20),(9,20),(10,20),(12,20),(13,20),(15,20),(16,20),(18,20),(19,20),(21,20),(22,20),(24,20),(25,20),(27,20),(1,21),(2,21),(3,21),(4,21),(5,21),(6,21),(7,21),(8,21),(9,21),(10,21),(11,21),(12,21),(13,21),(14,21),(15,21),(16,21),(17,21),(18,21),(19,21),(20,21),(21,21),(22,21),(23,21),(24,21),(25,21),(26,21),(27,21),(1,22),(2,22),(3,22),(7,22),(8,22),(9,22),(10,22),(11,22),(12,22),(16,22),(17,22),(18,22),(19,22),(20,22),(21,22),(25,22),(26,22),(27,22),(1,23),(3,23),(7,23),(9,23),(10,23),(12,23),(16,23),(18,23),(19,23),(21,23),(25,23),(27,23),(1,24),(2,24),(3,24),(7,24),(8,24),(9,24),(10,24),(11,24),(12,24),(16,24),(17,24),(18,24),(19,24),(20,24),(21,24),(25,24),(26,24),(27,24),(1,25),(2,25),(3,25),(4,25),(5,25),(6,25),(7,25),(8,25),(9,25),(10,25),(11,25),(12,25),(13,25),(14,25),(15,25),(16,25),(17,25),(18,25),(19,25),(20,25),(21,25),(22,25),(23,25),(24,25),(25,25),(26,25),(27,25),(1,26),(3,26),(4,26),(6,26),(7,26),(9,26),(10,26),(12,26),(13,26),(15,26),(16,26),(18,26),(19,26),(21,26),(22,26),(24,26),(25,26),(27,26),(1,27),(2,27),(3,27),(4,27),(5,27),(6,27),(7,27),(8,27),(9,27),(10,27),(11,27),(12,27),(13,27),(14,27),(15,27),(16,27),(17,27),(18,27),(19,27),(20,27),(21,27),(22,27),(23,27),(24,27),(25,27),(26,27),(27,27)]

4 점 O (0,0), A (1,0), B (0,1), C (0,2)가 있으면 다각형 OABC가 자체 교차입니까?
ngn

@ngn 그것은 내가 고려하지 않은 좋은 지적입니다! 나는 그것에 대해 생각해야 할 것이다. 이에 대해 또는 반대되는 주장이 있으면 알려주십시오.
flawr

@ngn이 다각형을 자체 교차로 계산합니다. 그 이유는 끝 점이 아닌 두 모서리의 공통점이 있으면 다각형이 자체 교차 되도록 정의하기 때문입니다.
flawr

@flawr 그런 다음 답변을 철회해야합니다. 기준점에서 최대 각도로 여러 개의 선형 점이있을 때 실패합니다.
ngn

답변:


10

Mathematica 29 28 바이트

FindShortestTour (16 바이트)는 트릭을 수행하지만 요청되지 않은 외부 정보 (경로 길이 및 시작점으로의 복귀)를 제공합니다.

Most@*Last@*FindShortestTour

대답 만 제공합니다 (@ user202729 덕분에 -1 바이트)

시각화하려면을 사용하십시오 Graphics@Line[g[[%]]]. 여기서 %위의 순열은 어디에 있고 g는 원래 점 목록입니다.

Menger 스폰지 솔루션의 시각화는 다음과 같습니다. 여기에 이미지 설명을 입력하십시오

1000 개의 임의 포인트에 대한 솔루션은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

여기서 가장 중요한 점은 유클리드 거리가 메트릭으로 사용될 때 가장 짧은 투어 또는 여행 세일즈맨 문제 해결 방법이 교차로를 생성하지 않는다는 것입니다. 솔루션을 현지화하고 최적 성을 보장하는 단계 중 하나는 이러한 교차점을 제거하는 것입니다.


6
P 문제가 더 짧기 때문에 NP 알고리즘을 사용하십시오. +1 (???).
user202729

1
@*바이트를 저장하는 것 같습니다.
user202729


6

JavaScript (ES6), 365 341 바이트

내장 기능이 없으면 예상보다 훨씬 길었습니다. 동일 선상 중첩 세그먼트를 감지하는 데 많은 바이트가 사용됩니다.

[x,y]좌표 배열로 입력을 받습니다. 입력의 순열을 반환합니다.

f=(a,p=[],o=([p,P],[q,Q],[r,R])=>Math.sign((S=[(p>q?r<q|r>p:r<p|r>q)|(P>Q?R<Q|R>P:R<P|R>Q),...S],Q-P)*(r-q)-(q-p)*(R-Q)))=>[...p,p[0]].some((A,i,P)=>P.some((C,j)=>j>i+1&&P[++j+!i]&&[E=o(A,B=P[i+1],C,S=[]),F=o(A,B,D=P[j]),G=o(C,D,A),H=o(C,D,B)].some(v=>!v&!S.pop())|E!=F&G!=H))?0:a[0]?a.some((_,i)=>r=f(b=[...a],p.concat(b.splice(i,1))))&&r:p

데모

이 스 니펫은 출력을 기록하고 캔버스에 해당 경로를 그립니다.

방법?

주요 재귀 함수 f () 의 구조는 다음과 같습니다 .

f = (a, p = []) =>                    // a = array of points, p = current path
  [...p,                              // build a closed path array P[] by adding the first
         p[0]]                        // point at the end of p[]
  .some((A, i, P) =>                  // for each point A at position i in P:
    P.some((C, j) =>                  //   for each point C at position j in P:
      j > i + 1 &&                    //     test whether C is at least 2 positions after A
      P[++j +                         //     and C is not the last point
              !i] &&                  //     and i > 0 or C is not the penultimate point
      intersection(                   //     and there's an intersection between
        A, P[i + 1], C, P[j]          //     the segments (A, P[i + 1]) and (C, P[j + 1])
      )                               //     (j was incremented above)
    )                                 //   end of inner some()
  ) ?                                 // end of outer some(); if truthy:
    0                                 //   discard this path by stopping recursion
  :                                   // else:
    a[0] ?                            //   if there's at least one remaining point:
      a.some((_, i) =>                //     for each remaining point at position i:
        r = f(                        //       do a recursive call with:
          b = [...a],                 //         a copy b[] of a[] without a[i] and
          p.concat(b.splice(i, 1)))   //         the extracted point added to the path
      ) && r                          //     end of some(); return the result, if any
    :                                 //   else:
      p                               //     this is a valid path: return it

다음은 교차 () 테스트 의 세부 사항입니다 . 이 페이지 는 사용 된 알고리즘에 대한 포괄적 인 설명을 제공합니다.

[                                     // build an array containing:
  E = o(A, B = P[i + 1], C, S = []),  //   E = test of (A, B, C) (+ initialization of S[])
  F = o(A, B, D = P[j]),              //   F = test of (A, B, D)
  G = o(C, D, A),                     //   G = test of (C, D, A)
  H = o(C, D, B)                      //   H = test of (C, D, B)
]                                     //
.some(v =>                            // the segments are collinear and overlapping if:
  !v &                                //   any value above is 0
  !S.pop()                            //   and the corresponding entry in S[] is falsy
) |                                   // the segments intersect if:
E != F & G != H                       //   E is not equal to F and G is not equal to H

마지막으로 헬퍼 함수 o () 의 정의는 다음과 같습니다.

o = (                                             // given three points represented by
  [p, P], [q, Q], [r, R]                          // a lowercase letter for x
) =>                                              // and an uppercase letter for y:
  Math.sign(                                      //
    (                                             //   1) prepend to the array S[]
      S = [                                       //      a boolean which is true if the
        (p > q ? r < q | r > p : r < p | r > q) | //      segment (P, Q) would not contain
        (P > Q ? R < Q | R > P : R < P | R > Q),  //      the point R, assuming that the
        ...S                                      //      3 points are collinear
      ],                                          //
                                                  //   2) return the orientation of P, Q, R:
      Q - P                                       //        -1 = counterclockwise
    ) * (r - q) - (q - p) * (R - Q)               //         0 = collinear
  )                                               //        +1 = clockwise

... 설명주세요?
user202729

1
@ user202729 (* 이마에 물티슈 *) 완료!
Arnauld

5

APL (Dyalog Classic) , 42 38 바이트

{⍋(⍪,(|z)ׯ1*⊢=⌈/)12z0j1⊥¨⍵-⍵[⊃⍋↑⍵]}

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

입력은 좌표 쌍의 목록입니다. 출력은 0 기반 순열입니다.

포인트의 목록입니다. { }

⍵[⊃⍋↑⍵] 가장 왼쪽 지점입니다

⍵- 가장 왼쪽이 좌표계의 원점이되도록 모든 점을 변환합니다.

0j1 허수 단위 i = sqrt (-1)

0j1⊥¨ base-i 수 시스템의 숫자처럼 좌표를 해독합니다. 즉 (x, y)를 복소수 ix + y로 바꿉니다.

z← 할당하다 z

12○복소수의 인수, 일명 세타 각도 또는 APL 순환 함수를 계산합니다 12

(⍪,(|z)ׯ1*⊢=⌈/)각도가 최대 ( ⊢=⌈/) 인 부울 마스크를 계산하는 기차이며 , ¯1을 해당하는 전력 ( ¯1*) 으로 증가시켜 마스크의 0 1을 1 ¯1로 바꾸고 복소수의 크기를 곱한 기차 입니다 |z. ,키가 크고 얇은 1 열 행렬 ( )의 오른쪽 ( )에 연결합니다 .

grade-행렬의 행을 사전 순으로 오름차순으로 정렬하는 순열을 반환합니다.


@ user202729 그들은 두 번째 기준에 따라 분류됩니다-거리 (즉, 원형 함수 10, 일명 복소 크기)
ngn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.