Tarzan의 올림픽 덩굴 스윙 루틴 점수


32

올림픽 덩굴 스윙 어는 표준 나무에서 일상을 수행합니다. 특히 표준 트리 n에는 0이 아닌 각 정점 을 그 아래 정점 에 연결하는 0위쪽 n-1및 모서리 a정점이 n % a있습니다. 예를 들어 표준 트리 5는 다음과 같습니다.

3
|
2   4
 \ /
  1
  |
  0

5를 3으로 나눈 나머지는 2이고, 5를 2로 나눈 4는 1이고, 5를 1로 나눈 나머지는 0이기 때문에 나머지는 0입니다.

올해 Tarzan은 정점 n - 1에서 시작하여 정점 으로 스윙하고 정점 n - 2으로 계속되는 n - 3등 새로운 루틴을 사용하여 금을 방어 할 것 0입니다.

루틴 점수는 각 스윙의 점수 (분리 포함)의 합계이며, 스윙 점수는 트리에서 시작 지점과 종료 지점 사이의 거리입니다. 따라서 Standard Tree 5의 Tarzan 루틴은 6 점입니다.

  • 에서 스윙 43점수를 세 점 (위, 아래, 위로)
  • 에서 스윙 32점수 한 점을 (아래)
  • 에서 스윙 21점수 한 점 (아래), 및
  • 에서 마운트 해제 1에 대한 0점수 한 점 (아래).

양의 정수가 주어지면 nStandard Tree에서 Tarzan 루틴의 점수를 계산 하는 프로그램이나 함수를 작성하십시오 n. 샘플 입력 및 출력 :

 1 ->  0
 2 ->  1
 3 ->  2
 4 ->  6
 5 ->  6
 6 -> 12
 7 -> 12
 8 -> 18
 9 -> 22
10 -> 32
11 -> 24
12 -> 34
13 -> 34
14 -> 36
15 -> 44
16 -> 58
17 -> 50
18 -> 64
19 -> 60
20 -> 66
21 -> 78
22 -> 88
23 -> 68
24 -> 82

규칙과 코드 스코어링은 합니다.


9
OEIS에서이 순서를 찾지 못했습니다. 좋은 질문.
Leaky Nun

8
뛰어난 사양!
xnor

1
@LeakyNun 추가해야합니다. 그것은이다 매우 원래 순서! (백 스토리 없이도)
DanTheMan

답변:


12

C, 98 97 바이트

F(i){int c[i],t=i-2,n=0,p;for(;++n<i;)for(p=c[n]=n;p=i%p;c[p]=n)t+=c[p]<n-1;return i>2?t*2:i-1;}

다음 공식을 사용하여 각 점 쌍 사이의 거리를 계산합니다.

  • 루트에서 노드 A까지의 거리 추가
  • 루트에서 노드 B까지의 거리를 추가하십시오.
  • 빼기 2 * A와 B의 공통 근의 길이

이것은 모든 쌍에 적용될 때 다음과 동일하다는 이점이 있습니다.

  • 루트에서 각 노드까지의 거리를 2 * 더하십시오
  • 각 노드 쌍의 공통 루트의 길이를 2 * 빼기
  • 루트에서 첫 번째 노드까지의 거리 빼기
  • 루트에서 마지막 노드까지의 거리 빼기

논리를 단순화하기 위해 질문 상태로 n-1에서 0이 아닌 노드 0에서 노드 n-1로 이동한다고 가정합니다. 루트 노드에서 노드 0까지의 거리는 분명히 0입니다 (동일합니다). 그리고 우리는 (가장) 나무의 경우 마지막 노드에서 루트까지의 거리가 2임을 알 수 있습니다

                    n+1 % n = 1  for all n > 1
and:                  n % 1 = 0  for all n >= 0
therefore:  n % (n % (n-1)) = 0  for all n > 2

이것은 특별한 경우가 있지만 (n <2),이를 쉽게 설명 할 수 있다는 것을 의미합니다.

고장:

