11 = (1 + 2 + 3 + 4 + 5)-(1 + 2 + 3) + (6)-(4)


35

양의 정수 N이 주어지면 다음 알고리즘에 필요한 단계 수를 N 에 도달하는 것입니다 .

  1. 작은 삼각형 번호 찾기 T i가 되도록 T 내가  ≥ N을 . 해당 목록 L = [1, 2, ..., i]를 작성하십시오 .

  2. L 항의 합 이 N 보다 큰 반면 목록에서 첫 번째 항을 제거합니다.

  3. L 항의 합계 가 이제 N 보다 작은 경우 i를 증가 시키고리스트에 추가하십시오. 2 단계로 진행하십시오.

N 에 도달 하자마자 멈 춥니 다 . 첫 번째 단계 만 체계적으로 실행됩니다. 2 단계와 3 단계는 전혀 처리되지 않을 수 있습니다.

아래는 N = 11 의 예입니다 .

예

따라서 N = 11에 대한 예상 출력 은 4 입니다.

다른 예 :

  • N = 5 - T 3 = 1 + 2 + 3 = 6 으로 시작하고 2 + 3 = 5로 시작 합니다. 예상 출력 : 2 .
  • N = 10 - 때문에 첫 번째 단계가 필요하다 (10)는 삼각형의 개수이다 : T 4 = 1 + 2 + 3 + 4 = 10 . 예상 출력 : 1 .

처음 100 개 값

다음은 1 ≤ N ≤ 100에 대한 결과입니다 .

  1,  2,  1,  4,  2,  1,  2, 10,  2,  1,  4,  2,  6,  2,  1, 22,  8,  2, 10,  2,
  1,  2, 12,  6,  2,  4,  2,  1, 16,  2, 18, 50,  2,  6,  2,  1, 22,  6,  2,  4,
 26,  2, 28,  2,  1,  8, 30, 16,  2,  6,  4,  2, 36,  2,  1,  2,  4, 12, 40,  2,
 42, 14,  2,108,  2,  1, 46,  2,  6,  4, 50,  2, 52, 18,  2,  4,  2,  1, 56, 12,
  2, 20, 60,  4,  2, 22, 10,  2, 66,  2,  1,  4, 10, 24,  2, 40, 72,  8,  2,  6

규칙

  • 전체 프로그램 또는 함수를 작성하여 결과를 인쇄하거나 리턴 할 수 있습니다.
  • 당신이있어 필요한 모든 처리하기 위해 N ≤ 65536을 미드 레인지 하드웨어에서 1 분 이내에.
  • 충분한 시간이 주어지면 프로그램 / 기능 이론적 으로 사용자의 언어에서 기본적으로 지원되는 N 값에 대해 작동 해야합니다. 그렇지 않은 경우, 답변에 이유를 설명하십시오.
  • 이것은 코드 골프이므로 바이트 단위의 최단 답변이 이깁니다!

관련. (이것에 대해 이미 알고 있다고 생각하지만 후손을 위해 게시하는 것만

처리해야하는 N의 최대 값은 얼마입니까?
Luke

@Luke 업데이트 된 규칙을 참조하십시오.
Arnauld

답변:


4

젤리 , 29 31 바이트

ÆDµ’H+Ṛ%1$ÐḟṂ
>TḢ_@Ç}‘Ḥ
R+\ðċȯç

결과를 반환하는 모나드 링크 (N = 65536은 2 초 미만 소요)

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

어떻게?

알고리즘에 대한 자세한 설명은 Martin Ender환상적인 게시물을 참조하십시오 .

ÆDµ’H+Ṛ%1$ÐḟṂ - Link 1, smallest natural number, M, that satisfies the below*, N
              - * N = T(M) - T(i) for some non-negative integer i <= M
ÆD            - divisors of N
  µ           - monadic chain separation, call that d
   ’          - increment d (vectorises)
    H         - halve (vectorises
      Ṛ       - reverse d
     +        - add (vectorises)
          Ðḟ  - filter discard if:
       %1$    -   modulo one is truthy (those which are the result of even divisors)
            Ṃ - minimum

>TḢ_@Ç}‘Ḥ - Link 2, evaluate result for non-triangular: list of T(1) to T(N), N
>         - T(i) > N
 T        - truthy indexes
  Ḣ       - head (yields the first i for which T(i) > N)
     Ç}   - call last link (1) as a monad converted to a dyad using the right argument
   _@     - subtract with reverse @rguments
       ‘  - increment
        Ḥ - double 

