Bir Fraktal Dizinin Yakınsama Toplamları


16

Arka fon

Bir fraktal dizi , her tamsayıdaki ilk oluşumunu kaldırabileceğiniz ve önceki ile aynı diziyle sonuçlayabileceğiniz bir tamsayı dizisidir.

Çok basit bir sıraya Kimberling'in açıklamaları denir . Pozitif doğal sayılarla başlarsınız:

1, 2, 3, 4, 5, 6, 7, 8, 9, ...

Sonra bazı boşluklarda fırfırlar:

1, _, 2, _, 3, _, 4, _, 5, _, 6, _, 7, _, 8, _, 9, ...

Ve sonra boşlukları tekrar tekrar dizinin kendisiyle doldurursunuz (boşluklar dahil):

1, 1, 2, _, 3, 2, 4, _, 5, 3, 6, _, 7, 4, 8, _, 9, ...
1, 1, 2, 1, 3, 2, 4, _, 5, 3, 6, 2, 7, 4, 8, _, 9, ...
1, 1, 2, 1, 3, 2, 4, 1, 5, 3, 6, 2, 7, 4, 8, _, 9, ...
1, 1, 2, 1, 3, 2, 4, 1, 5, 3, 6, 2, 7, 4, 8, 1, 9, ...

Bu bizim fraktal dizimiz! Şimdi kısmi toplamları alalım:

1, 2, 4, 5, 8, 10, 14, 15, 20, 23, 29, 31, 38, 42, 50, 51, 60, ...

Peki ya bu süreci tekrarlarsak? Yeni diziyi "fraktalize edin" (yani yukarıdaki adımlardan elde edilen kısmi toplamlar):

1, _, 2, _, 4, _, 5, _, 8, _, 10, _, 14, _, 15, _, 20, _, 23, ...
1, 1, 2, _, 4, 2, 5, _, 8, 4, 10, _, 14, 5, 15, _, 20, 8, 23, ...
1, 1, 2, 1, 4, 2, 5, _, 8, 4, 10, 2, 14, 5, 15, _, 20, 8, 23, ...
1, 1, 2, 1, 4, 2, 5, 1, 8, 4, 10, 2, 14, 5, 15, _, 20, 8, 23, ...
1, 1, 2, 1, 4, 2, 5, 1, 8, 4, 10, 2, 14, 5, 15, 1, 20, 8, 23, ...

Ve kısmi toplamları tekrar alın:

1, 2, 4, 5, 9, 11, 16, 17, 25, 29, 39, 41, 55, 60, 75, 76, 96, ...

Durulayın, tekrarlayın. Bu sürecin birleştiği ortaya çıkıyor. Bu işlemi her tekrarladığınızda, dizinin daha büyük bir öneki sabit kalır. Sonsuz miktarda yinelemeden sonra, OEIS A085765 ile sonuçlanırsınız .

İlginç gerçek: Bu işlem, orijinal dizi ile başladığımız sürece doğal sayılardan başlamasak bile aynı diziye yakınsar 1. Orijinal sekans başka bir sekansla başlarsa x, x*A085765bunun yerine elde ederiz .

Meydan okuma

Pozitif bir tamsayı verildiğinde , yakınsak dizinin th elemanını Nçıktılar N.

STDIN (veya en yakın alternatif), komut satırı bağımsız değişkeni veya işlev bağımsız değişkeni ile girdi alarak ve sonucu STDOUT (veya en yakın alternatif), işlev dönüş değeri veya işlev (çıkış) parametresi aracılığıyla çıktı alarak bir program veya işlev yazabilirsiniz.

Dizinin N0- veya 1 tabanlı olup olmadığını seçebilirsiniz .

Test Durumları

Dizi şununla başlar:

1, 2, 4, 5, 9, 11, 16, 17, 26, 30, 41, 43, 59, 64, 81, 82, 108, 117, 147, 151, 192, 203, 246, 248, 307, 323, 387, 392, 473, 490, 572, 573, 681, 707, 824, 833, 980, 1010, 1161, 1165, 1357, 1398, 1601, 1612, 1858, 1901, 2149, 2151, 2458, 2517

Bu yüzden girdi 5çıktı ile sonuçlanmalıdır 9.

İşte (STDIN'deN verilen N) ilk sayıları üreten saf bir CJam referans uygulaması . Kodunuzun Ntüm öneki değil, yalnızca th öğesini döndürmesi gerektiğini unutmayın .


Yani sadece kontrol ediyoruz: A085765'inN th terimini veriyoruz , değil mi?
GamrCorps

@GamrCorps Evet.
Martin Ender

Yanıtlar:


7

CJam ( 23 22 bayt)

Kısmi toplamlar, fraktal dizinin A086450 olan çift dizinlerinde verilir . Burada A086450'nin tanımı olarak verilen nüks bu uygulamaların temelini oluşturur.

Açık bir "yığın" (LIFO olmadığı için korkutucu tırnak içinde) kullanma:

{),){2md~)\),>+$)}h+,}

