Преобразование вложенных циклов Python в списки - PullRequest
3 голосов
/ 24 февраля 2010

Я начал работать над некоторыми проблемами Project Euler и решил номер 4 с помощью простого решения грубой силы:

def mprods(a,b):
 c = range(a,b)
 f = []
 for d in c:
  for e in c:
   f.append(d*e)
 return f

max([z for z in mprods(100,1000) if str(z)==(''.join([str(z)[-i] for i in range(1,len(str(z))+1)]))])

После решения я попытался сделать его максимально компактным и придумал этот ужасный результат!

Чтобы не оставить что-то наполовину выполненным, я пытаюсь сжать функцию mprods в понимание списка. До сих пор я придумал эти попытки:

  • [d*e for d,e in (range(a,b), range(a,b))]
    Очевидно, совершенно не на том пути. : -)
  • [d*e for x in [e for e in range(1,5)] for d in range(1,5)]
    Это дает мне [4, 8, 12, 16, 4, 8, 12, 16, 4, 8, 12, 16, 4, 8, 12, 16], где я ожидаю [1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16] или аналогичный.

Есть какие-нибудь Pythonistas, которые могут помочь? :)

Ответы [ 3 ]

7 голосов
/ 24 февраля 2010
c = range(a, b)
print [d * e for d in c for e in c]
3 голосов
/ 25 февраля 2010
from itertools import product

def palindrome(i):
  return str(i) == str(i)[::-1]

x = xrange(900,1000)

max(a*b for (a,b) in (product(x,x)) if palindrome(a*b))
  • xrange(900,1000) похоже на range(900,1000), но вместо возврата списка он возвращает объект, который генерирует числа в диапазоне по требованию. Для циклов это немного быстрее, чем range () и более эффективное использование памяти.

  • product(xrange(900,1000),xrange(900,1000)) дает декартово произведение входных итераций. Это эквивалентно вложенным циклам for. Например, product(A, B) возвращает так же, как: ((x,y) for x in A for y in B). Крайние левые итераторы находятся в самом внешнем цикле for, поэтому кортежи выходных циклов работают аналогично одометру (с изменением крайнего правого элемента на каждой итерации).

    product('ab', range(3)) -> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2) product((0,1), (0,1), (0,1)) -> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...

  • str(i)[::-1] - сокращение списка, чтобы перевернуть список.

  • Обратите внимание, как все обернуто в выражение генератора , высокопроизводительное обобщающее понимание списка и генераторы с эффективным использованием памяти.

  • Также обратите внимание, что самый большой палиндром, составленный из произведения двух двузначных чисел, сделан из чисел 91 99, двух чисел в range(90,100). Экстраполируя на трехзначные числа, вы можете использовать range(900,1000).

2 голосов
/ 24 февраля 2010

Думаю, вам понравится эта строка (отформатированная для удобства чтения):

max(z for z in (d*e
                for d in xrange(100, 1000)
                for e in xrange(100, 1000))
            if str(z) == str(z)[::-1])

Или слегка изменено:

c = range(100, 1000)
max(z for z in (d*e for d in c for e in c) if str(z) == str(z)[::-1])

Интересно, сколько паренов будет в Лиспе ...

...