R+\ðċȯç - Main link: N
R       - range -> [1,2,...,N]
 +\     - reduce with addition -> [1,3,6,10,...T(N)]
   ð    - dyadic chain separation, call that t
    ċ   - count occurrences of N in t (1 if N is triangular else 0)
      ç - call last link (2) as a dyad(t, N)
     ȯ  - or

설명 된 알고리즘으로 만든 29 바이트 전체 프로그램 구현은 랩톱에서 N = 65536의 경우 4 분 30이 걸리므로 계산하지 않습니다.

Ṁ‘ṭµS<³µ¿
ḊµS>³µ¿
0®Ḃ‘©¤ĿÐĿL’

모든 단계 3에 대해 while 루프를 사용하고 단계 1로 재사용하는 것은 길이가 목록을 초기화하여 관리 할 수있는 길이와 같습니다.

ḊµS>³µ¿
Ṁ‘ṭ
Ḥ½_.ĊR®Ḃ‘©¤ĿÐĿS€i

25

Mathematica, 79 바이트

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&

설명

도전 과제에서 알고리즘을 구현하기 위해 귀찮게 할 수 없었으므로 솔루션에 대한 지름길을 찾고 싶었습니다. 하나를 찾았지만 불행히도 알고리즘을 구현하는 Mathematica 답변을 능가하지는 않습니다. 즉, 이것은 이것이 최적으로 골프화되지 않았다고 확신하며,이 접근법이나 프로세스에서 얻은 통찰력을 활용할 수있는 다른 언어가있을 수 있습니다.

그래서 우리가 계산 해야하는 순서는 다음과 같습니다.

f (n) = 2 * ( A212652 (n) -A002024 (n)) + 1 + A023532 (n-1)

또는 n 이 삼각수 이면 f (n) = 1 이고, 그렇지 않으면 f (n) = 2 * ( A212652 (n) -A002024 (n) + 1) 입니다.

첫 번째 표현에서 A023532는 단순히이 두 가지 경우를 인코딩합니다. 다른 두 서열 (플러스 1) 가장 큰 정수의 차이이다 K 최장 분해 N 연속적인 정수로 (K-I + 1) + (K-I + 2) + ... + K = N 및 최대 정수 J 되도록 1 + 2 + ... + J <N .

좀 더 간단한 단어로, 여기에 비 삼각형 숫자에 대한 답을 찾는 방법이 있습니다. 먼저, n 보다 작은 가장 큰 삼각수 T j 를 찾으십시오 . 그런 다음 j1 단계에서 추가되는 두 번째 정수입니다 ( j + 1 을 추가 한 후 우리는 n 을 초과 했기 때문에 ). 그런 다음 n 을 가능한 한 많은 (또는 작은) 연속 정수로 분해 하고 이러한 숫자 k 중 최대 값을 호출하십시오 . 결과는 단순히 2 * (kj) 입니다. 직관적 인 이유는 분해의 최대 값이 매 단계마다 1 씩 증가하고 도달 할 때 멈추기 때문입니다k .

우리는 이것이 작동한다는 것을 증명하기 위해 4 가지를 보여 주어야합니다.

  1. 삼각 숫자의 경우 f (n) = 1 입니다. 첫 번째 단계는 단순히 모든 삼각형 숫자를 반복하기 때문에 이것은 사소한 경우입니다. 이 과정에서 정확히 n 을 누르면 계산이 완료된 것입니다.
  2. 다른 모든 숫자의 경우 항상 삽입 단계 이후가 아니라 삭제 단계 후에 끝납니다. 그것은 다른 모든 f (n) 이 짝수 임을 의미합니다 .
  3. 첫 번째 이후의 각 삽입 단계에서 단일 숫자 만 추가합니다. 이렇게하면 kj 쌍의 단계 후에 k 를 포함하여 분해에 도달 할 수 있습니다 .
  4. 우리가 얻는 n 의 최종 분해 는 항상 n 을 연속 정수로 분해 할 수있는 가장 긴 분해입니다. 즉, 항상 합산 된 수 중에서 최대 값이 가장 낮은 n 의 분해입니다 . 다시 말해, 합에 더하는 마지막 숫자는 항상 A212652 (n) 입니다.

