Fraktal Duman Sırası


33

Giriş

A229037 oldukça merak uyandırıcı bir komploya sahip (en azından ilk birkaç dönem için):

Bir tür fraktal özelliğe sahip olabileceği varsayımı var.

Bu dizi nasıl inşa edilir?

Tanımlama a(1) = 1, a(2) = 1her biri için daha sonra n>2tam sayı minimal Pozitif bulmak a(n)her aritmetik 3 terimi dizisi için bu tür n,n+k,n+2kendekslerin, dizinin karşılık gelen değerler a(n),a(n+k),a(n+2k)olduğu olmayan bir aritmetik dizi.

Meydan okuma

nGiriş olarak pozitif bir tamsayı verildiğinde , bu dizinin ilk nterimlerini çıkar a(1), ... , a(n). (Herhangi bir makul biçimlendirme ile. Olası satır / yönlendirme karakterleri / karakterleri önemli değil.)

Bu diziyi oluşturmak için pasajlar var, ancak diğer yaklaşımların belirli diller için daha golf / daha uygun olabileceğini düşünüyorum.

Lütfen programınızın nasıl çalıştığını bize bildirin. Eğer özellikle etkili bir algoritma bir çarpı işareti gelirseniz, daha kısa zamanda dizinin daha fazla terimini çizmeye izin vereceğinden de bahsetmek isteyebilirsiniz.

İlk birkaç test vakası:

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

Daha fazla test kodu:

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

Tüm terimler n=100000burada bulunabilir: https://oeis.org/A229037/b229037.txt

Yardım ve teşvik için @ MartinBüttner teşekkür ederiz.


2
Hey, bu grafiği daha önce nerede gördüm? :-D
Luis Mendo,

12
Başınızı biraz sola kaydırın, biraz yakınlaştırın, işte gidin! (:
kusur,

4
Çok sayıdaki bir video ortaya çıktı: youtube.com/watch?v=o8c4uYnnNnc
flawr 19

2
Bahse girerim kodu neredeyse golf gibi değildir!
Luis Mendo,

Yanıtlar:


12

Python 2,95 bayt

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

Asıl püf noktası, yeni değerin kaçınması gereken sayıları üretmektir. Şimdiye kadar tersine çevrilmiş diziyi koruyarak, lhangi elementlerin eklemek üzere olduğumuz değerle üç vadeli aritmetik bir ilerleme sağlayabileceğine bakalım.

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

Diğer sayılar , yani lher ikinci elemanın eşleşmiş üyeleridir . Eğer bu çift o zaman aritmetik ilerleme için olur . Kaçınılması gereken kümeleri oluşturduktan sonra , kod, tamamlayıcıdan minimum tutarı alır, yazdırır ve listeye hazırlar. (Aslında, hesaplama bir adaylar evreni görevi görmesi için sayıları 1 azaltılmış ve 1 daha yüksek basılmış şekilde yapılır .)lzip(l,l[1::2])(b,c)(a,b,c)a=2*b-carange(n)


8

Mathematica, 95 bayt

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]]&

Kesinlikle en golfçü yaklaşım değil, ancak bu, OEIS sayfasından çalıştığım algoritmalara kıyasla oldukça verimli.

Her s (n) için tüm yasak değerlerini kontrol etmenin aksine, oraya gidince elek temelli bir yaklaşım kullanıyorum. Yeni bir s (n) değeri bulduğumuzda, bunun m> n için hangi değerleri yasakladığını hemen kontrol ederiz . Sonra s (n + 1) 'i yasaklanmayan ilk değeri arayarak çözeriz .

Bu şartlı --i>0olarak değiştirerek daha verimli yapılabilir 2n-#<=--i>0. Bu durumda, girişten daha büyük n için yasaklı değerleri kontrol etmekten kaçınırız .

Biraz daha okunaklı bir sürüm için, sonuçları maxbir fonksiyonda saklayan bu kodla başladım fve daha sonra yukarıdaki tek satırlık saf fonksiyona girdim:

 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

Haskell, 90 , 89 , 84 , 83 bayt

Muhtemelen daha çok golf oynayabilir, ancak bu hala iyi ilk girişim:

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

Ungolfed:

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

Bu, sınırların dışında '0' döndüren basit bir uygulamadır. Daha sonra, olası her değer için, tüm k <= n ve sınırları içindeki [x, a (xk), a (x-2k)] öğesinin aritmetik bir sıralama olmadığını kontrol eder.

Zaman karmaşıklığına bağlı olarak üst sınır (OEIS sayfasındaki bir (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)!)

