2014-01-29 4 views
0

Это мое решение для 5-й проблемы в Project Euler. Есть ли способ улучшить условный цикл while вместо использования суммы?Оптимизация кода Python для Project Euler # 5

table = range(1,21) 
result = 1 
pf = 2 
while sum(table) > len(table): 
    flag = False 
    for x,y in enumerate(table): 
     if y % pf == 0: 
     table[x] = y/pf 
     flag = True 
    if flag: 
     result *= pf 
    else: 
     pf += 1 
print result 
+6

появляется этот вопрос быть не по теме, потому что она принадлежит на HTTP: //codereview.stackexchange .com – jonrsharpe

ответ

3

Это всегда яснее, чтобы написать программу, используя функцию высшего порядка вместо петли, так как все посторонние переменные, которые управляют работой петли исчезают. Вот программа, которая выполняет те же вычисления, что и ваши, но петли исчезают, как и переменные table, result, pf и flag; переменные x и y остаются, но ограничивается ролью поддержки в качестве вспомогательной функции, а не как часть основного расчета:

>>> from fractions import gcd 
>>> def lcm(x,y): return x*y/gcd(x,y) 
... 
>>> print reduce(lcm,range(1,21)) 
232792560 
+0

Я не согласен с тем, что это всегда яснее - вам всегда нужно подумать, станет ли код более понятным, поворачивая на циклы на функции. –

+0

@SimeonVisser: Конечно, все может быть оскорблено. Но прятание сантехники делает большинство программ более четкими и простыми. – user448810

1

Используйте константу. Легче понять, когда вы хотите вернуться и попробовать другое значение.

MAX_DIVISOR = 20 
table = range(1,MAX_DIVISOR + 1) 
result = 1 
pf = 2 
while pf < MAX_DIVISOR + 1: 
    flag = False 
    for x,y in enumerate(table): 
     if y % pf == 0: 
    table[x] = y/pf 
    flag = True 
    if flag: 
     result *= pf 
    else: 
     pf += 1 
print result 
+0

Как эта условная работа? pf - основной фактор, который я использую для разделения элементов в таблице, если это их фактор.Алгоритм останавливается, когда все элементы в таблице равны 1. Я не понимаю, почему pf должен быть меньше, чем максимальный элемент в таблице. Ну, я знаю, как это имеет смысл, поскольку цикл является условным? – Veritas

+0

Исправлена ​​ошибка в состоянии цикла while. Если вы посмотрели содержимое «таблицы» во время работы, вы бы увидели, что он продолжает увеличивать 'pf', пока не достигнет 19 - последнего простого числа. Фактически, ваша версия всегда будет работать, пока не достигнет последнего простого числа до целевого номера. – JoeClacks

+0

Эта версия (с фиксированным условным) работает только до последнего номера. Таким образом, единственное различие будет не больше [Prime gap] (http://en.wikipedia.org/wiki/Prime_gap), которое выполняется вокруг порядка ** O ((ln (n))^2) ** - в основном незначительные. На самом деле, если бы мы хотели сделать этот алгоритм значительно лучше, мы могли бы установить 'pf' только последовательность простых чисел, избегая проверки всех составных чисел. – JoeClacks

0

Вы можете использовать any() для проверки таблицы, например, так:

while any(n != 1 for n in table): 
    # do stuff 

Я думаю, что это яснее, чем sum(table) > len(table).

Кроме того, как рекомендуется @JoeClacks, используйте константу.

Полное пересмотренное решение:

MAX_DIVISOR = 20 
table = list(range(1, MAX_DIVISOR+1)) 

result = 1 
pf = 2 

while any(n != 1 for n in table): 
    assert pf <= MAX_DIVISOR 
    flag = False 
    for i,n in enumerate(table): 
     if n % pf == 0: 
      table[i] = n//pf 
      flag = True 
    if flag: 
     result *= pf 
    else: 
     pf += 1 

print(result) 

Я добавил assert, чтобы убедиться, что pf имеет только правовые ценности; это не нужно, если в коде нет ошибок, но может быть хорошей идеей сделать проверку правильности кода.

Я использовал i и n для индекса и номера, а не x и y.

Я использовал целочисленный оператор деления Python //, а не /, поэтому код будет работать на Python 3.x так же, как на Python 2.x. Также, как я написал оператор print, он будет одинаково хорошо работать в Python 3.x и Python 2.x.

я изменил отступ на ступеньках 4 пробелов в соответствии с PEP 8.

http://www.python.org/dev/peps/pep-0008/

Примечание: Мне нравится этот алгоритм для решения этой проблемы. Это элегантно. Вы придумали это, получите его из книги или что?

EDIT: На самом деле проблема Эйлера проекта 5 обсуждалась здесь, на StackOverflow. Вот ответ, который я просто сравнил с приведенным выше ответом. Это почти в десять раз быстрее, чем выше. Это немного сложнее!

https://stackoverflow.com/a/8026041/166949

+0

Алгоритм только что пришел ко мне вчера, но он, вероятно, уже существует. Кстати, любая функция выражает условие намного лучше, чем сумма, которую я использую. То, что я имел в виду, заменило это условным фактором, но я даже не уверен, что это возможно. – Veritas