【问题标题】:Check if a number can be divided into prime partitions检查一个数字是否可以划分为素数分区
【发布时间】:2019-06-28 06:17:13
【问题描述】:

有人可以在 Python 上解决这个问题吗?

一个正整数 m 可以被划分为素数,如果它可以写成 p + q 其中 p > 0, q > 0 并且 p 和 q 都是素数。

编写一个 Python 函数,将整数 m 作为输入,如果 m 可以划分为素数,则返回 True,否则返回 False。

试过了,但不适用于所有测试用例,例如它应该为 3432 返回 True,它返回 False。

def partition(num):
    primelist=[]
    for i in range(2,num + 1):
        for p in range(2,i):
            if (i % p) == 0:
                break
        else:
            primelist.append(i)


    for x in primelist:
        y= num-x
        for z in range(2,y):
            if y%z == 0:
                return False

        return True

【问题讨论】:

  • 有些网站可以聘请程序员为您工作。这不是其中之一。
  • 请在提问前努力解决问题。请让您的回答具体。您需要编码方面的帮助吗?如果有,是哪一部分?您需要算法方面的帮助吗?如果真是这样,那么是以哪种方式?您是否正在寻找比蛮力更好的时间复杂度?尝试将您的问题与您真正坚持的核心方面分开。

标签: python python-3.x partition-problem


【解决方案1】:

错误在于第二个 for 循环。您正在遍历可能的素数 x,然后希望检查 y = num - x 是否也是素数。

您的逻辑错误在于,在第二个 for 循环中,如果循环中的第一个元素 y = num - x 不是素数,它将返回 False,而不检查任何其他可能的值。

您可以通过将return False 语句移出一个循环来纠正此问题,但是由于您已经生成了一个小于numprimelist 的素数列表(并且由于y = num - x,(如果素数y存在)它将在此列表中),您只需检查列表的成员身份:

    for x in primelist:
        y= num-x
        # Note: num = x + y, thus need only check y prime
        if y in primelist:
            return True
        # If no such y is prime, not possible
        else:
            return False

注意:我建议让您的脚本逻辑更加模块化,将素数列表生成器分离到它自己的函数中:

def partition(num):
    """
    Return True if there exist primes x,y such that num = x + y.
    Else return False.
    """
    primelist = primes(num)
    for x in primelist:
        y= num-x
        # Note: num = x + y, thus need only check y prime
        if y in primelist:
            return True
    # If no such y is prime, not possible
    else:
        return False

def primes(num):
    """Return list of all primes less than num."""
    primelist=[]
    for i in range(2,num + 1):
        for p in range(2,i):
            if (i % p) == 0:
                break
        else:
            primelist.append(i)
    return primelist

【讨论】:

  • 哦,我再次检查 y 是否为质数,方法是再次进行与我之前在第一个循环中所做的相同的检查,从来没有来找过我,我可以根据列表检查数字素数,谢谢,它有很大帮助。
  • 上面的代码有一个bug......例如检查m = 4时的情况。素数是[2 3]。上面的代码显示 True for m = 4
  • @sivasrinivaskolukula 我建议您再次阅读该问题。 “如果一个正整数 m 可以写成 p + q 其中 p > 0, q > 0 并且 p 和 q 都是素数,那么它可以被划分为素数。” p=2, q=24 的有效解决方案,因此它应该返回 True
  • 你最终的 modular 代码示例对我不起作用。 partition(4) 返回 Falsepartition(11) 返回 True -- 两者都是错误的。事实上,primes(4) 返回[3, 4]。我不明白什么?
  • @cdlane 是的,有错误,马上改正。
【解决方案2】:

我得到的最终解决方案:

def primepartition(m):
    primelist=[]
    if m<0:
        return False
    else:
        for i in range(2,m + 1):
            for p in range(2,i):
                if (i % p) == 0:
                    break
            else:
                primelist.append(i)

        for x in primelist:
            y= m-x
            if y in primelist:
                return True
        return False

【讨论】:

  • 上面的代码有一个bug......例如检查m = 4时的情况。素数是[2 3]。上面的代码显示 True for m = 4。
  • @SivaSrinivasKolukula,正如您对@ukemi 解决方案的类似评论所解释的那样,4 的结果应该是True,因为它划分了[2, 2]
【解决方案3】:

下面给出的代码有望为您提供正确的输出。

def factors(n):
    factorslist = []
    for i in range(1, n+1, 1):
        if n % i == 0:
            factorslist.append(i)
    return(factorslist)    

def prime(n):
    if factors(n) == [1, n] and n > 1:
        return(True)

def primelist(n):
    primenolist = []
    for i in range(1, n+1, 1):
        if prime(i) == True:
            primenolist.append(i)
    return(primenolist)

def primepartition(m):
    if m > 0:
        primenolist = primelist(m)
        checklist = []
        for p in primenolist:
            q = m - p
            if q in primenolist and p > 0 and q > 0:
                checklist.append((p,q))
        if len(checklist) > 0:
            return(True)
        else:
            return(False)
    else:
        return(False)

