Reccurence算法:在n移动后找到位置

时间:2016-12-22 22:10:53

标签: python algorithm

简介

我正在尝试编码Finding the position at n?中引用的问题。为此,我只使用了问题中公布的公式。我没有通过公式和答案他们对我来说有点太复杂了。我在python中编写了代码,它在这里表示。

算法描述(复制)

这种舞蹈要求每个表演者遵循一系列精确的步骤:

•第0阶段:首先,通过在0号位置设置起点来远离障碍物

•第1阶段:向前迈出一步(+1步)

•第2阶段:向后退两步(-2步)

•要遵循,通过特定的计算,每次都可以获得下一步所需的步骤和方向:您在前一阶段所采取的步数减去您的步数倒数第二阶段。

也就是说,在第3阶段,舞者必须向后退步3步(-2 - 1)。

在第3阶段,舞者处于-4位置。

  

阶段(n)=阶段(n-1) - 阶段(n-2)

     

pos(n)= pos(n-1)+ stage(n)

     

在第4阶段,舞者处于-5位置。

enter image description here

源代码

#!/usr/bin/python
if __name__=="__main__":
    s = [0, 1, -2]
    p = [0, 1, -1]
    for n in range(3, 5):
        diff = s[n - 1] - s[n - 2]
        s.append(diff)
        p.append(p[n - 1] + diff)
        print "Position at stage %s is %s" %(n, p[len(p) - 1])

问题

我的问题是假设我们有超过1000万个阶段。列表p和s将增长并可能导致内存问题。有没有办法解决这个问题。我找不到另一个解决方案,而不是使用列表。

如果删除第一个元素s.pop() p.pop(),则它是一个超出范围异常的索引。这是正常的。除此之外,我无法确定在哪里继续。

更新

我想的更简单。

#!/usr/bin/python
if __name__=="__main__":
    last_move = -2
    penultimate_move = 1
    previous_position = -1
    for n in range(3, 5):
        #compute current move and position
        current_move = last_move - penultimate_move
        current_position = previous_position + current_move

        #do switch in here
        penultimate_move = last_move
        last_move = current_move
        previous_position = current_position

        print "current position %s" %current_position

5 个答案:

答案 0 :(得分:7)

对此有一个简单的解决方案:在阶段6,7和8,位置分别为0,1和-1,这些位置与初始位置相同。由于下一阶段和位置仅取决于前一对阶段和先前的位置,因此保证重复相同的序列。

所以计算给定 n 的位置的函数可以是:

def position(n):
    return [0, 1, -1, -4, -5, -3][n % 6]

用数字 n 计算阶段的函数:

def stage(n):
    return [3, 1, -2, -3, -1, 2][n % 6]

答案 1 :(得分:4)

对于这类问题,你必须尝试为某些情况找到解决方案,也许你会找到一个像我找到的模式,它将帮助你在O(1)时间内解决这个问题,只有6个元素的列表。< / p>

让我们迭代几个初始阶段,

           Steps to take      New position
Stage 0        ---                0
Stage 1         1                 1
Stage 2        -2                -1
Stage 3        -3                -4
Stage 4        -1                -5
Stage 5         2                -3
Stage 6         3                 0
Stage 7         1                 1
Stage 8        -2                -1
Stage 9        -3                -4
Stage 10       -1                -5

所以你可以看到Stage 6模式重复之后。所以下面的python代码将帮助您更快地解决这个问题。

def getpos(n):
    '''Returns the position of the performer after nth stage.'''
    ls = [0, 1, -1, -4, -5, -3]
    return ls[n % 6]

def getstep(n):
    '''Returns the step taken at nth stage'''
    ls = [3, 1, -2, -3, -1, 2]
    if n == 0:
        return None
    return ls[n % 6]

函数getpos()getstep()是此问题中您需要的实用函数。

答案 2 :(得分:3)

好;让我们从重复定义开始:

stage(n) = stage(n-1) - stage(n-2)
pos(n) = pos(n-1) + stage(n)

现在,让我们制作三个变量:

pos is for pos(n)     -- position
ult is for stage(n-1) -- ultimate
pen is for stage(n-2) -- penultimate

如上所述,更新很简单。 这个初始值在问题和代码中给出:

pos = -1
ult = -2
pen = 1

现在,每次循环,更新上面给出的值。

stage_n = ult - pen
pos += stage_n

最后一步是准备下一次迭代。当我们再迈出一步时,这将成为下一次迭代的终极;目前的终极被降级为倒数第二名:

pen = ult
ult = stage_n

......现在我们已准备好回到循环的顶端。

总的来说,它看起来像这样:

limit = <wherever you want to stop>

pos = -1
ult = -2
pen = 1

for n in range (3, limit):
    stage_n = ult - pen
    pos += stage_n

    pen = ult
    ult = stage_n

print "Step", limit, "is at position", pos

答案 3 :(得分:2)

你有1000万+阶段的原因是迫使你学习这个技巧。

有助于以差分方程的形式来看待它,

s(n+1) = s(n) - s(n-1)
p(n+1) = p(n) + s(n+1)

将每个步骤视为2个数组s_np_n

的状态
s_n = [ s(n), s(n-1) ]
p_n = [ p(n) ] 

我们如何找到s_n+1p_n+1?看看公式,

s_n+1 = [ s_n[0] - s_n[1], s_n[0] ]
p_n+1 = [ s_n+1[0] + p_n[0] ]

希望这是有道理的。您只需要指定状态来解决方程,而不是整个历史。我可能会弄错,但我认为它被称为&#34;无记忆&#34;在LTE系统中。基本上你是在计算差分方程(离散动态系统),这在DSP中很常见。我在实时DSP实验室学到了这种技术。 :)

答案 4 :(得分:0)

public int calculate( int iterationNumber )
   {
      int position = 0;
      int step1 = 1;
      position = position + step1;
      iterationNumber = iterationNumber - 1;
      int step2 = -2;
      position = position + step2;
      iterationNumber -= 1;
      while( iterationNumber > 0 )
      {
         position = position + ( step2 - step1 );
         int buffer = step1;
         step1 = step2;
         step2 = step2 - buffer;
         iterationNumber -= 1;
      }
      return position;
   }

   @Test
   public void positionOfTheDancerTest()
   {
      assertEquals( -4, positionOfTheDancer.calculate( 3 ) );
      assertEquals( -5, positionOfTheDancer.calculate( 100000 ) );
      assertEquals( 1, positionOfTheDancer.calculate( 2147483647 ) );
   }