Konvergierende Summen einer Fraktalsequenz


16

Hintergrund

Eine fraktale Sequenz ist eine Ganzzahlsequenz, bei der Sie das erste Vorkommen jeder Ganzzahl entfernen und dieselbe Sequenz wie zuvor erhalten können.

Eine sehr einfache solche Folge nennt man Kimberlings Paraphrasen . Sie beginnen mit den positiven natürlichen Zahlen:

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

Dann riffelst du ein paar Lücken:

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

Und dann füllen Sie wiederholt die Lücken mit der Sequenz selbst (einschließlich der Lücken):

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

Das ist unsere fraktale Sequenz! Nehmen wir nun die Teilsummen:

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

Aber was ist, wenn wir diesen Prozess wiederholen? "Fraktalisieren" Sie die neue Sequenz (dh die aus den obigen Schritten erhaltenen Teilsummen):

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

Und nimm nochmal die Teilsummen:

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

Spülen, wiederholen. Es stellt sich heraus, dass dieser Prozess konvergiert. Jedes Mal, wenn Sie diesen Vorgang wiederholen, bleibt ein größeres Präfix der Sequenz festgelegt. Nach einer unendlichen Anzahl von Iterationen erhalten Sie OEIS A085765 .

Unterhaltsame Tatsache: Dieser Vorgang würde zu derselben Sequenz konvergieren, selbst wenn wir nicht von den natürlichen Zahlen ausgehen, solange die ursprüngliche Sequenz mit beginnt 1. Wenn die ursprüngliche Sequenz mit einer anderen beginnt x, erhalten wir x*A085765stattdessen.

Die Herausforderung

Geben Sie bei einer positiven Ganzzahl Ndas Ndritte Element der konvergierten Sequenz aus.

Sie können ein Programm oder eine Funktion schreiben, indem Sie eine Eingabe über STDIN (oder die nächstgelegene Alternative), ein Befehlszeilenargument oder ein Funktionsargument vornehmen und das Ergebnis über STDOUT (oder die nächstgelegene Alternative), einen Funktionsrückgabewert oder einen Funktionsparameter (out) ausgeben.

Sie können wählen, ob der Index auf N0 oder 1 basiert.

Testfälle

Die Sequenz beginnt mit:

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

Eingaben 5sollten also zu Ausgaben führen 9.

Hier ist eine naive CJam-Referenzimplementierung, die die ersten NZahlen generiert ( Nauf STDIN angegeben). Beachten Sie, dass Ihr Code nur das Nth-Element zurückgeben sollte, nicht das gesamte Präfix.


Also nur nachsehen : Wir geben den drittenN Ausdruck von A085765 aus , richtig?
GamrCorps

@GamrCorps Ja.
Martin Ender

Antworten:


7

CJam ( 23 22 Bytes)

Die Teilsummen werden an den geraden Indizes der fraktalen Sequenz angegeben, die A086450 ist . Die dort angegebene Wiederholung als Definition von A086450 ist die Basis für diese Implementierungen.

Verwenden eines expliziten "Stapels" (in Anführungszeichen, da es sich nicht um LIFO handelt):

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

Online-Demo

Präparation

{         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)
}

Bei 23 Bytes gibt es einen viel effizienteren Ansatz mit Merken:

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

Online-Demo


1
Ich bin mir sicher, dass es einige Sprachen gibt, in denen die Implementierung kürzer wäre f(0) = 1; f(n) = f(n/2) + (n % 2 ? 0 : f(n-2)); return f(2*x), aber ich kann mit diesem Ansatz in CJam keine Möglichkeit finden, Einsparungen zu erzielen.
Peter Taylor

9

Python 2, 55 49 42

Ich habe keine Ahnung, was los ist, aber es scheint schwer zu sein, die Maple-Formel von der OEIS-Seite zu übertreffen. Dies verwendet eine 0-basierte Indizierung.

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

Vielen Dank an @PeterTaylor für -6 Bytes.


Es ist einfach, um 6 Zeichen zu optimieren, wenn Sie sich nicht für die Leistung interessieren. Die Teile nach dem ersten orsind effektiv g(n,1) = f(n/2,n%2); g(n,0) = f(n-1) + g(n,1); so können Sie die gemeinsame herausziehen, um g(n,1)zu bekommenf=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

Als schädlich eingestufte Vorlagen , 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>>

Dies ist eine anonyme Funktion. Es ist ungefähr so, wie wenn mein Python die Maple-Formel auf der OEIS-Seite beantwortet , außer dass ich keinen Modul implementiert habe, also musste ich nn / 2 * 2 anstelle von n% 2 verwenden.

Erweitert:

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 Bytes

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

0

Matlab 108 103

Ich nutze die Tatsache, dass die gewünschte Serie die Teilsumme von https://oeis.org/A086450 ist

Aber der Rechenaufwand meiner Implementierung ist selbst für diese einfache Wiederholung alles andere als optimal.

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)))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.