우리는 이미 (1)이 참인 이유를 이미 보았습니다. 다음으로, 우리는 초기 단계 (삼각이 아닌 숫자에서는 발생하지 않음)를 제외하고는 삽입 단계를 끝낼 수 없다는 것을 증명합니다.

우리가 삽입 단계를 끝내고 합에 값 p 를 더한 후 n 에 도달 했다고 가정 해보십시오 . 이는이 삽입 단계 이전에 값이 np 였음을 의미합니다 ( 한 번에 여러 값을 추가 한 경우 더 적음 ). 그러나이 삽입 단계 앞에는 삭제 단계가 있습니다 ( 1 단계에서 n 을 칠 수 없으므로 ). 이 삭제 단계에서 제거한 마지막 값 q 는 알고리즘 작동 방식으로 인해 반드시 p 보다 작습니다 . 우리가 제거되기 전에 그러나 그 수단이 질문을 우리가했다 N-P + Q를 ( 작거나 미만이다) N. 그러나 다른 q 를 제거하는 대신 n-p + q 를 칠 때 정수 제거를 중단해야했기 때문에 모순 입니다. 이것은 위의 포인트 (2)를 증명합니다. 이제 우리는 항상 삭제 단계를 끝내고 삼각형이 아닌 모든 숫자에도 출력이 있음을 알고 있습니다.

다음으로 각 삽입 단계는 하나의 값만 삽입 할 수 있음을 증명합니다 (3). 이것은 본질적으로 (2)의 결과입니다. 하나의 값을 추가 한 후에는 n을 정확하게 칠 수없고 증명이 부등식을 사용 했기 때문에 n 이하로 끝날 수 없습니다 ( n-p + q 는 여전히 n 보다 작으므로 제거하지 않아야 함) 처음부터 그 많은 가치). 따라서 단일 값을 추가 할 때마다 더 작은 값을 제거하여 n 아래로 이동했기 때문에 n 을 초과 할 수 있습니다. 따라서 우리는 합계의 상단이 매 단계마다 1 씩 증가한다는 것을 알고 있습니다. 우리는 (그것은 작은의이 상단의 초기 값을 알고 m 그러한T m > n ). 이제 최종 합에 도달하면이 상단을 알아 내면됩니다. 그러면 단계 수는 단순히 두 배의 차이 (+ 1)입니다.

이를 위해, 우리는 최종 합이 항상 n 을 가능한 한 많은 정수로 분해하거나 그 분해의 최대 값이 최소 인 분해 (즉, 가능한 가장 빠른 분해) 임을 증명합니다 (4 ). 우리는 다시 모순에 의해 이것을 할 것입니다.

n 의 가장 빠른 / 가장 긴 분해 가 a + (a + 1) + ... (b-1) + b 이고 a ≤ b 이고 알고리즘이 그것을 건너 뜁니다. 즉 , b 가 추가 될 때 a 는 더 이상 합계의 일부가 아니어야합니다. 경우 A는 합계의 일부 , 우리가 가진 것 N ≤이야 그 순간에. 따라서 어느 합 만의 값을 포함 에 B 같음 N 우리는 (그러므로, 우리는이 분해를 생략하지 않은) 중지 또는 미만의 적어도 하나 개의 값이 존재 경우 합에가 승리 N <들그리고 그 값은 정확한 합에 도달 할 때까지 제거됩니다 (다시 말해서 분해를 건너 뛰지 않았습니다). 그래서 우리는 제거해야 할 것 추가하기 전에 B를 . 그러나 우리가 가진 것 그 수단이있는 상황에 도달하는 A는 합계의 가장 작은 구성 요소, 그리고 가장 큰되지 아직. 그러나 그 시점에서 우리가 제거 할 수 없습니다 합계가 명확 미만이기 때문에, N (이후 B가 없는), 우리는 우리가 추가 할 때까지 첫 번째 값을 추가하는 데 필요한 것, 그래서 B를 하고 명중 n은 정확히. 이것은 (4)를 증명합니다.

