简体   繁体   中英

Find the largest palindrome made from the product of two 3-digit numbers using numpy

I got stuck on this question when I tried solving it using the numpy package. My idea was that I would multiply and keep a list of all the calculations I did of the 3 digit numbers ranging from 100 to 999, then check through the list to see which ones are a palindrome and save them. Finally, I would order the list and get the largest palindrome. Code below shows what I tried to do.

import numpy as np

def void():
    list1 = np.array(range(100,999))
    list2 = np.array(range(100,999))
    k = []
    
    for i,j in zip(list1,list2):
        k.append(np.multiply(list1,list2))
        
    b = []
    
    for x in range(0,len(k)):
        if(reverseNum(k[x])==k[x]):
            b.append(k[x])
            
    print(b)
    print(b[-1])
    
def reverseNum(num):
    rev = 0
    
    while(num>0):
        rem = num % 10
        rev = (rev*10) +rem
        num = num // 10
        
    return rev  
    
void()

However, when I try to check if the numbers in the list are a palindrome, I get the following bug:

Traceback (most recent call last):                                                                                    
  File "main.py", line 40, in <module>                                                                                
    void()                                                                                                            
  File "main.py", line 22, in void                                                                                    
    if(reverseNum(k[x]),k[x]):                                                                                        
  File "main.py", line 31, in reverseNum                                                                              
    while(num>0):                                                                                                     
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()  

Does this mean that it is not possible to use numpy as a method to solve this problem? If it is, where am I going wrong?

EDIT: What I have tried so far (since it was asked): Based on the error messages, I tried using np.equal as well as np.greater instead of checking if(reverseNum(k[x])==k[x]) and num>0 but it gives the same error.

A NumPy way assuming the result has six digits (it can't have more, as 999 2 is 998001):

import numpy as np

v = np.arange(100, 1000)                     # the range of three-digit numbers
a = np.outer(v, v)                           # all the products
print(a[(a // 100000 == a % 10) &            # first digit == sixth digit
        (a // 10000 % 10 == a // 10 % 10) &
        (a // 1000 % 10 == a // 100 % 10)].max())

Prints 906609 .

Double checking with pure Python:

>>> max(x*y
        for x in range(100, 1000)
        for y in range(100, 1000)
        if str(x*y) == str(x*y)[::-1])
906609

Your issue stems from the your line including the zip . My code below isn't pretty, but attempts to follow your approach loosely.

import numpy as np

def void():
    list1 = np.array(range(100,1000))  # you want to include '999'
    list2 = np.array(range(100,1000))
    k = []
    
    for i,j in zip(list1,list2):
        k.append(np.multiply(list1,j))
        
    b = []
    
    for r, row in enumerate(k):
        for c, cell in enumerate(row):
            if reverseNum(cell)==cell:
                b.append(cell)
            
    print(b)
    print(max(b))

    
def reverseNum(num):
    rev = 0
    
    while(num>0):
        rem = num % 10
        rev = (rev*10) +rem
        num = num // 10
        
    return rev
    
void()

Why does it have to use numpy?

# test if palindrome based on str
def is_palindrome(number: int):
    converted_to_string = str(number)
    return converted_to_string == converted_to_string[::-1]


# product of two three-digit numbers
you_right = []
values = []
for x in range(999, 99, -1):
    for y in range(999, 99, -1):
        product = x*y
        if is_palindrome(product):
            values.append((x, y))
            you_right.append(product)
winner = you_right.index(max(you_right))
print(values[winner])
# output
(993, 913)

Another real NumPy solution, using your way to reverse the numbers (fixing it mostly by using .any() as suggested in the error message, which you stubbornly refused to try).

v = np.arange(100, 1000)
a = np.outer(v, v)

num = a.copy()
rev = num * 0
while (m := num > 0).any():
    rev[m] = rev[m] * 10 + num[m] % 10
    num[m] //= 10

print(a[rev == a].max())

Without the mask m you get the same result (906609), but it's safer with it. Otherwise products with five digits aren't reversed correctly, like 101*102=10302 becomes 203010 instead of 20301.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM