2014-10-04 25 views
0

我想找出最接近的素數(即存在於該數組中),到數組中的任何其他數字?
例子:如何在數組中找到最接近的素數到該數組中的另一個數?

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

所以最近的素數到42並在15情況下,這將是7。這裏我假設列表中的每個元素都是不同的。
我花了幾個小時就可以解決,但解決不了,有沒有efficient的方法來解決這個問題?

+0

是什麼在列表中的最大可能是多少? – 2014-10-04 06:29:44

+0

定義高效。 。 。而這種方法可能取決於我們談論的數字以及它們可能有多大。 。 。 – mgilson 2014-10-04 06:30:31

+0

定義爲最接近的 - 可以使素數值大於或小於給定的數值(或甚至等於?)。在你的例子中,最接近12的素數是7還是15? – 2014-10-04 06:51:51

回答

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] 

注意我,你會被反覆使用同一列表的假設下熟這件事。如果你沒有,你會做的更好,只是:

  • 找到你感興趣的個數指標
  • 找到的第一個主要的指數權(如果存在的話)。
  • 找到的第一個主要的指標向左(如果存在的話)
  • 檢查哪一個更接近

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。你可以找到'max(lst)',並使用Eratosthenes的Sieve生成一組小於'max(lst)+ 1'的所有素數,然後'isprime = primes .__ contains__'。 [代碼非常簡單,例如'sieve_of_eratosthenes(limit)'](http://stackoverflow.com/a/20782064/4279)如果'max(lst)'與len(lst)相比可能很大,那麼a可以使用直接素數測試,例如[你已經鏈接](http://en.wikipedia.org/wiki/Primality_test#Python_implementation)。如果'max(lst)'非常大,那麼應該使用諸如Miller-Rabin素性測試的概率方法。 – jfs 2014-10-04 11:38:45

1

下面是Eratosthenes篩的一個相當有效的實現,它可以與mgilson的代碼結合使用。但正如J.F.塞巴斯蒂安所說,如果列表中的數字非常大,使用預先計算的素數表格可能效率不高,& /或列表長度很小。

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') 
+0

哎呀!我最好將'/'改成'//',以便在Python 3上正常工作。:) – 2014-10-06 12:45:04

相關問題