【问题标题】:Finding the largest palindrome of the product of two 3-digit numbers in Python在 Python 中找到两个 3 位数乘积的最大回文
【发布时间】:2017-05-28 07:12:18
【问题描述】:

所以我要解决的挑战是找到由两个 3 位数字的乘积构成的最大回文数。我是 Python 新手,所以我的代码还不是优雅的或折射的,但是我似乎找不到一个逻辑错误。

def ispalindrome(n):
    rev_n = str(n)[::-1]
    if n == rev_n:
        return True
    else:
        return False


first_num = 100
second_num = 100
mylist=[]
while first_num < 1000:
    while second_num < 1000:
        item = first_num * second_num
        mylist.append(item)
        second_num += 1
    second_num = 100
    first_num +=1
# print (mylist)
num_as_string = []
for i in mylist:
    i = str(i)
    num_as_string.append(i)
print("Total products of two 3-digit numbers: {}").format(len(num_as_string))
print("-----------------------------------------------------")

def convert_to_num_list(string_list):
    new_num_list = []
    item = int(string_list)
    new_num_list.append(item)
    return new_num_list



palindrome_list = []

for j in num_as_string:
    if ispalindrome(j) == True:
        palindrome_list.append(j)
        palindrome_list.sort()
        # print(palindrome_list)
        x = convert_to_num_list(j)
        largest_palindrome = max(x)

print("Total palindroms of product of two 3-digit numers: {}").format(len(palindrome_list))

print("Largest palindrome = {}").format(largest_palindrome)

问题是我得到的最大回文数为 580085,即 995*583,但不是最大的回文数。我相信最大的回文数是 906609,即 993*913,但我的代码没有找到这个。谁能帮我解决我的逻辑缺陷?

【问题讨论】:

  • 如果要形成最大的数,为什么要从100开始,一直到1000呢?如果你从 999 开始到 100(每个计数器一次一个单位),你可以在得到第一个回文后立即停止搜索。
  • @jsbueno 谢谢。这听起来绝对是获得此结果的最有效方法。
  • @jsbueno 我当然没有想到这种方法。这显然是有效的,如果我使用 900 万个数字而不是 900 个数字,我会很高兴这个建议。但我怀疑它也可能很难做到正确。
  • 问题很快就会变得更难,甚至更早的问题可能会以截然不同的数字出现,我们必须重新考虑策略。与 Project Euler 一起玩吧! :-)

标签: python palindrome


【解决方案1】:

您的代码在数字和字符串之间进行了很多不必要的转换,这使得错误很难找到。代码中唯一需要字符串表示的地方是在确定数字是否为回文时。所以这应该是代码进行转换的唯一地方。

逻辑错误在您的函数convert_to_num_list() 中。它采用 one 数字的字符串表示形式并返回包含该数字的 1 列表。因此,"123321" 返回为 [123321]。然后,您获取该 1 列表的 max(),它始终是传递给 convert_to_num_list() 的值。所以代码永远不会保留最大值,因为如果稍后出现较小的值,它将被覆盖。代码将995*583 报告为最大的,因为它比993*913 来得晚,这又是因为995 > 993

您可以使用if 语句修复该错误,但该程序过于复杂并且很可能包含其他错误。我建议将代码简化为产生最大回文的基本任务,而不打印出中间结果,因为代码越简单,就越容易看到逻辑错误。

def ispalindrome(n):
    return str(n) == str(n)[::-1]

mylist=[]
for first_num in range(100,1000):
    for second_num in range(100,1000):
        item = first_num*second_num
        if ispalindrome(item):
            mylist.append(item)
print(max(mylist))

这给出了您预期的答案:

906609

