Сходящиеся суммы фрактальной последовательности

16

Фон

Фрактальная последовательность представляет собой целое число последовательностей , где можно удалить первое вхождение любого целого и в конечном итоге с той же самой последовательностью , как и раньше.

Очень простая такая последовательность называется парамфразами Кимберлинга . Вы начинаете с положительных натуральных чисел:

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

Тогда вы врезаетесь в некоторые пробелы:

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

И затем вы неоднократно заполняете пробелы самой последовательностью (включая пробелы):

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

Это наша фрактальная последовательность! Теперь давайте возьмем частичные суммы:

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

Но что, если мы повторим этот процесс? «Фрактализуйте» новую последовательность (то есть, частичные суммы, полученные из шагов выше):

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

И снова возьмите частичные суммы:

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

Промыть, повторить. Оказывается, этот процесс сходится. Каждый раз, когда вы повторяете этот процесс, больший префикс последовательности остается неизменным. После бесконечного количества итераций вы получите OEIS A085765 .

Интересный факт: этот процесс сходится к той же последовательности, даже если мы не начинаем с натуральных чисел, если исходная последовательность начинается с 1. Если исходная последовательность начинается с любой другой x, мы получили бы x*A085765вместо этого.

Соревнование

Учитывая положительное целое число N, выведите Nэлемент сходящейся последовательности.

Вы можете написать программу или функцию, принимая ввод через STDIN (или ближайшую альтернативу), аргумент командной строки или аргумент функции и выводя результат через STDOUT (или ближайшую альтернативу), возвращаемое значение функции или параметр функции (out).

Вы можете выбрать, будет ли индекс Nна основе 0 или 1.

Тестовые случаи

Последовательность начинается с:

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

Таким образом, ввод 5должен привести к выводу 9.

Вот наивная ссылочная реализация CJam, которая генерирует первыйN числа (данные Nв STDIN). Обратите внимание, что ваш код должен возвращать только Nэлемент th, а не весь префикс.

Мартин Эндер
источник
Итак, просто проверяем: мы выводимN й термин A085765 , верно?
GamrCorps
@GamrCorps Да.
Мартин Эндер

Ответы:

7

CJam ( 23 22 байта)

Частичные суммы даны при четных индексах фрактальной последовательности, которая является A086450 . Повторение, данное там как определение A086450, является основой для этих реализаций.

Использование явного «стека» (в кавычках, потому что это не LIFO):

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

Онлайн демо

рассечение

{         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 байта есть гораздо более эффективный подход с запоминанием:

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

Онлайн демо

Питер Тейлор
источник
1
Я уверен, что есть некоторые языки, на которых это будет короче f(0) = 1; f(n) = f(n/2) + (n % 2 ? 0 : f(n-2)); return f(2*x), но я не могу найти способ сэкономить с этим подходом в CJam.
Питер Тейлор
9

Python 2, 55 49 42

Я понятия не имею, что происходит, но, кажется, трудно превзойти формулу Maple со страницы OEIS. При этом используется индексирование на основе 0.

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

Спасибо @PeterTaylor за -6 байтов.

feersum
источник
Это легко оптимизировать на 6 символов, если вы не заботитесь о производительности. Части после первого orэффективно g(n,1) = f(n/2,n%2); g(n,0) = f(n-1) + g(n,1); так что вы можете вытащить общее, g(n,1)чтобы получитьf=lambda n,t=0:n<1or f(n/2,n%2)+0**t*f(n-1)
Питер Тейлор
3

Хаскелл, 65

s l=[0..]>>=(\i->[l!!i,s l!!i])
r=1:(tail$scanl1(+)$s r)
f n=r!!n
Damien
источник
2

Шаблоны считаются вредными , 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>>

Это анонимная функция. Это более или менее так же, как мой ответ Python на формулу Maple на странице OEIS, за исключением того, что я не реализовал модуль, поэтому мне пришлось использовать nn / 2 * 2 вместо n% 2.

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
>> 
feersum
источник
2

Mathematica, 47 44 байта

If[#<1,1,#0[Floor@#/2]+(1-2#~Mod~1)#0[#-1]]&
alephalpha
источник
0

Matlab 108 103

Я использую тот факт, что желаемая серия является частичной суммой https://oeis.org/A086450

Но сложность вычислений моей реализации далека от оптимальной, даже для этого простого повторения.

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)))
flawr
источник