프랙탈 연기 시퀀스


32

소개

A229037 에는 아주 흥미로운 음모가 있습니다 (적어도 처음 몇 용어에 대해서는).

실제로 어떤 종류의 프랙탈 속성을 가질 수 있다는 추측이 있습니다.

이 순서는 어떻게 구성됩니까?

정의 a(1) = 1, a(2) = 1각각에 대해 다음 n>2정수 최소 긍정적 찾을 a(n)마다 산술 3 기간 시퀀스가되도록 n,n+k,n+2k인덱스 시퀀스의 대응되는 값 a(n),a(n+k),a(n+2k)이다 하지 연산 시퀀스.

도전

양의 정수 n를 입력으로 받으면 이 시퀀스 의 첫 번째 na(1), ... , a(n)을 출력하십시오 . (합리적인 형식으로 가능합니다. 가능한 선행 / 훈련 문자 / 문자열은 관련이 없습니다.)

이 시퀀스를 생성하는 스 니펫이 있지만 특정 언어에 대해 다른 접근 방식이 더 골프화 가능하거나 더 적합하다고 생각합니다.

당신의 progrm 작동 방식을 알려주십시오. 특히 효율적인 알고리즘을 사용하는 경우 더 짧은 시간에 더 많은 시퀀스 항을 그릴 수 있으므로 언급 할 수도 있습니다.

처음 몇 가지 테스트 사례 :

1, 1, 2, 1, 1, 2, 2, 4, 4, 1, 1, 2, 1, 1, 2, 2, 4, 4, 2, 4, 4, 5, 5, 8, 5, 5, 9, 1, 1, 2, 1, 1, 2, 2, 4, 4, 1, 1, 2, 1, 1, 2, 2, 4, 4, 2, 4, 4, 5, 5, 8, 5, 5, 9, 9, 4, 4, 5, 5, 10, 5, 5, 10, 2, 10, 13, 11, 10, 8, 11, 13, 10, 12, 10, 10, 12, 10, 11, 14, 20, 13

더 많은 테스트 사례 :

  a(100)  =   4
  a(500)  =   5
 a(1000)  =  55
 a(5000)  =  15
a(10000)  = 585

https://oeis.org/A229037/b229037.txtn=100000 : 여기 까지 모든 용어를 사용할 수 있습니다

도움과 격려를 주신 @ MartinBüttner에게 감사드립니다.


2
이봐 요,이 그래프를 전에 본 적이 있습니까? :-D
Luis Mendo 2016 년