따라서 이러한 것들을 함께 취하면 첫 번째 단계 쌍이 최대 값 A002024 (n)을 제공한다는 것을 알고 있습니다. 우리는 최종 분해의 최대 값이 A212652 (n) 임을 알고 있습니다. 그리고 우리는이 최대 값이 모든 단계 쌍마다 한 번씩 증가한다는 것을 알고 있습니다. 따라서 최종 표현식은 2 * ( A212652 (n) -A002024 (n) + 1) 입니다. 이 공식은 삼각 숫자에 거의 효과가 있습니다. 단, 2 대신에 1 단계 만 필요하다는 점을 제외하고는 삼각 숫자의 표시 기능으로 결과를 수정하는 것입니다 (또는 그 중에서 더 편리한 방법).

마지막으로 구현에 관해서는. 전자 시퀀스의 경우 OEIS 의 공식 MIN (odd d | n; n / d + (d-1) / 2)을 사용 하고 있습니다. 이 식 에 2 의 인수를 취하여 MIN (odd d | n; 2n / d + d-1) 을 얻으면 몇 바이트를 절약하는 것으로 나타났습니다 . 왜냐하면 -1 은 첫 번째 버전에서 +1 로 취소 되기 때문입니다. 의 F (n)은 직접 삼각이 아닌 삼각형 번호의 두 경우를 인코딩한다. 코드에서 이것은 다음과 같습니다.

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]

후자의 시퀀스 ( 1, 2, 2, 3, 3, 3, ...)에는 간단한 닫힌 형식을 사용할 수 있습니다.