Bu sınırın ne kadar iyi olduğundan emin değilim çünkü 't' nin ilk 1k değerlerini hesaplamak ve değerlerin günlüklerinde appx verilmiş olan lineer bir model kullanmak. O (22 ^ n), p değeri <10 ^ (- 1291), olması durumunda.

Bir uygulama düzeyinde, '-O2' ile derlemek, ilk 20 değeri hesaplamak için ~ 35 dakika sürdü.


1
Programınız için zaman karmaşıklığı nedir?
kusur,

@flawr Gönderiye biraz zaman karmaşıklık analizi eklendi
Michael Klein

3

Brachylog , 33 31 bayt

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

Çevrimiçi deneyin!

Önemli olması durumunda: Bu zorlukta çalıştıktan sonra istediğim özellik sayesinde 2 baytlık golf mümkündü .

açıklama

Diziyi yinelemeli sırayla liste halinde oluştururuz, örn. [2,2,1,1,2,1,1] , ve sonunda tersine.

Burada iç içe geçmiş birkaç tahmin var. Onlara içten dışa bakalım. İlki ġh₃hᵐs₂ᶠ-ᵐ=aday adayı alır a(n),a(n-1),...,a(0)ve a(n),a(n-k),a(n-2k)bazıları için aritmetik sekans olup olmadığını belirler 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