F(i){                               // Types default to int
    int c[i],                       // Buffer for storing paths
        t=i-2,                      // Running total score
        n=0,                        // Loop index
        p;                          // Inner loop variable
    for(;++n<i;)                    // Loop through all node pairs (n-1, n)
        for(p=c[n]=n;p=i%p;c[p]=n)  //  Recurse from current node (n) to root
            t+=c[p]<n-1;            //   Increase total unless this is a common
                                    //   node with the previous path
    return i>2?   :i-1;             // Account for special cases at 1 and 2
               t*2                  // For non-special cases, multiply total by 2
}

1 바이트 저장 감사합니다 @feersum


보너스 : 나무!

이 나무들이 어떻게 보이는지보기 위해 빠르고 더러운 프로그램을 작성했습니다. 결과는 다음과 같습니다.

6:

5 4  
| |  
1 2 3
 \|/ 
  0  

8:

  5      
  |      
7 3   6  
|  \ /   
1   2   4
'--\|/--'
    0    

13:

   08              
    |              
11 05   10 09 07   
 |   \ /    |  |   
02   03    04 06 12
 '-----\  /---'--' 
        01         
         |         
        00         

19 :

   12                       
    |                       
   07   14                  
     \ /                    
     05    15 11            
       \  /    |            
17      04    08 16 13 10   
 |       '-\  /--'   |  |   
02          03      06 09 18
 '---------\ |/-----'--'--' 
            01              
             |              
            00              

49:

                         31                                                    
                          |                                                    
           30            18   36                                               
            |              \ /                                                 
           19   38 27      13    39 29    32                                   
             \ /    |        \  /    |     |                                   
   26        11    22 44      10    20 40 17   34                              
    |         '-\  /--'        '-\  /--'    \ /                                
47 23   46       05               09        15    45 43 41 37 33 25    35 28   
 |   \ /          '--------------\ |/-------'-----'   |  |  |  |  |     |  |   
02   03                           04                 06 08 12 16 24 48 14 21 42
 '----'--------------------------\ |/----------------'--'--'--'--'--'    \ |/  
                                  01                                      07   
                                   '-----------------\  /-----------------'    
                                                      00                       

return 문에는 불필요한 괄호가 있습니다.
feersum

@feersum d' oh! 항상 불필요한 것은 아니지만 특수한 경우 처리를 변경했습니다. 감사!
Dave

3
시각화를 좋아하십시오!
Edward

7

파이썬 2, 85 바이트

def f(a,i=1):h=lambda n:n and{n}|h(a%n)or{0};return i<a and len(h(i)^h(i-1))+f(a,i+1)

7

펄, 65 59 55 54 바이트

에 +2 포함 -ap

STDIN에서 트리 크기로 실행하십시오.

for i in `seq 24`; do echo -n "$i: "; vines.pl <<< $i; echo; done

vines.pl:

