2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Найти наибольший палиндром произведения двух чисел на Python
Сообщение01.07.2017, 13:34 


17/03/17
176
Всем привет. Возникла проблема поиска палиндрома произведения двух чисел (задание в низу).

Число-палиндром с обеих сторон (справа налево и слева направо) читается одинаково. Самое большое число-палиндром, полученное умножением двух двузначных чисел $\text{~---}$ $9009 = 91 \cdot 99$.
Найдите самый большой палиндром, полученный умножением двух трёхзначных чисел.

Я написал код в котором два цикла, которые создают два трехзначных числа. Эти числа умножаются друг на друга. Затем полученное число проверяют на палиндром и записываются в список. Далее я ищу максимальный элемент.
код: [ скачать ] [ спрятать ]
Используется синтаксис Python
s_list=[]
def num(i):
    k=1000
    while k>=100:
        k-=1
        s0=str(i*k)
        s=s0[::-1]
        if s0==s:
            s=int(s)
            s_list.append(s)
            return s_list
class palinom:
    def num(self):
        i=99
        while i<=1000:
            i+=1
            num(i)
        return num(i)
a=palinom()
print(max(a.num()))
 

В ответе я получаю $999999$, но это неправильно. В чем проблема?

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение01.07.2017, 18:19 
Заслуженный участник


06/07/11
5627
кран.набрать.грамота
Я питон не знаю, но вот знак "меньше или равно" перед тысячей мне не нравится...
Сделайте отладочный вывод, пусть программа в каждой строке выводит, какие числа она перемножает.

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение01.07.2017, 18:40 


27/02/09
253
Цикл
Используется синтаксис Python
        while i<=1000:
            i+=1
            num(i)
 
завершается при первом $\rm{i}>1000$, т.е., при $\rm{i}=1001$. После этого у вас снова вызывается функция $\rm{num}$ для этого $\rm{i}$:
Используется синтаксис Python
        return num(i)
 
которая, естественно, помещает в список $1001\cdot 999$ как палиндром. Он и выводится, поскольку самый большой.

Да, и внутри цикла тоже вызывается $\rm{num}(1001)$ - там же увеличение счётчика идёт перед вызовом функции.

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение02.07.2017, 11:18 


17/03/17
176
Все получилось. Пришлось переделать немного код.
код: [ скачать ] [ спрятать ]
Используется синтаксис Python
s_list=[]
def palinom():
    for i in range(100,1000):
        k=1000
        while k>=100:
            s=str(i*k)
            s0=s[::-1]
            k-=1
            if s0==s:
                s_list.append(int(s))
    return s_list
a=palinom()
print(max(a))


 

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение07.07.2017, 04:45 


30/08/10
159

(Оффтоп)

Есть некоторый смысл сделать перебор так:

Используется синтаксис Python
for i in range(100,1000):
    for j in range(100,1000):
        #здесь всё то, что в цикле

(Оффтоп)

Первое и второе числа играют одинаковую роль, и по ним можно идти совершенно одинаково. То есть можно сделать два почти одинаковых цикла for. Это довольно сильно улучшает читаемость кода.

И ещё - немного эффективнее будет хранить одно число - наибольший встреченный, на данный момент, палиндром, назовём его p. В самом начале сделать его равным 0, а дальше, каждый раз, когда в результате умножения получается палиндром, сравнивать его с p и если получился больше, присваивать p получившийся палиндром. Это позволит уменьшить расход памяти (в конце перебора будут храниться не все найденные палиндромы, а только один, самый большой). Хотя это изменение кода уже не так полезно, так как читаемость может ухудшиться.

Ещё можно примерно в два раза уменьшить число перебираемых вариантов, ещё немного изменив циклы.

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение07.07.2017, 09:36 
Заслуженный участник


06/07/11
5627
кран.набрать.грамота
Tookser
Желание сократить число перебираемых вариантов - это правильное желание. Все остальное, что у вас есть - неправильно :mrgreen:
Во-первых, в задаче сказано про трехзначные числа, так что 1000 отпадает. 100 тоже можно откинуть, совершенно очевидно, что ничего толкового с сотней не выйдет. Хотя я не знаю питон, так что если конструкция for i in range(100,1000): означает перебор числел от 101 до 999 - то ок.
Во-вторых, мы ищем максимум. Поэтому начинать надо с 999 и идти вниз.
В-третьих, умножение коммутативно, поэтому цикл по j надо начинать не с 999, а с i.
Далее, когда найден хотя бы один палиндром (допустим, при значениях i1 и j1), не имеет смысла продолжать цикл по i до 101. Достаточно дойти до j1, все остальные произведения будут заведомо меньше.

-- 07.07.2017, 11:12 --

Кстати, есть способ еще круче, но немного менее очевидный.
Перебираем числа, начиная с 1998. Цикл выглядит примерно так (на паскале напишу, он довольно понятный, а питон я не знаю):
Используется синтаксис Pascal
s := 1998; p := 0; // p - искомое произведение
while p = 0 do
  begin
    i := 999;
    j := s - i;
    while (j <= i) and (p = 0) do
      begin
        if {i * j является палиндромом} then p := i * j;
        inc(j); // увеличение на единицу
        dec(i); // уменьшение на единицу
      end;
    dec(s);
  end;
Число перебираемых вариантов меньше и первое найденное произведение будет гарантированно наибольшим.

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение07.07.2017, 10:36 
Заслуженный участник


04/03/09
906
Если пишем на питоне, то желание сократить код должно перевешивать желание сократить перебираемые варианты. =) Я вот за такое:
Используется синтаксис Python
from operator import mul
print max(x for x in map(mul,range(100,1000),range(100,1000)) if str(x)==str(x)[::-1])

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение07.07.2017, 10:43 
Заслуженный участник


06/07/11
5627
кран.набрать.грамота
Я для сокращения кода предпочитаю SQL. Длиннее, чем питон, но все равно сильно короче, чем паскаль. И отладка проще на порядок.
Используется синтаксис Oracle 11 SQL
WITH t AS (SELECT ROWNUM + 99 n FROM dual CONNECT BY LEVEL <= 900)
SELECT MAX(t1.n * t2.n)
  FROM t t1, t t2
 WHERE TO_CHAR(t1.n * t2.n) = REVERSE(TO_CHAR(t1.n * t2.n))

 Профиль  
                  
 
 Re: Найти наибольший палиндром произведения двух чисел на Python
Сообщение07.07.2017, 22:24 
Заслуженный участник


27/04/09
28128
Зачиркано зачиркано

Скучный код без оптимизаций:

Используется синтаксис Haskell
ghci> let pal n = (let s = show n in s == reverse s) in maximum [k | i <- [100..1000-1], j <- [i..1000-1], let k = i * j, pal k]
906609

UPD. Вот дословная запись оптимизированного поиска rockclimber (жанр однострочников ужасен):

Используется синтаксис Haskell
ghci> let li s0 i0 = filter pal . map (uncurry (*)) . takeWhile (\(i, j) -> j <= i) $ zip [i0,i0-1..] [j0,j0+1..] where j0 = s0 - i0 in head $ concat [li s0 999 | s0 <- [1998,1998-1..]]
906609

UPD2. Ой, это не однострочник, pal используется (я его потом определил отдельно).

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group