【问题标题】:iterative implementation of the ruler function (1,2,1,3,1,2,1,4,1,2,1,3,...)标尺函数的迭代实现(1,2,1,3,1,2,1,4,1,2,1,3,...)
【发布时间】:2015-03-13 01:55:15
【问题描述】:

ruler function 的迭代实现是什么?

This website 断言“标尺函数可以非递归方式生成”,但从未显示示例。

Python 中的递归实现(来自同一网页)如下所示:

def ruler(k):
  for i in range(1, k+1):
    yield i
    for x in ruler(i-1): yield x

【问题讨论】:

  • 我在那里找不到这个程序。你能显示确切的位置吗?另外,ruler 的递归没有基本情况?!?
  • @thefourtheye 我认为基本情况隐含在对range 的调用中,因为当i-1 变为零时,您的范围为空。
  • @Two-BitAlchemist 哦,是的。感谢您指出这一点:-)

标签: python algorithm number-theory


【解决方案1】:

对于每个数字nruler(n) 等于 1 +(二进制 n 中尾随 0 的数量)。

我认为(这个未经测试)它可以有效地实现

def ruler(n):
    return (x ^ (x - 1)).bit_length()

因为在二进制中尾数看起来像

...mno1000    # x
...mno0111    # x - 1
...0001111    # x XOR (x - 1)

然后你想要.bit_length() 给你的 1 的数量。

【讨论】:

  • 伙计,太棒了 :-) 你是怎么得到这个的?
  • 这是一个很好的硬件方法(我知道x^(x-1)x&(x-1) 比特旋转黑客),但bit_length() 函数似乎在作弊。 (也许不是 Python,而是其他语言)
  • 在 C 中,这只是 ffs(n),它返回 n 中最低有效设置位的位位置。 (gcc 还为更长的单词长度提供了 ffsl 和 ffsll。)
【解决方案2】:

我可能在这里遗漏了一些东西,但基于标尺功能的描述......

def ruler(k):
    pow = 1
    while ((2*k) % (2**pow)) == 0:
        pow += 1
    return pow-1

for x in range(1, 10):
     print ruler(x)

1
2
1
3
1
2
1
4
1

不知道,也许我没有理解这个问题。

【讨论】:

  • 没错。当你可以循环时,永远不要递归。
  • 只测试一个输入;递归版本中的ruler(k) 是2k - 1 个值的生成器。
【解决方案3】:

查找表和位旋转可以让您有效地解决这个问题。

ruler = dict((1<<i, i+1) for i in xrange(63))

for i in xrange(1, 20):
    print ruler[i & ~(i-1)],

【讨论】:

  • O(N) 大小的查找表节省时间但不节省空间。
  • @JasonS 表的大小为 O(log N)。其中的 63 个元素适用于 N 到 18446744073709551616。
  • 哦,好吧,我错过了。
【解决方案4】:

使用 Hugh Bothwell 所说的,您可以执行以下操作(对于 n &gt; 0):

def ruler(n):
  return len(bin(n).split('1')[-1]) + 1

【讨论】:

    【解决方案5】:

    我正在尝试这个问题并使用一些旧方法。请检查一次。我还没有完全设置它。但显然它正在工作。那里很少有未完成的损坏代码。

    提前道歉。

    #!/usr/bin/env python
    import os
    def ruler():
        print("Initiating ruler function...")
        num = int(input("Enter the value to Eval::  "))
    
        expNumrange = 1234567890
    
        if num%2 == 0:
            for i in range(num):
                print(expNumrange,end='----')
    
        else:
            rem = num%2
            remLen = len(str(abs(rem)))
            expNumrangelen = len(str(abs(expNumrange)))
            finval = len(str(abs(expNumrange - remLen)))
            setVal = expNumrange - finval
            #rem2 = (str(expNumrange) - str(remLen))
            for i in range(num):
                print(expNumrange, end=(str(setVal) + '--'))
    
    
    
    if __name__ == '__main__':
        ruler()
    

    现在,请检查输出。

    对于“8”

    1234567890----1234567890----1234567890----1234567890----1234567890----1234567890----1234567890----1234567890----
    

    对于“5”

    12345678901234567880--12345678901234567880--12345678901234567880--12345678901234567880--12345678901234567880--
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 2013-11-02
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 2021-11-16
      • 1970-01-01
      相关资源
      最近更新 更多