Örneğin, giriş ile [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.

Bir sonraki tahmin, dışa doğru ~b.hℕ₁≜∧.¬{...}∧bir girdi oluşturur a(n-1),a(n-2),...,a(0)ve bir sonraki daha büyük sırayı verir 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

Son olarak, ana belirteç ;Ė{...}ⁱ⁽↔bir girdi numarası alır ve dizinin birçok terimini çıkarır.

;Ė{...}ⁱ⁽↔
;           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

Ruby , 71 bayt

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

Çevrimiçi deneyin!

Tüm yasaklanmış değerleri oluşturur, daha sonra bu dizinin tamamlayıcısını (1..n) içine alır ve sonucun ilk değerini alır. Bu, varsaydığım anlamına gelira[n] <= n , tüm n'lerin indüksiyon kullanılarak kolayca kanıtlanabileceğini (ilk n / 2 terimlerinin hepsinin n / 2'den küçük olması durumunda, o zaman n'e giden bir aritmetik ilerleme olamaz) anlamına gelir.

Buradaki sözdizimsel hilesi de oldukça ilginç: *aek argümanlar dizisini başlatmak için kullanılır (eğer a.fillgeçersek göz ardı edilirse) ve argüman dizisini değiştirir ve sonra onu döndürür.


1
-1 bayt: yerine a[s-o]ve a[s-2*o]kullanabilirsiniz a[s-=1]vea[s-o]
GB

3

APL (Dyalog Genişletilmiş) , 37 bayt SBCS

Bu cevabı , APL dilini öğrenmek için harika bir yer olan The APL Orchard'da yazma ve golf oynamadaki yardımları için Adám'a teşekkür ederiz . Çevrimiçi deneyin!

Düzenleme: Adám sayesinde -6 bayt

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

açıklama

{⍵,⍨⊃(⍳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 bayt SBCS

İşte ⍺(10000)birkaç saniye içinde hesaplayabilen daha hızlı ancak daha az golfçü bir çözüm .

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

Çevrimiçi deneyin!


2

MATLAB, 156 147 bayt

Sonunda biraz golf oynamak için aldım:

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

Ungolfed:

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=...

Giriş STDIN'den okunur ve yazdırma otomatik olarak ans=ve eklenir. Umarım bu "makul" bir çıktı olarak nitelendirilir.

Bu, aynı zamanda, bir elek-esaslı bir çözelti olmaktadır: değişken s(i,:)olan bu dizi değerleri izler yasak için a(i). try-catchBlok boş (yani tam sıfır) durumunda tedavi için gereklidir smatris: bu durumda, en düşük değeri 1önceden verilir.

Ancak, bellek ihtiyacı (veya çalışma zamanı?) Yukarıda oldukça karışıklaşıyor N=2000. İşte burada rekabet etmeyen, daha verimli bir çözüm:

%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

Bu uygulamada smatris yine yasak değerler içeriyor, ancak sıralı bir şekilde, sıfır blok olmadan (rakip sürümde mevcut olan). İndeks vektörü i, içerisindeki yasak vektörlerin sayısını izler s. İlk bakışta hücreler, depolanan bilgilerin kaydını tutmak için harika olurdu s, ama bunlar yavaş olacaktı ve aynı anda bir demetini endeksleyemedik.

MATLAB'ın kötü özelliklerinden biri, M(1,end+1)=3;bir matrisi söyleyip otomatik olarak genişletebilmenize rağmen, aynı şeyi lineer indeksleme ile yapamayacağınızdır. Bir anlam ifade ediyor (MATLAB, lineer endeksleri yorumlayabilmesi için ortaya çıkan dizi boyutunu nasıl bilmeli?) Ama yine de beni şaşırttı. Gereksiz çizginin nedeni budur s(N,max(i(j))) = 0;: bu sgerektiğinde matrisi bizim için genişletir . Başlangıç ​​büyüklüğü tahmini N*0.07+20, bu arada doğrusal bir uyumdan ilk birkaç elemana kadar geliyor.

Çalışma zamanını test etmek için, kodun biraz değiştirilmiş bir sürümünü de kontrol ettim; burada smatrisi boyutlandırmak için başlattım N/2. İlk 1e5unsurlar için bu çok cömert bir tahmin gibi görünüyor, bu yüzden sönceki paragrafta belirtilen genişleme adımını kaldırdım . Bunlar birlikte kodun daha hızlı olacağını ancak çok yüksek oranda daha az sağlam Nolacağını (serinin orada nasıl göründüğünü bilmediğimden beri) ima ediyor .

Yani burada birkaç çalışma zamanı, karşılaştırarak

  • v1: rakip golf versiyonunu,
  • v2: düşük başlangıç ​​boyutu, kusursuz sürüm ve
  • v3: cömert-başlangıç ​​büyüklüğü, büyük N sürümü için başarısız olabilir.

Bunları R2012b'de ölçtüm, adlandırılmış bir fonksiyon tanımı içinde 5 çalıştırmanın en iyisini alarak 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 (beklemedi)
    • v2: 2.021213 s
    • v3: 1.572958 s
  6. N=10000:
    • v1: N / A
    • v2: 6.248483 s
    • v3: 5.812838 s

v3Sürüm önemli ölçüde, ancak ezici bir şekilde daha hızlı değil gibi görünüyor . Bir belirsizlik unsurunun (çok büyük N) çalışma zamanındaki küçük artışa değip değmeyeceğini bilmiyorum .


M=1;M(end+1)=2;benim için mükemmel çalışıyor mu?
kusur,

@ skaler ve vektörler için çalışacak @flawr. M=rand(2); M(end+1)=2Bunun yerine deneyin :)
Andras Deak

Ah şimdi anlıyorum =)
kusur

2

Jöle , 24 19 bayt

Bu bir süredir ilk Jelly cevabım. Dönmüş olmaktan mutluyum.

Bu, burada kullanılan algoritmaların çoğunun bir uyarlaması olan APL cevabımın bir limanı . En büyük fark, bunun 0 indeksli olmasıdır.

Düzenleme: Jonathan Allan sayesinde -5 bayt.

Çevrimiçi deneyin!

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

açıklama

Ḋ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.

sadece œ-bir bayt tasarrufu yapmanın yanı sıra yapacak
Jonathan Allan

Oldukça emin (uyarınca endeksi sıfır olabilir dizisi ) ve böylece yerini “”ile 1bir daha tasarruflu, tam programdan bir listesinin bir jöle temsilini çıkışı.
Jonathan Allan

Œœị@2Ḋm2iki tasarruf için golf olabilir .
Jonathan Allan,

L‘RŻJbirini kurtarmak için golf olabilir .
Jonathan Allan,

@JonathanAllan Beş bütün bayt! Teşekkürler!
Sherlock9

1

ES6, 114 bayt

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

Dizinin ilk n öğelerinin bir dizisini döndürür, bu nedenle endeksler aşağıdaki ungolfed sürümünün 1’idir. Elek yaklaşımını kullandım. Bu sürüm n = 2000'den sonra yavaşlar; önceki bir sürüm dizinin başlangıcından okumaktan kaçınıyordu, bu da n = 2500'e kadar yavaşlamadığı anlamına geliyordu. Daha eski bir versiyon elek dizisini, değerlerin yasaklandığı bir boolean dizisinden ziyade yasak değerlerin bir listesi olarak kullandı; bu, ter kırmadan yaklaşık n = 5000 seviyesine ulaşabilir. Orijinal sürümüm bit maskeleri kullanmayı denedi, ancak faydasız olduğu ortaya çıktı (ve 198 byte'da da çok uzundu).

Oldukça yavaş olmayan bir sürüm 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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.