Çevrimiçi demo

teşrih

{         e# Anonymous function body; for clarify, pretend it's f(x)
          e# We use a stack [x_0 ... x_i] with invariant: the result is sum_j f(x_j)
  ),      e# Initialise the stack to [0 ... x]
  )       e# Uncons x, because our loop wants one value outside the stack
  {       e# Loop. Stack holds [x_0 ... x_{i-1}] x_i
    2md   e# Split x_i into (x_i)/2 and (x_i)%2
    ~)\   e# Negate (x_i)%2 and flip under (x_i)/2
    ),>   e# If x_i was even, stack now holds [x_0 ... x_{i-1}] [0 1 ... (x_i)/2]
          e# If x_i was odd, stack now holds [x_0 ... x_{i-1}] [(x_i)/2]
    +     e# Append the two arrays
    $     e# Sort to get the new stack
    )     e# Uncons the greatest element in the new stack
  }h      e# If it is non-zero, loop
          e# We now have a stack of zeroes and a loose zero
  +,      e# Count the total number of zeroes, which is equivalent to sum_j f(0)
}

23 baytta, belleğe alma ile çok daha verimli bir yaklaşım var:

{2*1a{2md~)\){j}%>:+}j}

Çevrimiçi demo


1
Eminim uygulamanın daha kısa olacağı bazı diller vardır f(0) = 1; f(n) = f(n/2) + (n % 2 ? 0 : f(n-2)); return f(2*x), ancak CJam'da bu yaklaşımla tasarruf elde etmenin bir yolunu bulamıyorum.
Peter Taylor

9

Python 2, 55 49 42

Neler olduğu hakkında hiçbir fikrim yok, ancak OEIS sayfasından Maple formülünü yenmek zor görünüyor. Bu, 0 tabanlı dizinleme kullanır.

f=lambda n,t=0:n<1or f(n/2,n%2)-~-t*f(n-1)

-6 bayt için @PeterTaylor'a teşekkürler.


Performansı önemsemiyorsanız 6 karakterle optimize etmek kolaydır. İlkinden sonraki parçalar oretkili g(n,1) = f(n/2,n%2); g(n,0) = f(n-1) + g(n,1); böylece ortak g(n,1)almak için dışarı çekebilirsinizf=lambda n,t=0:n<1or f(n/2,n%2)+0**t*f(n-1)
Peter Taylor

3

Haskell, 65

s l=[0..]>>=(\i->[l!!i,s l!!i])
r=1:(tail$scanl1(+)$s r)
f n=r!!n

2

Zararlı Olarak Kabul Edilen Şablonlar , 124

Fun<If<A<1>,Add<Ap<Fun<Ap<If<Sub<A<1>,Mul<I<2>,Div<A<1>,I<2>>>>,A<0>,A<0,1>>,Div<A<1>,I<2>>>>,A<1>>,Ap<A<0>,Sub<A<1>,T>>>,T>>

Bu anonim bir işlevdir. Az ya da çok aynı şekilde var benim Python cevap yerine n% 2/2 * 2 nn kullanmak zorunda, ben modülüne uygulamak vermedi dışında OEIS sayfasındaki Maple formülü.

Expanded:

Fun<If<
    A<1>,
    Add<
        Ap<
            Fun<Ap<
                If<
                    Sub<
                        A<1>,
                        Mul<
                            I<2>,
                            Div<A<1>,I<2> >
                        >
                    >,
                    A<0>,
                    A<0,1>
                >,
                Div<A<1>,I<2>>
            >>,
            A<1>
        >,
        Ap<
            A<0>,
            Sub<A<1>, T>
        >
    >,
    T
>> 

2

Mathematica, 47 44 bayt

If[#<1,1,#0[Floor@#/2]+(1-2#~Mod~1)#0[#-1]]&

0

MATLAB 108 103

İstenen dizinin https://oeis.org/A086450 kısmi toplamı olduğu gerçeğini kullanıyorum

Ancak benim uygulamamın hesaplama karmaşıklığı, bu basit tekrarlama için bile optimal olmaktan çok uzak.

n=input('')+1;
z=zeros(1,n);z(1)=1;
for k=1:n;
z(2*k)=z(k);
z(2*k+1)=sum(z(1:k+1));
end;
disp(sum(z(1:n)))
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.