如何在数组中找到最接近的素数,到该数组中的另一个数?

时间:2014-10-04 06:27:30

标签: python algorithm list python-2.7

我想找出最接近的素数(存在于该数组中),以及数组中的任何其他数字?
示例:

list a -> [1,2,4,6,8,12,9,5,0,15,7]

因此4的最近素数为215的素数为7。在这里,我假设列表中的每个元素都是不同的 我花了几个小时但却无法解决,有没有efficient方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

首先,你需要一个好的素数检查器。 Wikipedia has an implementation - 根据python版本等,它可能会进一步优化。

现在,列出所有素数的索引:

indices = [i for i, val in enumerate(data) if is_prime(val)]

接下来,选择一个任意数字并找到它的索引(或不是任意...)。

n = random.choice(data)
idx = data.index(n)

我们几乎就在那里......将你的方法分成两部分,找出n的索引在索引列表中的位置。

indices_idx = bisect.bisect_left(indices, idx)

现在,要确定更接近的数字是左侧还是右侧,我们需要查看值。

# Some additional error handling needs to happen here to make sure that the index
# actually exists, but this'll work for stuff in the center of the list...
prime_idx_left = indices[indices_idx - 1]
prime_idx_right = indices[indices_idx]

最后,找出哪个索引更接近并拉出值:

if (idx - prime_idx_left) <= (prime_idx_right - idx):
    closest_prime = data[prime_idx_left]
else:
    closest_prime = data[prime_idx_right]

注意我在假设您将反复使用相同列表的情况下对此进行了烹饪。如果你不是,你会做得更好:

  • 找到您感兴趣的数字的索引。
  • 找到右边第一个素数的索引(如果存在)
  • 找到左边第一个素数的索引(如果存在)
  • 检查哪一个更近

e.g。

def find_idx_of_prime(lst, start_idx, stop_idx, dir):
    for ix in xrange(start_idx, stop_idx, dir):
        if is_prime(lst[ix]):
            return ix
    return dir*float('inf')

idx = data.index(number)
left_idx = find_idx_of_prime(data, idx, 0, -1)
right_idx = find_idx_of_prime(data, idx, len(data), 1)
prime_idx = left_idx if idx - left_idx < right_idx - idx else right_idx
prime_value = data[prime_idx]  # raises TypeError if no primes are in the list.

答案 1 :(得分:1)

以下是Eratosthenes Sieve的一个相当有效的实现,可以与mgilson的代码一起使用。但正如J.F. Sebastian所说,如果列表中的数字非常大,使用预先计算的素数表可能效率不高,&amp; /或者如果列表的长度很小。

def primes(n):
    ''' Return a boolean list of all primes < n '''
    s = [False]*2 + [True]*(n-2)
    for i in xrange(2, int(n**0.5) + 1):
        if s[i]:
            s[i*i : n : i] = [False] * (1 + (n - 1)//i - i)
    return s

你会这样使用它:

a = [1,2,4,6,8,12,9,5,0,15,7]
is_prime = primes(max(a) + 1)

然后将mgilson的find_idx_of_prime()函数更改为:

def find_idx_of_prime(lst, start_idx, stop_idx, dir):
    for ix in xrange(start_idx, stop_idx, dir):
        if is_prime[lst[ix]]:
            return ix
    return dir*float('inf')