⌊(2#)^.5+.5⌋

마지막으로, 8n + 1 이 완벽한 정사각형 때마다 삼각 숫자의 역 지표 함수는 0 입니다. 이것은 Mathematica에서 다음과 같이 표현 될 수 있습니다.

⌈Sqrt[8#+1]~Mod~1⌉

이 마지막 두 시퀀스를 표현하고 그 사이에 일정한 오프셋을 이동시키는 많은 방법이 있으므로 이것이 아직 최적의 구현이 아니라고 확신하지만 이것이 다른 사람들에게 새로운 접근 방식을 살펴볼 수있는 출발점이 될 수 있기를 바랍니다. 그들의 언어.

이 모든 문제를 겪었으므로 여기에 n = 1000 까지의 시퀀스 플롯이 있습니다 (몇 초 안에 100k를 계산할 수도 있지만 실제로 추가 통찰력을 보여주지는 않습니다).

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

그 직선에 대한 변형을 살펴 보는 것이 흥미로울 수 있지만 다른 사람에게 남겨 두겠습니다 ...


나는 마침내 당신의 대답을 철저히 읽는 데 시간이 걸렸습니다. 훌륭합니다. (3) 이미 알고리즘 가정 것을 주 (단계 # 3는 인 경우 가 아닌, 동안 ),하지만 증거입니다 - 물론 - 많은 환영했다.
Arnauld

@Arnauld 감사합니다. :) if / while 부분을 간과했거나 오해 했어야합니다. 그것이 차이를 만들지 않는 것이 좋습니다.
마틴 엔더

7

Mathematica, 72 바이트

(For[l=u=c=k=0,k!=#,c++,If[#>k,While[#>k,k+=++u],While[#<k,k-=l++]]];c)&

정수 인수를 취하는 순수 함수.

작동 원리

For[ ... ]

For루프.

l=u=c=k=0

초기화; 세트 l(아래), u(상부) c(카운터)과 k0 (합).

k!=#

조건; k입력과 같지 않은 동안 반복 하십시오.

c++

증가; 카운터를 증가시킵니다 c.

If[#>k,For[,#>k,,k+=++u],For[,#<k,,k-=l++]]

신체

If[#>k, ... ]

입력이 다음보다 큰 경우 k:

While[#>k,k+=++u]

입력이보다 크면 k씩 증가 u및 증가 k합니다 u.

입력이 다음보다 크지 않은 경우 k:

While[#<k,k-=l++]

입력 미만이지만 k감소, kl과 증가 l.

( ... ;c)

c루프 후 돌아 갑니다.


1
For[,...]박동 While[...].
마틴 엔더


5

하스켈 , 70 63 68 64 바이트

편집하다:

  • -7 바이트 :의 의미를 부정함으로써 공백, 두 개의 부호 및 일부 괄호를 제거했습니다 a. 설명에서 일대일 오류를 수정했습니다.
  • 5 바이트 : 아아는 완전히 65536의 요구 사항, 그리고 밝혀 (2) (1) 힘은, 특히 비싼 것을 놓친 당신이 (숫자 자체 (2) 너무 오래 범위를 합산되는 얻을 때 그들은 단지 히트를 얻을 수 있기 때문에 랩 의 주위에 제로) 항상. 합계를 수학 공식으로 대체했습니다.
  • -4 바이트 : 조정 ab선형 취소 할 합계 수식 용어를 얻을 수 있습니다.

1#1 정수를 가져오고 리턴하는 익명 함수입니다.

로 사용하십시오 (1#1) 100.

1#1
(a#b)n|s<-a*a-b*b=sum$[a#(b+2)$n|s>8*n]++[(b#a)(-n)+1|s<8*n]

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

작동 원리

  • (a#b)n현재 계산 단계를 나타냅니다. a, b의 번호는 1, 3, 5, ..반면, n공정에 따라 포지티브 또는 네거티브 일 수있다.
    • 1 단계 또는 3 단계에서 목록 [(a+1)/2,(a+3)/2..(b-1)/2]및 목표 번호를 나타냅니다 -n.
    • 2 단계에서 목록 [(b+1)/2,(b+3)/2..(a-1)/2]및 목표 번호를 나타냅니다 n.
  • a, b리스트와리스트 사이의 이상한 대응 은 짧은 표현으로 요약 할 수 있습니다 s=a*a-b*b.
    • 1 단계와 3 단계에서 이는 동일합니다 s= -8*sum[(a+1)/2..(b-1)/2].
    • 2 단계에서 이는와 동일합니다 s=8*sum[(b+1)/2..(a-1)/2].
  • 분기는 각각 하나의 경우에만 요소를 생성하는 목록 이해력을 가지며 결과를 합산하여 수행됩니다.
    • 만약이 s>8*n다음 b재귀 전에이 증가합니다.
      • 1 단계와 3 단계에서는 목록이 커지고 2 단계에서는 목록이 줄어 듭니다.
    • 있으면 s<8*n, 다음 재귀 교환함으로써 변경 단계 ab, 그리고 부정을 n하고, (1)은 그 결과에 부가된다.
    • 인 경우 s==8*n두 목록 이해 중 어느 것도 요소를 제공하지 않으므로 합계는 0입니다.
  • (1#1) n는 시작하기 전에 더미 "단계 2"를 나타내며, 즉시 단계 1로 변경되어에서 목록을 작성 [1..0]=[]합니다.

4

PHP> = 7.0, 74 바이트

while($i=$r<=>$argn)for($s++;($r<=>$argn)==$i;)$r+=$i+1?-++$y:++$x;echo$s;

우주선 연산자를 사용하십시오

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

넓히는

while($i=$r<=>$argn) # if input is not equal sum of array
  for($s++;  # raise count steps
  ($r<=>$argn)==$i;)
  # so long as value compare to input has not change to lower/higher to higher/lower or equal  
    $r+=$i+1
      ?-++$y # if $i was higher remove the first integer
      :++$x;} # if $i was lower add the next highest integer     
echo$s; # Output steps

무엇입니까 $argn?
chx

이는 @chx 변수를 사용할 때 -R 옵션을 사용하여 명령 줄에서 당신은 당신이 PHP php.net/manual/en/features.commandline.options.php
요 르그 Hülsermann

와우. 나는 들어 본 적이 -R덜 훨씬 argvargi. 물론 argc와 argv를 알고있었습니다. 매우 흥미 롭습니다. 감사합니다.
chx

4

C, 94 91 바이트

온라인 시도

c;s;m;M;f(n){while(s-n){while(s<n)s+=++M;c++;if(s==n)break;while(s>n)s-=++m;c++;}return c;}

초기화되지 않은 변수에 대한 광범위한 사용 oO
YSC

C에서 @YSC, 초기화되지 않은 전역 선언 정수는 컴파일 타임에 0으로 설정됩니다. 더 읽기
Khaled.K

이것에 대해 잊었다. 이 알림에 감사드립니다.
YSC

참고로 다른 C 답변을 게시했습니다 . 내가 사용한 트릭 중 적어도 하나는 다른 컴파일러와 함께 작동하지 않지만 누락 된 컴파일러의 경우 return자유롭게 사용할 수 있습니다.
hvd

3

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

D=(o,a=0,b=1,d=1,c=0)=>a<o?D(o,a+=b,b+1,d,c+(a>=o)):a>o?D(o,a-=d,b,d+1,c+(a<=o)):c

테스트 스 니펫


죄송하지만 각 ↄ는 3 바이트로 계산됩니다. 사소하게 이름을 바꿀 수 있기 때문에 중요하지 않은 것 같습니다.
Ørjan Johansen

@ ØrjanJohansen 알려 주셔서 감사합니다. 길이가 아닌 바이트 단위로 코드를 스코어링해야한다는 것을 기억해야합니다. "명명하게 이름을 바꿀 수있는 [변수]"에 대한 커뮤니티 합의가 없다고 생각하여 글을 수정했습니다. 오 잘
R. Kap

3
스 니펫은 6553에서 "너무 많은 재귀"로 실패합니다. 6553은 노드 (6.9.1)에서 로컬로 작동하지만 65536은 작동하지 않습니다 ( "최대 호출 스택 크기를 초과했습니다").
eush77

3

dc , 61 바이트

dsN[ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx]dsFxz2-

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

설명

주요 재귀 매크로 :

ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx
   9k4*d2*1+dv-0k2/-                              # Compute triangular root
                    d1+*2/                        # Compute triangular number
  d                       -d[q]s.0=.              # Check if sum is exact
 d                                  -lN-          # Compute S-N or S+N
                                        0lN-sN    # Update N := -N
d                                             lFx # Leave the trail and recurse

이 매크로 :

  1. 스택의 현재 수를 초과하는 최소 삼각 수를 찾습니다 (수정 된 삼각 근 공식 사용).
  2. 삼각 합 S이 현재 숫자를 정확하게 나타내는 지 확인합니다 . 있는 경우 종료합니다.
  3. S+N(근사치 초과) 또는 S-N( 근사치 부족)을 사용하여 1 단계로 진행 하면 선택이 반복간에 번갈아 나타납니다.

종료되면 스택에 남은 흔적은 주 프로그램에 반복 횟수를 알려줍니다.


3

파이썬 3, 150 138 바이트

n=int(input())
S=sum
l=[1]
i=s=1
while S(l)<n:i+=1;l+=[i]
while S(l)!=n:
 while S(l)>n:l.pop(0)
 s+=1
 if S(l)<n:i+=1;l+=[i];s+=1
print(s)

변경 로그:

  • 추가를 + =로 변경하고 다른 것을 제거했습니다 (musicman523, Loovjo 덕분에 -12 바이트).

1
2 단계 는 목록 에서 한 번에 하나 이상의 용어를 제거 할 수 있지만 (예 : N = 11의 경우 1, 2 및 3) 한 단계로 계산됩니다.
Arnauld

@Arnauld는 그것을 간과했습니다. 결정된.
L3viathan

1
else필요한지 설명 할 수 있습니까 ? 내가 믿는 else루프가 항상 (없이 정상적으로 종료하기 때문에, 때마다 실행 break), 그리고 그것없이 잘 작동 보인다 .
musicman523

A=l.append부품을 건너 뛰고 l+=[x]대신 사용할 수 있습니다 .
Loovjo

3

배치, 126 바이트

@echo off
set/an=s=l=u=0
:l
if %s% lss %1 set/as+=u+=1,n+=!!l&goto l
if %s% gtr %1 set/as-=l+=1&goto l
cmd/cset/an+n+2-!l

설명 : l2 단계를 실행 한 적이 없으면 0입니다. 이를 통해 n3 단계의 반복 횟수를 추적 할 수 있습니다 . 알고리즘은 3 단계에서 중지되지 않으므로 n+1전체 n+n+2단계에 대해 1 단계와 2 단계를 한 번 실행해야 합니다. 그러나 매개 변수가 삼각형이면 단계 2는 실행되지 않으므로 한 단계를 빼야합니다.


3

파이썬 2, 86 81 바이트

n=input()
l=u=i=s=0
while n:k=n>0;i+=k^s;s=k;l+=k;n-=l*k;u+=k^1;n+=u*-~-k
print i

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

TIO 에서 65536 테스트 케이스를 계산합니다 0.183s.


84 바이트의이 재귀 버전은 최대 65536까지의 모든 값을 계산할 수 없습니다.

def f(n,l=[0],m=1):k=n>sum(l);return n==sum(l)or f(n,[l[1:],l+[l[-1]+1]][k],k)+(m^k)

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


2

Mathematica, 92 바이트

(For[q=a=b=0;t={},t~AppendTo~q;q!=#,If[q<#,q+=++b,q-=++a]];Length@Split@Sign@Differences@t)&

정수 인수를 사용하여 정수를 리턴하는 순수 함수.

변수 ab위해 스탠드, 고려 합 시작과 끝 번호 (끊임없이 변화) 동안 q(숫자에서 실행중인 총 스탠드 a+1b); 지금까지 발생한 t모든 값을 추적합니다 q. 이러한 변수를 초기화 한 후 For루프는 계속 실행됩니다 If[q<#,q+=++b,q-=++a].이 값은 끝에 새로운 숫자를 추가하거나 사양에서 지시 한대로 q입력과 같아 질 때까지 앞의 숫자를 뺍니다 .

이제 단계에서 발생 t하는 q값 목록 에서 단계 수를 추출하면 됩니다. 예를 들어, 입력이 11이면 For루프는 t등호로 종료됩니다 {0,1,3,6,10,15,14,12,9,15,11}. 이 단계에서 걸음 수를 계산하는 가장 좋은 방법은 차이가 올라가고 내려가는 횟수를 세는 것입니다. 그것이 자세한 명령 Length@Split@Sign@Differences@t이하는 일이지만 개선 될 수 있다고 생각합니다.


2

C (tcc), 71 바이트 (61 + 10)

명령 줄 인수 (공백 포함) :

-Dw=while

출처:

c,m,M,s;f(n){w(++c,s-n){w(c&s<n)s+=++M;w(~c&s>n)s-=m++;}--c;}

작동 방식 :

c걸음 수를 계산합니다. mM범위의 최소 및 최대 저장 s합. 처음에는 모두 0입니다.

지속적 c으로 증가하고 s비교됩니다 n. 그들이 동일하지 않은 한 :

  • 경우 c홀수, 다음만큼 s<n의 범위의 단부의 정수를 추가 증가 M하나에 의해 s의해 M.

  • 경우 c만큼도 다음입니다 s>n, 범위의 시작의 정수를 제거 : 감소 s에 의해 m, 그리고 증가 m하나.

루프가 종료되면 c너무 많이 증가했습니다. 값을 줄이면 올바른 결과가 나오고 올바른 레지스터에서 계산되어 반환 값으로 작동합니다.

Khaled.K 의 C answer 와 정확히 동일한 변수 이름을 사용하는 것이 재미 있습니다. 그들은 복사되지 않습니다.


1

펄 6 , 114 바이트

{((0,0,1),->(\a,\b,\c){b,(a..*).first(->\d{(d,b).minmax.sum*c>=$_*c}),-c}...->(\a,\b,\c){(a,b).minmax.sum==$_})-1}

(이전의 Haskell 구현에서 영감을 얻음 )

그것을 시도하십시오
내 컴퓨터에서 45 초 안에 65536의 입력으로 실행되지만 TIO.run을 사용하여 60 초 안에 실행할 수 없었습니다.
Rakudo v2017.04 +가 있으며 v2017.01이 있습니다.
Rakudo / NQP / MoarVM은 거의 매일 최적화를 수행하므로, 시간이 지남에 따라 필요한 중간에 여러 가지가있을 수 있습니다.


넓히는

{
  (

    # generate a sequence

    (0,0,1),           # initial value 

    -> (\a,\b,\c) {
      b,               # swap the first two values

      (a..*)
      .first(          # find the first number that brings us to or past the input

        -> \d {
          (d,b).minmax # get a Range object regardless of which is larger
          .sum * c     # sum it, and negate it every other time

          >=           # is it equal to or greater than

          $_ * c       # negate the original input every other time
        }

      ),

      -c               # invert for next round
    }

    ...                # keep doing that until

    -> (\a,\b,\c) {
     (a,b).minmax.sum == $_ # it finally reaches the input
    }

  ) - 1 # count the number of elements in the sequence
        # and subtract one for the initializer
}

Rakudo는 Range.sum모든 값을 반복 할 필요가 없도록 최적화되었습니다 .

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