分形序列的收敛和


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收敛序列的th个元素。

您可以编写程序或函数,通过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上给定)。请注意,您的代码应仅返回Nth元素,而不是整个前缀。


因此,只需检查一下:我们正在输出A085765Nth项,对吗?
GamrCorps,2015年

@GamrCorps是的。
马丁·恩德

Answers:


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
我敢肯定,有些语言将用as来实现会更短一些f(0) = 1; f(n) = f(n/2) + (n % 2 ? 0 : f(n-2)); return f(2*x),但是我找不到在CJam中用这种方法节省开支的方法。
彼得·泰勒

9

蟒蛇2,55 49 42

我不知道发生了什么,但是在OEIS页面上击败Maple公式似乎很困难。这使用基于0的索引。

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

感谢@PeterTaylor提供了-6个字节。


如果您不关心性能,则很容易按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)
Peter Taylor

3

哈斯克尔,65岁

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

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答案大致相同与OEIS页面上的 Maple公式,只是我没有实现模数,所以我不得不使用nn / 2 * 2而不是n%2。

展开:

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字节

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

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)))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.