Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 递归交错排列_Algorithm_Language Agnostic_Recursion_Permutation_Interlacing - Fatal编程技术网

Algorithm 递归交错排列

Algorithm 递归交错排列,algorithm,language-agnostic,recursion,permutation,interlacing,Algorithm,Language Agnostic,Recursion,Permutation,Interlacing,我有一个程序(分形),它以交错的顺序画线。最初,给定要绘制的H行,它确定帧数N,并绘制每个N第帧,然后绘制每个N+1第帧,以此类推 例如,如果H=10和N=3,则按顺序绘制: 0, 3, 6, 9, 1, 4, 7, 2, 5, 8. 然而,我不喜欢条纹逐渐变厚的方式,在很长一段时间内,在未绘制的区域之间留下很大的区域。因此,改进了该方法,以递归方式在每组中绘制中点线,而不是直接绘制顺序线,例如: 0, (32) # S (step size) = 32 8, (24)

我有一个程序(分形),它以交错的顺序画线。最初,给定要绘制的
H
行,它确定帧数
N
,并绘制每个
N
第帧,然后绘制每个
N+1
第帧,以此类推

例如,如果
H=10
N=3
,则按顺序绘制:

0, 3, 6, 9,
1, 4, 7,
2, 5, 8.
然而,我不喜欢条纹逐渐变厚的方式,在很长一段时间内,在未绘制的区域之间留下很大的区域。因此,改进了该方法,以递归方式在每组中绘制中点线,而不是直接绘制顺序线,例如:

0, (32)          # S (step size) = 32
8, (24)          # S = 16
4, (12)          # S = 8
2, 6, (10)       # S = 4
1, 3, 5, 7, 9.   # S = 2
(括号中的数字超出范围,无法绘制。)算法非常简单:

Set S to a power of 2 greater than N*2, set F = 0.
While S > 1:
    Draw frame F.
    Set F = F + S.
    If F >= H, then set S = S / 2; set F = S / 2.
当奇数帧在最后一个步长上绘制时,它们以简单的顺序绘制,就像初始(恼人的)方法一样。每四帧都是一样的,因为已经画出了一些中间帧,所以没有那么糟糕

但同样的排列可以递归地应用于每个步长的元素。在上面的示例中,最后一行将更改为:

1,      # the 0th element, S' = 16
9,      # 4th, S' = 8
5,      # 2nd, S' = 4
3, 7.   # 1st and 3rd, S' = 2
前几行元素太少,递归无法生效。但是如果
N
足够大,一些行可能需要多级递归。具有3个或更多对应元素的任何步长都可以递归置换

问题1。对于
N
元素上的这种排列是否有一个通用名称,我可以用它来查找其他材料?我还对可能存在的任何类似例子感兴趣。如果我是第一个想这么做的人,我会很惊讶

问题2。我可以使用一些技术来计算它吗?我在C语言工作,但在这个阶段我对算法更感兴趣;我很乐意阅读其他语言的代码(在合理的范围内)


我还没有解决它的实施问题。我希望我将首先预计算置换(与上面前面方法的算法相反)。但我也很感兴趣的是,是否有一种简单的方法可以在不进行预计算的情况下绘制下一帧,其复杂性与前一种方法类似。

听起来好像你在尝试构建一维图像。可以通过反转索引的二进制表示来计算置换

def rev(num_bits, i):
    j = 0
    for k in xrange(num_bits):
        j = (j << 1) | (i & 1)
        i >>= 1
    return j
适用于通用n的变体:

def rev(n, i):
    j = 0
    while n >= 2:
        m = i & 1
        if m:
            j += (n + 1) >> 1
        n = (n + 1 - m) >> 1
        i >>= 1
    return j

>>> [rev(10,i) for i in xrange(10)]
[0, 5, 3, 8, 2, 7, 4, 9, 1, 6]

我觉得我对你的问题还不够了解,无法回答,但这让人想起伽罗瓦域()和拉丁方()。也许这两者之间的某些东西会引导你准确地回答你的问题。嗯,我担心我已经打开了高等数学的潘多拉盒子!我看看我是否能看懂那些文章……嗯,我想你有什么发现。它是一种“准随机序列”。它不是随机的,但它有几层均匀分布,所以我想它会通过一些相同的测试。是的,我得到了相同的排列,N=16!但对于N=10,则不适用。从您的代码中,我以
[0,8,4,12,2,10,6,14,1,9]
结束,而不是期望的
[0,8,4,2,6,1,9,5,3,7]
。两者中出现的数字顺序正确。看起来我只需要计算较大的排列,而忽略超出范围的元素。@Edmund我发布了一个通用
N
的版本。它没有给出您指定的确切顺序,但它的操作原理相同。谢谢。(我的用例不需要获得完全相同的序列。)
def rev(n, i):
    j = 0
    while n >= 2:
        m = i & 1
        if m:
            j += (n + 1) >> 1
        n = (n + 1 - m) >> 1
        i >>= 1
    return j

>>> [rev(10,i) for i in xrange(10)]
[0, 5, 3, 8, 2, 7, 4, 9, 1, 6]