【讨论】:

    【解决方案2】:

    这是一个用于查找我在 stackoverflow 中找到的两个 3 位数乘积的最大回文数的函数。

    链接到我发现的内容-https://stackoverflow.com/a/7460573

    def is_pal(c):
           return int(str(c)[::-1]) == c
    
       maxpal = 0
       for a in range(999, 99, -1):
           for b in range(a, 99, -1):
               prod = a * b
               if is_pal(prod) and prod > maxpal:
                   maxpal = prod
    
       print maxpal
    

    【讨论】:

      【解决方案3】:
      n1=999
      n2=999
      k=0
      sl=[]
      while n1>1:
        count=n1
        while count>=1:
          result=n1*count
          res=str(result)
          res1=res[::-1]
          if (res==res1):
            sl.insert(k,result)
            k+=1
          count=count-1
        n1=n1-1
      print("largest pelindrom of 3 digit product is is %d" %(max(sl)))
      

      【讨论】:

      • 欢迎来到 StackOverflow!已经有一个被接受的答案,所以你应该用几句话解释你的答案与已经接受的答案有什么不同。
      • 因为我们必须找到最大的 3 位乘积,所以我开始先将高位乘以更快地执行,所以我从 n1=n2=999 开始并将 n1 临时存储在计数中,然后将 n2 与计数相乘。我已经习惯了循环,以便程序不会错过任何乘法,并且通过将其转换为字符串来存储在 res 中的乘法结果,以便我们可以轻松检查该字符串是否为回文。如果回文则存储在列表中并最后 i使用 max 函数打印了 max 。我已经执行了这两个代码,任何我的代码大约需要 4-5 秒,而其他代码需要 5-6 秒。
      • 原始答案的目的不是提供更好的算法,而是向 OP 解释他的逻辑错误在哪里。因此,它保留了尽可能多的原始代码(算法、变量名称和一般结构),这与从可读程序中获得正确结果是一致的。你的算法效率提高了 40%(499,499 个回文检查而不是 810,000 个),如果使用sl.append(result) 而不是sl.insert(k,result),或者使用一组,它会更快。但它没有回答问题谁能帮我解决我的逻辑缺陷?
      • 嗨,公猪 Guess first_num in range(100,1000): for second_num in range(100,1000) 是第一次 first_num 100 的缺陷,当它进入内循环时 second_num 100 然后 101 依此类推所以当内部循环结束时它再次乘以 100*101 然后 first_num=101 当涉及到内部循环时 second_num=100 所以它乘以 101*100 所以很多 luplicate 值即使我的代码时间也减少了如果我使用 n1>100 和n2>我后来意识到的 100 个
      【解决方案4】:
      palin=[]
      
      for a in (range(1,1000)):
          for b in (range(1,1000)):
              d = a*b
              d=str(d)
              if len(d)>5: 
                  if d[0]==d[5]:
                          if d[1]==d[4]:
                              if d[2]==d[3]:
                                  palin.append(d)
      palin.sort()
      print(palin[len(palin)-1])
      

      【讨论】:

        【解决方案5】:

        使用列表推导可以减少代码行数,但我会提供一个替代选项,使其更具可读性。

        List_of_palindromes = [i*j for i in range(100,1000) for j in range(i,1000) if str(i*j)==str(i*j)[::-1]]
        print(max(List_of_palindromes))
        

        更易读的表格

        List_of_palindromes = []
        for i in range(100,1000):
            for j in range(100,1000):
                if str(i*j)==str(i*j)[::-1]:
                    List_of_palindromes.append(i*j)
        print(max(List_of_palindromes))
        

        【讨论】:

          【解决方案6】:

          看看这个..! 这可以缩短,但这样更好理解(对于初学者)。

              l = list(range(100, 1000))
              m = list(range(100, 1000))
              prod_max = 0
          
              def is_palindrome(num):
                temp = num
                rev=0
                while num > 0:
                  div = num%10
                  rev = rev*10 + div
                  num = num //10
                  if rev == temp:
                    return True
                  else:
                    return False
          
              for i in range(len(l)):
                for j in range(len(m)):
                  prod = l[i]*m[j]
                  if is_palindrome(prod) == True:
                    if prod > prod_max:
                      prod_max = prod
                      num1 = l[i]
                      num2 = m[j]
              print(f'{prod_max} the product of {num1} and {num2} is a palindrome')
          

          【讨论】:

          • 欢迎来到 SO。尽管我们感谢您的回答,但如果它在其他答案之上提供额外的价值会更好。这个问题有几个答案,请您用几句话解释一下您的答案与其他人的不同之处吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-18
          • 1970-01-01
          • 2014-01-31
          相关资源
          最近更新 更多