12
머리를 약간 왼쪽으로 움직이고 조금 확대하면됩니다. (:
flawr

4
숫자 동영상이 방금 나왔습니다 : youtube.com/watch?v=o8c4uYnnNnc
flawr

2
나는 그의 코드가 거의 골프가 아니라고 확신합니다!
Luis Mendo

답변:


12

파이썬 2, 95 바이트

l=[];n=input()
exec"a=min(set(range(n))-{2*b-c for b,c in zip(l,l[1::2])});print-~a;l=[a]+l;"*n

주요 트릭은 새로운 값이 피해야하는 숫자를 생성하는 것입니다. 지금까지 반대 순서를 유지하면서 l추가하려는 값으로 어떤 요소가 3 기 산술 연산을 구성 할 수 있는지 살펴 보겠습니다.

? 4 2 2 1 1 2 1 1   a b c
^ ^ ^               ? 4 2
^   ^   ^           ? 2 1
^     ^     ^       ? 2 2
^       ^       ^   ? 1 1

다른 번호의 쌍 구성원 l및 모든 두 번째 요소 l때문에 zip(l,l[1::2]). 이 쌍 (b,c)이면에 대한 산술 진행이 (a,b,c)발생합니다 a=2*b-c. a피하기 위해 의 세트를 생성 한 후 , 코드는 최소의 보수를 취하여 인쇄 한 다음 목록 앞에 추가합니다. (실제로, 계산은 range(n)후보의 우주 역할 을하도록 1 씩 감소하고 1을 더 높게 인쇄하여 수행됩니다.)


8

Mathematica, 95 바이트

For[n_~s~k_=0;n=0,n<#,For[i=n,--i>0,s[2n-i,2f@n-f@i]=1];For[++n;i=1,n~s~i>0,++i];Print[f@n=i]]&

확실히 가장 골치 아픈 접근법은 아니지만 OEIS 페이지에서 시도한 알고리즘과 비교할 때 실제로 상당히 효율적입니다.

우리가 거기에 도착했을 때 각 s (n) 에 대해 금지 된 모든 값을 확인하는 것과는 달리 체 기반 접근 방식을 사용하고 있습니다. 새로운 값 s (n) 을 찾으면 m> n에 대해 어떤 값을 금지하는지 즉시 확인합니다 . 그런 다음 금지되지 않은 첫 번째 값을 찾아서 s (n + 1) 을 해결하면 됩니다.

조건 --i>0을 로 변경하여보다 효율적으로 만들 수 있습니다 2n-#<=--i>0. 이 경우 입력 값 보다 큰 n에 대해 금지 된 값을 확인하지 않아도됩니다 .

좀 더 읽기 쉬운 버전의 경우이 코드로 시작하여 결과를 max함수에 저장 f한 다음 위의 한 줄 순수 함수로 골프화했습니다.

 max = 1000;
 ClearAll[sieve, f];
 sieve[n_, k_] = False;
 For[n = 0, n < max,
  temp = f[n];
  For[i = n - 1, i > 0 && 2 n - i <= max, --i,
   sieve[2 n - i, 2 temp - f[i]] = True;
   ];
  ++n;
  i = 1;
  While[sieve[n, i], ++i];
  f@n = i;
  ]

3

하스켈, 90 , 89 , 84 , 83 바이트

아마도 더 골프를 칠 수는 있지만 이것은 여전히 ​​좋은 시도입니다.

a n|n<1=0|n<3=1|1<2=[x|x<-[1..],and[x/=2*a(n-k)-a(n-k-k)||a(n-k-k)<1|k<-[1..n]]]!!0

언 골프 드 :

a n | n<1        = 0 
    | n<3        = 1
    | otherwise  = head (goods n)

goods n = [x | x <- [1..], isGood x n]

isGood x n = and [ x - a(n-k) /= a(n-k) - a(n-k-k) || a(n-k-k) == 0 | k <- [1..n] ]

범위를 벗어난 경우 '0'을 반환하는 간단한 구현입니다. 그런 다음 각 가능한 값에 대해 모든 k <= n 및 범위 내에서 [x, a (xk), a (x-2k)]가 산술 시퀀스가 ​​아닌지 확인합니다.

상한 시간 복잡성 (OEIS 페이지의 사실을 사용하여 a (n) <= (n + 1) / 2 :

t n <= sum[ sum[2*t(n-k) + 2*t(n-k-k) | k <- [1..n]] | x <- [1..(n+1)/2]]
    <= sum[ sum[4*t(n-1)              | k <- [1..n]] | x <- [1..(n+1)/2]]
    <= sum[     4*t(n-1)*n                         ] | x <- [1..(n+1)/2]]
    <=          4*t(n-1)*n*(n+1)/2
    ->
O(t(n)) == O(2^(n-2) * n! * (n+1)!)

't'의 첫 번째 1k 값을 계산하고 appx에 주어진 값의 로그에 선형 모델을 사용하기 때문에이 경계가 얼마나 좋은지 잘 모르겠습니다. 중요한 경우 p- 값이 10 ^ (-1291) 인 O (22 ^ n)

'-O2'로 컴파일하는 구현 수준에서 처음 20 개의 값을 계산하는 데 ~ 35 분이 걸렸습니다.


1
프로그램의 시간 복잡성은 무엇입니까?
flawr

@flawr 게시물에 시간 복잡성 분석 추가
Michael Klein

3

Brachylog , 33 31 바이트

;Ė{~b.hℕ₁≜∧.¬{ġh₃hᵐs₂ᶠ-ᵐ=}∧}ⁱ⁽↔

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

중요한 경우 : 이 과제를 수행 한 후 요청한 기능 덕분에 2 바이트 골프가 가능 했습니다.

설명

예를 들어 [2,2,1,1,2,1,1], 순서대로 역순으로 목록으로 시퀀스를 생성 하고 끝에서 역순으로 만듭니다.

여기에 두 개의 중첩 술어가 있습니다. 안쪽에서 밖을 보자. 첫 번째 ġh₃hᵐs₂ᶠ-ᵐ=는 후보 서브 시퀀스를 취하여 some의 산술 시퀀스 a(n),a(n-1),...,a(0)인지 여부를 결정합니다 .a(n),a(n-k),a(n-2k)k

ġ            Group the list into equal-length sublists (with the possible exception of
             the last sublist, which might be shorter)
 h₃          Get the first 3 sublists from that list
   hᵐ        and get the head of each of those 3 sublists
             We now have a list containing a(n),a(n-k),a(n-2k) for some k
     s₂ᶠ     Find all 2-element sublists of that list: [a(n),a(n-k)] and [a(n-k),a(n-2k)]
        -ᵐ   Find the difference of each pair
          =  Assert that the two pairwise differences are equal

예를 들어, 입력으로 [1,2,1,1,2,1,1]:

ġ has possible outputs of
    [[1],[2],[1],[1],[2],[1],[1]]
    [[1,2],[1,1],[2,1],[1]]
    [[1,2,1],[1,2,1],[1]]
    [[1,2,1,1],[2,1,1]]
    [[1,2,1,1,2],[1,1]]
    [[1,2,1,1,2,1],[1]]
    [[1,2,1,1,2,1,1]]
h₃ has possible outputs of
    [[1],[2],[1]]
    [[1,2],[1,1],[2,1]]
    [[1,2,1],[1,2,1],[1]]
hᵐ has possible outputs of
    [1,2,1]
    [1,1,2]
    [1,1,1]
s₂ᶠ has possible outputs of
    [[1,2],[2,1]]
    [[1,1],[1,2]]
    [[1,1],[1,1]]
-ᵐ has possible outputs of
    [-1,1]
    [0,-1]
    [0,0]
= is satisfied by the last of these, so the predicate succeeds.

다음 술어는 바깥쪽으로 서브 ~b.hℕ₁≜∧.¬{...}∧시퀀스 a(n-1),a(n-2),...,a(0)를 입력하고 다음으로 큰 서브 시퀀스를 출력합니다 a(n),a(n-1),a(n-2),...,a(0).

~b.hℕ₁≜∧.¬{...}∧
~b.                 The input is the result of beheading the output; i.e., the output is
                    the input with some value prepended
  .h                The head of the output
    ℕ₁              is a natural number >= 1
      ≜             Force a choice as to which number (I'm not sure why this is necessary,
                    but the code doesn't work without it)
        ∧           Also,
         .          the output
          ¬{...}    does not satisfy the nested predicate (see above)
                    I.e. there is no k such that a(n),a(n-k),a(n-2k) is an arithmetic sequence
                ∧   Break unification with the output

마지막으로 기본 술어 ;Ė{...}ⁱ⁽↔는 입력 번호를 사용하여 시퀀스의 많은 항을 출력합니다.

;Ė{...}ⁱ⁽↔
;           Pair the input number with
 Ė          the empty list
  {...}ⁱ⁽   Using the first element of the pair as the iteration count and the second
            element as the initial value, iterate the nested predicate (see above)
         ↔  Reverse, putting the sequence in the proper order

3

루비 , 71 바이트

->n,*a{a.fill(0,n){|s|([*1..n]-(1..s/2).map{|o|2*a[s-o]-a[s-2*o]})[0]}}

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

모든 금지 된 값을 생성 한 다음 (1..n)에서 해당 배열의 보수를 취하고 결과의 첫 번째 값을 취합니다. 즉 a[n] <= n, 유도를 사용하여 쉽게 입증되는 모든 n에 대해 가정하고 있음 을 의미 합니다 (첫 번째 n / 2 항이 모두 n / 2보다 작 으면 n으로 이어지는 산술 진행이 불가능합니다).

여기의 구문 요령도 약간 흥미 롭습니다. *a추가 인수의 배열을 초기화하는 데 사용됩니다 (우리가 전달하면 무시됩니다). 그런 다음 a.fill인수 배열 을 변경하고 암시 적으로 반환합니다.


3

APL (Dyalog Extended) , 37 바이트 SBCS

APL 언어를 배우기에 좋은 장소 인 APL Orchard 에서이 답변을 작성하고 골프를 치는 데 도움을 준 Adám에게 많은 감사를드립니다 . 온라인으로 사용해보십시오!

편집 : Adám 덕분에 -6 바이트

⌽{⍵,⍨⊃(⍳1+≢⍵)~-¯2⊥⍵[2×⍀⍥⍳⌊2÷⍨≢⍵]}⍣⎕,⍬

설명

{⍵,⍨⊃(⍳1+≢⍵)~-¯2⊥⍵[2×⍀⍥⍳⌊2÷⍨≢⍵]}   is our right argument, the sequence S

                        2÷⍨≢⍵    We start by calculating X = len(S2
                                 Get a range [1, X]
                   2×⍀⍥           With that we can get S[:X] and S[:X×2:2]
                                  or S up to halfway and every 2nd element of S
             2⊥⍵[           ]   And with that we can get 2*S[:X] - S[:X×2:2]
                                  Which is C=2*B-A of a progression A B C
     (⍳1+≢⍵)~                     We remove these Cs from our possible a(n)s
                                  I use range [1, len(S)+1]
                                 Get the first result, which is the minimum
 ⍵,⍨                              And then prepend that to S


⌽{...}⍣⎕,⍬

 {...}⍣⎕    We iterate an "input"  times
        ,⍬  with an empty list  as the initial S
           and reversing S at the end as we have built it backwards

APL (Dyalog Unicode) , 43 39 38 바이트 SBCS

⍺(10000)몇 초 안에 계산할 수있는 더 빠르지 만 덜 골프적인 솔루션이 있습니다 .

⌽{⍵,⍨⊃(⍳1+≢⍵)~-⌿⍵[1 2 1∘.×⍳⌊2÷⍨≢⍵]}⍣⎕,⍬

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


2

MATLAB, (156) 147 바이트

나는 마침내 이것을 조금 아래로 골프에 갔다.

N=input('');s=[0;0];for n=1:N,x=s(n,~~s(n,:));try,a(n)=find(~ismember(1:max(x)+1,x),1);catch,a(n)=1;end,s(n+1:2*n-1,end+1)=2*a(n)-a(n-1:-1:1);end,a

언 골프 드 :

N=input('');                                   % read N from stdin

s=[0;0];
for n=1:N,
    x=s(n,~~s(n,:));                           % x=nonzeros(s(n,:));
    try,
        a(n)=find(~ismember(1:max(x)+1,x),1);  % smallest OK number
    catch,
        a(n)=1;                                % case of blank page for n
    end,

    s(n+1:2*n-1,end+1)=2*a(n)-a(n-1:-1:1);     % determined new forbidden values
end,
a                                              % print ans=...

STDIN에서 입력을 읽고 인쇄 ans=하고 추가 한 내용을 자동으로 인쇄 합니다. 이것이 "합리적인"결과물이되기를 바랍니다.

이것은 체 기반 솔루션입니다. 변수 s(i,:)금지 된 시퀀스 값을 추적 합니다 a(i). try-catch블록은 빈 (즉 완전 제로)의 경우 치료를 위해 필요한 s행렬이 경우의 최저 값은 1이미 허용된다.

그러나 메모리 필요 (또는 런타임?)는 위에 상당히 지저분 해 N=2000집니다. 따라서 경쟁적이지 않고 더 효율적인 솔루션이 있습니다.

%pre-alloc
s = zeros([N,fix(N*0.07+20)]); %strict upper bound, needs adjusting later
i = zeros(1,N);

a = 1;
for n = 2:N,
    x = s(n,1:i(n));
    if isempty(x),
        a(n) = 1;
    else
        a(n) = find(~ismember(1:max(x)+1,x),1);
    end,

    j = n+1:min(2*n-1,N);
    i(j) = i(j)+1;
    s(N,max(i(j))) = 0;   %adjust matrix size if necessary
    b = a(n-1:-1:1);
    s(sub2ind([N,size(s,2)+1],j,i(j))) = 2*a(n)-b(1:length(j));
end

이 구현에서, s매트릭스는 다시 금지 된 값을 포함하지만, 제로 블록 (경쟁 버전에 존재)없이 잘 정렬 된 방식으로 포함됩니다. 인덱스 벡터 i는의 금지 된 벡터 수를 추적합니다 s. 처음에는 셀에 저장된 정보를 추적 s하는 것이 좋았지 만 속도가 느려 동시에 여러 개의 색인을 생성 할 수 없었습니다.

MATLAB의 불쾌한 특징 중 하나 M(1,end+1)=3;는 행렬을 말하고 자동으로 확장 할 수 있지만 선형 인덱싱에서는 동일한 기능을 수행 할 수 없다는 것입니다. 그것은 일종의 의미가 있습니다 (MATLAB은 선형 인덱스를 해석 해야하는 프레임 워크에서 결과 배열 크기를 어떻게 알아야합니까?). 그러나 여전히 놀랐습니다. 이것이 불필요한 선의 이유입니다 . 필요할 때마다 매트릭스 s(N,max(i(j))) = 0;가 확장됩니다 s. 그런데 시작 크기 추측 N*0.07+20은 처음 몇 요소에 대한 선형 맞춤에서 비롯됩니다.

런타임을 테스트하기 위해 약간 수정 된 코드 버전도 확인했습니다. 여기서 ssize를 갖도록 행렬을 초기화했습니다 N/2. 첫 번째 1e5요소의 경우 이것은 매우 관대 한 추측으로 보이므로 s이전 단락에서 언급 한 확장 단계를 제거했습니다 . 이것들은 함께 코드가 더 빠르지 만 매우 강력하다는 것을 의미합니다 N(시리즈가 어떻게 생겼는지 모르겠 기 때문에).

다음은 몇 가지 런타임입니다.

  • v1 : 경쟁 골프 버전
  • v2 : 낮은 시작 크기의 완벽한 버전
  • v3 : 넉넉한 시작 크기, 대용량 N 버전.

나는 R2012b에서 이것을 측정하여로 명명 된 함수 정의 내에서 5 번의 실행을 가장 잘 수행했습니다 tic/toc.

  1. N=100:
    • v1 : 0.011342 s
    • v2 : 0.015218 s
    • v3 : 0.015076 s
  2. N=500:
    • v1 : 0.101647 s
    • v2 : 0.085277 s
    • v3 : 0.081606 s
  3. N=1000:
    • v1 : 0.641910 s
    • v2 : 0.187911 s
    • v3 : 0.183565 s
  4. N=2000:
    • v1 : 5.010327 s
    • v2 : 0.452892 s
    • v3 : 0.430547 s
  5. N=5000:
    • v1 : N / A (기다리지 않았다)
    • v2 : 2.021213 s
    • v3 : 1.572958 s
  6. N=10000:
    • v1 : N / A
    • v2 : 6.248483 s
    • v3 : 5.812838 s

v3버전이 상당히 높지만 압도적으로 빠르지는 않은 것 같습니다 . 불확실성이 큰 요소가 N런타임에 약간 증가 할 가치가 있는지는 모르겠습니다 .


M=1;M(end+1)=2;나를 위해 완벽하게 작동합니까?
flawr

스칼라와 벡터에서 작동하는 @flawr M=rand(2); M(end+1)=2대신 보십시오 :)
Andras Deak

아 이제는 내가 볼 =)
flawr

2

젤리 , 24 19 바이트

이것은 꽤 오랜 시간 내 첫 젤리 답변입니다. 돌아와서 다행입니다.

이것은 내 APL 답변 의 포트 자체이며 여기에서 사용되는 많은 알고리즘의 적응입니다. 가장 큰 차이점은 이것이 인덱스가 없다는 것입니다.

편집 : Jonathan Allan 덕분에 -5 바이트.

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

Ḋm2ɓṁḤ_
ŻJḟÇṂ;
1Ç¡U

설명

Ḋm2ɓṁḤ_  First link. Takes our current sequence S as our left argument.

         We are trying to calculate, of an arithmetic progression A B C, 
           the C using the formula, C = 2*B - A
Ḋ        Remove the first element of S.
 m2      Get every element at indices 0, 2, 4, ...
           This is equivalent to getting every second element of S, a list of As.
   ɓ     Starts a dyad with reversed arguments.
           The arguments here are S and As.
    ṁ    This molds S in the shape of As, giving us a list of Bs.
     Ḥ   We double the Bs.
      _  And subtract As from 2 * Bs.

ŻJḟÇṂ;  Second link. Takes S as our left argument.

Ż       Append a 0 to S.
 J      Range [1, len(z)]. This gets range [1, len(S) + 1].
  ḟÇ    Filter out the results of the previous link, our Cs.
    Ṃ   Take the minimum of Cs.
     ;  And concatenate it with the rest of the sequence so far.

1Ç¡U  Third link. Where we feed our input, n.

1     A list with the element 1.
 Ç¡   Run the previous link n times.
   U  Reverse everything at the end.

œ-바이트 를 절약 할 뿐 아니라
Allan

확신 당신은 (당 지수 제로 수 순서 ) 등 교체 “”와 함께 1한 번 더 절약, 전체 프로그램 목록의 젤리 표현을 출력한다.
Jonathan Allan

Œœị@2Ḋm2두 개 를 구하기 위해 골프를 치는 것일 수 있습니다 .
Jonathan Allan

L‘RŻJ하나 를 구하기 위해 골프를 치는 것일 수 있습니다 .
Jonathan Allan

@JonathanAllan 5 바이트 전체! 감사!
Sherlock9

1

ES6, 114 바이트

n=>[...r=Array(n)].map((x,i,s)=>{for(y=1;x&&x[y];y++);r[i]=y;for(j=i;++j<n;s[j][y+y-r[i+i-j]]=1)s[j]=s[j]||[]}&&r

시퀀스의 처음 n 개 요소의 배열을 반환하므로 인덱스는 아래의 ungolfed 버전에서 1입니다. 나는 체 접근법을 사용했습니다. 이 버전은 약 n = 2000 후에 느려집니다. 이전 버전에서는 어레이의 시작 부분을 읽지 않아 약 n = 2500까지 느려지지 않았습니다. 이전 버전에서는 값이 금지 된 부울 배열이 아니라 체 배열을 금지 된 값 목록으로 사용했습니다. 이것은 땀을 흘리지 않고 약 n = 5000에 도달 할 수 있습니다. 내 원래 버전은 비트 마스크를 사용하려고 시도했지만 도움이되지 않는 것으로 나타났습니다 (198 바이트에서도 너무 길었습니다).

너무 느린 버전은 ungolfed입니다 :

function smoke(n) {
    result = [];
    sieve = [];
    for (i = 1; i <= n; i++) {
        value = 1;
        if (sieve[i]) {
            while (sieve[i][value]) {
                value++;
            }
        }
        result[i] = value;
        for (j = 1; j < i && i + j <= n; j++) {
            if (!sieve[i + j]) sieve[i + j] = [];
            sieve[i + j][value + value - result[i - j]] = true;
        }
    }
    return result;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.