#!/usr/bin/perl -ap
$_=map{${"-@F"%$_}|=$_=$$_|$"x$p++.1;/.\b/g}1-$_..-1

설명

나무를 다시 쓰면

3
|
2   4
 \ /
  1
  |
  0

각 노드에는 모든 조상과 자체 세트가 포함되어 있습니다.

 {3}
  |
{2,3}   {4}
   \    /
    \  /
  {1,2,3,4}
      |
 {0,1,2,3,4}

그런 다음 모든 노드를 4에서 3까지의 경로로 설명 할 수 있습니다.

  • 3을 포함하지만 4를 포함하지 않는 모든 노드 (3에서 내려 가기)
  • 4를 포함하지만 3을 포함하지 않는 모든 노드 (4에서 내려 가기)
  • 3과 4를 모두 포함하는 가장 높은 노드 (결합)

모서리 수는 노드 수보다 1이 적으므로이를 사용하여 결합 점을 무시할 수 있으므로 경로가 4에서 3 사이 인 모서리의 수는 3이됩니다.

  • 3을 포함하지만 4 : 2를 포함하지 않는 노드 수
  • 4를 포함하지만 3 : 1을 포함하지 않는 노드 수

이는 대상으로 직접 내려가는 경로에도 적용됩니다. 예를 들어 3에서 2까지의 경로의 경우 가장자리 수는 1이므로 다음과 같습니다.

  • 2를 포함하지만 3 : 3을 포함하지 않는 노드의 수
  • 3을 포함하지만 2 : 1을 포함하지 않는 노드의 수

그런 다음 이러한 모든 조합을 요약 할 수 있습니다.

대신 노드 만 봅니다 (예 : 조상이 설정된 노드 2) {2,3}. 이 노드는 경로를 처리 할 때 2 to 11이 아니라 2를 포함하므로 한 번 기여할 것입니다. 경로 3 to 2는 2와 3을 모두 갖기 때문에 경로 에 아무런 영향을 미치지 않지만 3이 4 to 3있기 때문에 경로를 처리 할 때는 한 번만 기여합니다. no 4. 일반적으로 노드의 조상 세트에있는 숫자는 세트에없는 각 이웃에 대해 하나씩 기여합니다 (하나는 낮음). 경로가 없기 때문에 낮은 이웃 3에만 기여하는 최대 요소 (이 경우 4)를 제외하고5 to 4. Simular 0은 한면이지만 0은 항상 트리의 루트에 있고 모든 숫자를 포함하므로 (최종 조인이며 조인을 계산하지 않습니다) 0에서 기여한 부분이 없으므로 노드 0을 떠나는 것이 가장 쉽습니다. 모두 밖으로.

따라서 각 노드의 조상 세트를보고 문제를 계산하고 모든 노드의 합계를 계산하여 문제를 해결할 수도 있습니다.

이웃을 쉽게 처리하기 위해 조상 세트를 공백 문자열로 표시하고 위치 p의 각 1이 n-1-p가 조상임을 나타내는 1을 나타냅니다. 예를 들어 n=5위치 0에서 1 의 경우 4는 조상임을 나타냅니다. 후행 공백을 남기겠습니다. 따라서 내가 만들 트리의 실제 표현은 다음과 같습니다.

" 1"
  |
" 11"   "1"
   \    /
    \  /
   "1111"

노드 0 "11111"을 무시할 것이므로 표시되는 노드 0을 제외했습니다 (기여하지 않음).

낮은 이웃이없는 조상은 이제 1의 시퀀스 끝으로 표시됩니다. 더 높은 이웃이없는 조상은 이제 1의 시퀀스 시작으로 표시되지만 5 to 4존재하지 않는 경로 를 나타내므로 문자열 시작시 시퀀스의 시작을 무시해야 합니다. 이 조합은 정규식과 정확히 일치합니다 /.\b/.

조상 문자열 만들기는 모든 노드를 순서대로 처리 n-1 .. 1하고 노드 자체의 위치에 1을 설정하고 자손에 "또는"을 수행하여 수행합니다.

프로그램이 이해하기에 충분히 쉬운 모든 것 :

-ap                                                  read STDIN into $_ and @F

   map{                                    }1-$_..-1 Process from n-1 to 1,
                                                     but use the negative
                                                     values so we can use a
                                                     perl sequence.
                                                     I will keep the current
                                                     ancestor for node $i in
                                                     global ${-$i} (another
                                                     reason to use negative
                                                     values since $1, $2 etc.
                                                     are read-only
                       $$_|$"x$p++.1                 "Or" the current node
                                                     position into its ancestor
                                                     accumulator
                    $_=                              Assign the ancestor string
                                                     to $_. This will overwrite
                                                     the current counter value
                                                     but that has no influence
                                                     on the following counter
                                                     values
       ${"-@F"%$_}|=                                 Merge the current node
                                                     ancestor string into the
                                                     successor
                                                     Notice that because this
                                                     is an |= the index
                                                     calculation was done
                                                     before the assignment
                                                     to $_ so $_ is still -i.
                                                     -n % -i = - (n % i), so
                                                     this is indeed the proper
                                                     index
                                     /.\b/g          As explained above this
                                                     gives the list of missing
                                                     higher and lower neighbours
                                                     but skips the start
$_=                                                  A map in scalar context
                                                     counts the number of
                                                     elements, so this assigns
                                                     the grand total to $_.
                                                     The -p implicitly prints

공지 것으로 교체 /.\b/하여 /\b/이 문제를 해결합니다의 왕복 타잔 버전은 또한 경로를 얻어 여기서0 to n-1

조상 문자열이 어떻게 보이는지에 대한 몇 가지 예 (순서대로 n-1 .. 1) :

n=23:
1
 1
  1
   1
    1
     1
      1
       1
        1
         1
          1
          11
         1  1
        1    1
       1      1
      11      11
     1          1
    11  1    1  11
   1              1
  1111  11  11  1111
 111111111  111111111
1111111111111111111111
edges=68

n=24:
1
 1
  1
   1
    1
     1
      1
       1
        1
         1
          1
           1
          1 1
         1   1
        1     1
       1       1
      1         1
     1  1     1  1
    1             1
   11    1   1    11
  1   1         1   1
 1        1 1        1
1                     1
edges=82

죄송합니다. 편집하신 내용이 몇 초 밖에되지 않았다는 사실을 모르겠습니다. 어쨌든 매우 깔끔한 접근과 설명!
FryAmTheEggman

@FryAmTheEggman 문제 없습니다, 우리는 정확히 같은 레이아웃 문제를 해결하고있었습니다. 어쨌든, 나는이 프로그램에서 모든 조각들이 어떻게 조합되었는지에 매우 만족합니다. 나는 현재 지방이 잘리지 않는 것을 보지 못합니다.
Ton Hospel

3

매쓰, 113 (103) 102 바이트

(r=Range[a=#-1];Length@Flatten[FindShortestPath[Graph[Thread[r<->Mod[a+1,r]]],#,#2]&@@{#,#-1}&/@r]-a)&

@feersum 덕분에 -10 바이트; @MartinEnder 덕분에 -1 바이트

다음은 훨씬 빠르지 만 (불행히도 158 바이트 에서는 더 길다 )

(a=#;If[a<4,Part[-{1,1,1,-6},a],If[EvenQ@a,-2,1]]+a+4Total[Length@Complement[#,#2]&@@#&/@Partition[NestWhileList[Mod[a,#]&,#,#!=0&]&/@Range@Floor[a/2],2,1]])&

나는 당신이 사용하지 않고 물건을 할당 할 수 있다고 생각합니다 With. 또한 매번 Range사용될 때처럼 보이며 a인수이므로 제외시킬 수 있습니다.
feersum

1
r=Range[a=#-1]바이트를 저장합니다.
마틴 엔더

2

J, 37 바이트

[:+/2(-.+&#-.~)/\|:@(]|~^:(<@>:@[)i.)

용법:

   f=.[:+/2(-.+&#-.~)/\|:@(]|~^:(<@>:@[)i.)
   f 10
32
   f every 1+i.20
0 1 2 6 6 12 12 18 22 32 24 34 34 36 44 58 50 64 60 66

여기에서 온라인으로 사용해보십시오.


이것이 어떻게 작동하는지에 대해보고 싶습니다. 또한 tryj.tk 서비스가 망가진 것 같습니다 ( "localStorage를 읽지 못했습니다…"및 "$ (…) .terminal이 기능하지 않습니다")
Dave

@Dave 해당 사이트는 Chrome에서도 작동하지 않지만 IE 또는 Edge를 사용하면 작동하지만 관심이 있다면 J ( link )를 설치하는 것이 좋습니다 !
마일

@miles Weird, 나를 위해 모든 브라우저 (FF, Chrome, IE)에서 작동합니다.
randomra

그것은 크롬을 사용하여 나를 위해 일했다,하지만 몇 달 전에 작동을 중지하고 데이브의 유사한 오류 메시지로 응답했다
마일

@Edward 시간을 찾으면 할 것입니다.
randomra

1

자바 스크립트 (ES6) 118 116 바이트

n=>[...Array(n)].map(g=(_,i)=>i?[...g(_,n%i),i]:[],r=0).reduce(g=(x,y,i)=>x.map(e=>r+=!y.includes(e))&&i?g(y,x):x)|r

차이 설정 기능이 없으면 실제로 아프지 만 일부 창의적인 재귀는 바이트 수를 약간 줄입니다. 편집 : 불필요한 매개 변수를 제거하여 2 바이트를 절약했습니다.

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