Find the smallest regular number that is not less than N

后端 未结 8 2101
清歌不尽
清歌不尽 2020-12-16 19:08

Regular numbers are numbers that evenly divide powers of 60. As an example, 602 = 3600 = 48 × 75, so both 48 and 75 are divisors of a power of 60.

8条回答
  •  感动是毒
    2020-12-16 19:22

    Here's another possibility I just thought of:

    If N is X bits long, then the smallest regular number RN will be in the range
    [2X-1, 2X]

    e.g. if N = 257 (binary 100000001) then we know R is 1xxxxxxxx unless R is exactly equal to the next power of 2 (512)

    To generate all the regular numbers in this range, we can generate the odd regular numbers (i.e. multiples of powers of 3 and 5) first, then take each value and multiply by 2 (by bit-shifting) as many times as necessary to bring it into this range.

    In Python:

    from itertools import ifilter, takewhile
    from Queue import PriorityQueue
    
    def nextPowerOf2(n):
        p = max(1, n)
        while p != (p & -p):
            p += p & -p
        return p
    
    # Generate multiples of powers of 3, 5
    def oddRegulars():
        q = PriorityQueue()
        q.put(1)
        prev = None
        while not q.empty():
            n = q.get()
            if n != prev:
                prev = n
                yield n
                if n % 3 == 0:
                    q.put(n // 3 * 5)
                q.put(n * 3)
    
    # Generate regular numbers with the same number of bits as n
    def regularsCloseTo(n):
        p = nextPowerOf2(n)
        numBits = len(bin(n))
        for i in takewhile(lambda x: x <= p, oddRegulars()):
            yield i << max(0, numBits - len(bin(i)))
    
    def nextRegular(n):
        bigEnough = ifilter(lambda x: x >= n, regularsCloseTo(n))
        return min(bigEnough)
    

提交回复
热议问题