2010-02-24 4 views
3

Я начал работать над некоторыми проблемами проекта Эйлера и решившими number 4 с простым грубой силой раствором:трансформирующих вложенные Python петли в списковый

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, которые могут помочь? :)

+1

Выполнение максимально компактных операций - довольно глупая цель. –

+1

Глупый, но развлекательный! :) –

ответ

7
c = range(a, b) 
print [d * e for d in c for e in c] 
+0

Спасибо! Я не знал, что вы могли бы это сделать ... :) –

+0

, а затем вы можете собрать все это, чтобы получить [d * e для d в диапазоне (a, b) для e в диапазоне (a, b). Кроме того, я бы рекомендовал использовать xrange, а не диапазон для скорости. –

+1

Просто будьте осторожны с порядком при итерации вложенных структур. Внешний слой нужно сначала повторить: '[x для y в N для x в y]' В противном случае имя для внутренней структуры не будет существовать, когда вы перейдете к итерации по нему (в этом случае 'y'). –

2

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

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]) 

Интересно, сколько круглых скобок, которые были бы в Лиспе ...

+1

':: - 1'? Это круто! :) Python превращается в NetHack - TDTTOE. Благодарю. –

3
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), но вместо того, чтобы возвращать список, он возвращает объект, который генерирует числа в диапазоне по запросу. Для циклизации это немного быстрее, чем диапазон() и более эффективный объем памяти.

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

    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] является список нарезка стенографии, чтобы отменить список.

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

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

+0

То есть * чрезвычайно * круто ... еще одна новая функция Python, которую выучили - генераторные выражения. Neat :) –

+0

Примечание: это может быть еще более компактным: 'max (a * b для (a, b) в продукте (xrange (900,1000), repeat = 2), если str (a * b) == str (а * б) [:: - 1]) ' – Synthetica

 Смежные вопросы

  • Нет связанных вопросов^_^