【讨论】:

    【解决方案4】:

    另一种方法, 最初,我们将所有素数元素存储到 m 并检查总和等于 m

    的素数对
    def primepartition(a):
    l=[2]#since 'a' should be >=2 for below loops, we took here 2(1st prime).
    for i in range(2,a):
            flag=0
            for j in range(2,i):
                if i%j==0:
                    flag=0
                    break
                else:
                    flag=1
            if flag==1:
                l.append(i)
    for i in l:
        for j in l:
            if i+j==a:
                return True
    return False
    

    【讨论】:

      【解决方案5】:
      n=int(input("Enter any number: "))
      list=[]
      for num in range(0,n + 1):  
       if num > 1:  
           for i in range(2,num):  
             if (num % i) == 0:  
                 break  
             else:
                 list.append(num)
      if (n<= 1):
          print("False")
          #print("It is not positive ")
      else:
          for i in list:
              y = num -i
              if (y in list):
                  print("True")
                  #print(y,"+",i,"=",n)
                  #print(i,"+",y,"=",n)
                  #print("The number can be expressed as the sum of two prime numbers.")
                  break
          else:
              print("False")
              #print("The number can not be expressed as the sum of two prime numbers.")
      

      【讨论】:

      • 这是我与我分享的最好的代码:)
      【解决方案6】:

      您的代码略有不同:

      def primepartition0(m):
          primelist=[]
          if m<0:
              return False
          else:
              for i in range(2,m + 1):
                  for p in range(2,i):
                      if (i % p) == 0:
                          break
                  else:
                      primelist.append(i)
      
              for x in primelist:
                  for y in primelist:
                      if x != y and x+y == m:
                          return True
              return False   
      

      【讨论】:

      • 这段代码为primepartition0(4)primepartition0(6)返回False,两者都有有效的解决方案。
      【解决方案7】:

      一种尝试减少所需代码量的替代方法:

      def primepartition(m):
          if m > 3:
              for number in range(m // 2, m - 1):
                  difference = m - number
      
                  for psuedoprime in range(2, int(number ** 0.5) + 1):
                      if number % psuedoprime == 0 or difference > psuedoprime and difference % psuedoprime == 0:
                          break
                  else:  # no break
                      return number, difference  # as good a non-False result as any other...
      
          return False
      

      【讨论】:

        【解决方案8】:
        def factors(n):
            factlist = []
            for i in range(1,n+1):
                # Since factors of 2 cannot be primes, we ignore them.
                if n%i==0 and i%2!=0:
                    factlist.append(i)
            return factlist
        
        def isprime(n):
            return(factors(n)==[1,n])
        
        def preimesupto(n):
            primelist = []
            if n>=2:
                primelist.append(2)
            for i in range(n):
                if isprime(i):
                    primelist.append(i)
            return primelist
        
        def primepartition(n):
            if n<0:
                return False
            primelist = preimesupto(n)
            for i in primelist:
                j = n-i
                if j in primelist:
                    return True
            else:
                return False
        

        【讨论】:

        【解决方案9】:

        如果您不需要生成实际的素数,而只测试是否存在一对素数 p 和 q 使得 p+q == N,您可以根据哥德巴赫猜想将其变得非常简单。所有偶数都可以表示为两个素数之和。因此,如果数字是偶数,则返回 True 并检查 N-2 是否是奇数的素数(因为 2 是唯一的偶素数,这是从奇数开始时会产生另一个奇数的唯一素数)。这将归结为仅对奇数进行 N-2 的一次素数测试。

        def primePart(N):
            return N%2==0 or all((N-2)%p for p in range(3,int(N**0.5)+1,2))
        
        primePart(3432)  # True
        
        primePart(37+2)  # True
        
        primePart(13+41) # True
        
        primePart(123)   # False
            
        

        如果您想实际找到一对加起来为 N 的素数,您可以生成最多为 N 的素数并返回第一个素数 >= N/2 其中 N - 素数是已经找到的素数之一:

        def findPQ(N):
            if not primePart(N): return
            if N%2: return 2,N-2
            isPrime = [0]+[1]*N
            for p in range(3,N,2):
                if not isPrime[p]: continue
                if 2*p>=N and isPrime[N-p]: return p,N-p
                isPrime[p*p::p] = [0]*len(isPrime[p*p::p])
        

        输出:

        findPQ(3432)      # (1723, 1709)
        
        findPQ(12345678)  # (6172879, 6172799)
        

        要超过 10^9,您将需要一个内存效率更高的算法,而不是同样快的 Eratosthenes 筛子。这可以通过要跳过的素数倍数的字典来实现:

        def findPQ(N):
            if not primePart(N): return
            if N%2: return 2,N-2
            skip,primes = {},{2}
            for p in range(3,N,2):
                if p in skip:
                    prime = skip.pop(p)
                    mult  = p + 2*prime
                    while mult in skip: mult += 2*prime
                    if mult <= N: skip[mult] = prime
                else:
                    if 2*p>=N and N-p in primes: return p,N-p
                    if p*p<=N: skip[p*p]=p
                    if 2*p<=N: primes.add(p)
        

        输出(需要一段时间但不会破坏内存空间):

        findPQ(1234567890)  # (617283983, 617283907)    
        

        【讨论】:

          【解决方案10】:
          def checkprime(number):
          fact=1
          for r in range(2,number):
          if number%r==0:
            fact=fact+1
          return(fact<2)
          
          def primepartition(m):
          
          for i in range(2,m):
          
          flag=0
          if checkprime(i) and checkprime(m-i)==True:
            flag=1
            break
          return(flag==1)
          
          def matched(s):
          list_of_string=list(s)
          for y in range(len(list_of_string)):
          if list_of_string[y]=='(':
          for z in range(y,len(list_of_string)):
              if list_of_string[z]==')':
                list_of_string[y]='@'
                list_of_string[z]='@'
                break
           return('('not in list_of_string and ')'not in list_of_string)
          
           def rotatelist(l,k):
           if k>len(l):
           k=int(k%len(l))
           return(l[k:]+l[0:k])
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-09-15
            • 2015-03-08
            • 2021-04-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多