递归交错排列

发布于 2024-12-16 19:46:39 字数 1376 浏览 3 评论 0原文

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

例如,如果 H = 10N = 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 语言,但现阶段我对算法级别更感兴趣;我很高兴阅读其他语言的代码(在合理范围内)。

我还没有解决它的实施问题。我希望我会首先预先计算排列(与上面方法的算法相反)。但我也感兴趣是否有一种简单的方法可以绘制下一帧而无需预先计算它,其复杂性与之前的方法类似。

I have a program (a fractal) that draws lines in an interlaced order. Originally, given H lines to draw, it determines the number of frames N, and draws every Nth frame, then every N+1'th frame, etc.

For example, if H = 10 and N = 3, it draws them in order:

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

However I didn't like the way bands would gradually thicken, leaving large areas between undrawn for a long time. So the method was enhanced to recursively draw midpoint lines in each group instead of the immediately sebsequent lines, for example:

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

(The numbers in parentheses are out of range and not drawn.) The algorithm's pretty simple:

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.

When the odd numbered frames are drawn on the last step size, they are drawn in simple order just as an the initial (annoying) method. The same with every fourth frame, etc. It's not as bad because some intermediate frames have already been drawn.

But the same permutation could recursively be applied to the elements for each step size. In the example above, the last line would change to:

1,      # the 0th element, S' = 16
9,      # 4th, S' = 8
5,      # 2nd, S' = 4
3, 7.   # 1st and 3rd, S' = 2

The previous lines have too few elements for the recursion to take effect. But if N was large enough, some lines might require multiple levels of recursion. Any step size with 3 or more corresponding elements can be recursively permutated.

Question 1. Is there a common name for this permutation on N elements, that I could use to find additional material on it? I am also interested in any similar examples that may exist. I would be surprised if I'm the first person to want to do this.

Question 2. Are there some techniques I could use to compute it? I'm working in C but I'm more interested at the algorithm level at this stage; I'm happy to read code other language (within reason).

I have not yet tackled its implemention. I expect I will precompute the permutation first (contrary to the algorithm for the previous method, above). But I'm also interested if there is a simple way to get the next frame to draw without having to precomputing it, similar in complexity to the previous method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不离久伴 2024-12-23 19:46:39

听起来好像您正在尝试构建一维低差异序列。您的排列可以通过反转索引的二进制表示来计算。

def rev(num_bits, i):
    j = 0
    for k in xrange(num_bits):
        j = (j << 1) | (i & 1)
        i >>= 1
    return j

用法示例:

>>> [rev(4,i) for i in xrange(16)]
[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]

适用于一般 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]

It sounds as though you're trying to construct one-dimensional low-discrepancy sequences. Your permutation can be computed by reversing the binary representation of the index.

def rev(num_bits, i):
    j = 0
    for k in xrange(num_bits):
        j = (j << 1) | (i & 1)
        i >>= 1
    return j

Example usage:

>>> [rev(4,i) for i in xrange(16)]
[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]

A variant that works on general 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]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文