вопрос о циклах в Python
Я хочу вычислить пифагоровые триплеты (код ниже), и я хочу вычислить бесконечно, как мне это сделать, не используя три цикла for? Могу ли я каким-то образом использовать цикл for? Благодарю.
import math
def main():
for x in range (10000, 1000):
for y in range (10000, 1000):
for z in range(10000, 1000):
if x*x == y*y + z*z:
print y, z, x
print '-'*50
if __name__ == '__main__':
main()
Ответов (12)12
Использование xrange вместо range
должно использовать меньше памяти, особенно если вы хотите попробовать большие диапазоны.
Как правило, нельзя. Три переменные, три петли.
Но это частный случай, как никто не указал. Решить эту проблему можно двумя петлями.
Также нет смысла проверять y, z и z, y.
Ах да range(10000, 1000) = []
.
import math
for x in range(1, 1000):
for y in range(x, 1000):
z = math.sqrt(x**2 + y**2)
if int(z) == z:
print x, y, int(z)
print '-'*50
Вам понадобится всего два цикла - просто проверьте, math.sqrt(x*x+y*y)
является ли это целым числом. Если да, то вы открыли тройку пифагора.
Я новичок в Python, поэтому не знаю, что range(10000, 1000)
делает - где он начинается и заканчивается? Я спрашиваю, потому что вы можете вдвое сократить время выполнения, указав диапазон для y
начала x
вместо того, чтобы исправлять его, из-за того, что сложение является коммутативным.
edit: Этот ответ - это то, к чему я пришел, и что я написал бы, если бы знал больше Python.
Вы можете разместить свой код в одном основном цикле следующим образом:
MIN = 10000
MAX = 10010
a = [MIN, MIN, MIN]
while True:
print a
for i in range(len(a)):
a[i] = a[i] + 1
if a[i] < MAX:
break
a[i] = MIN
i += 1
else:
break
Вместо этого print a
вы можете выполнить там свой тест на триплет Пифагора. Это будет работать для произвольного количества измерений.
Если вы действительно хотите делать это бесконечно, вам придется использовать другую технику итераций, например диагонализацию .
Если вы хотите считать до бесконечности ..
Создайте функцию генератора, которая считает с нуля и никогда не останавливается, и используйте для нее цикл for.
def inf():
i = 0
while True:
yield i
i = i + 1
for i in inf():
print i # or do whatever you want!
Я не знаю, есть ли уже такая встроенная функция
Это то же самое, что и ответ Джана Берка Гудера, но сделано как генератор, просто для удовольствия. Это не очень полезно с вложенными циклами здесь, но часто может быть более чистым решением. Ваша функция дает результаты; позже вы беспокоитесь о том, сколько их нужно получить.
import math
def triplets(limit):
for x in range(1, limit):
for y in range(x, limit):
z = math.sqrt(x**2 + y**2)
if int(z) == z:
yield x, y, int(z)
for x, y, z in triplets(10):
print x, y, z
print "-" * 50
Не самый эффективный (Python построит массив с миллиардом кортежей), но это единственный цикл:
for x, y, z in [(x, y, z) for x in range(10000, 11000) for y in range(10000, 11000) for z in range(10000, 11000)]:
if x*x == y*y + z*z:
print y, z, x
print '-'*50
Или, как предположил Кристиан Уиттс ,
for x, y, z in ((x, y, z) for x in xrange(10000, 11000) for y in xrange(10000, 11000) for z in xrange(10000, 11000)):
if x*x == y*y + z*z:
print y, z, x
print '-'*50
(при условии, что Python> = 2.4) использует генераторы вместо построения массива из миллиардов кортежей.
В любом случае, вы не должны кодировать так ... Ваш исходный код с вложенными циклами более понятен.
Вот эффективная версия, использующая итераторы, которая генерирует все такие тройки по порядку. Хитрость здесь в том, чтобы перебирать наборы пар (x, y), сумма которых равна N, для всех N.
импортная математика импортировать itertools def all_int_pairs (): "генерировать все пары положительных целых чисел" для n в itertools.count (1): для x в xrange (1, n / 2 + 1): доходность x, nx для x, y в all_int_pairs (): z = math.sqrt (x ** 2 + y ** 2) если int (z) == z: напечатать x, y, int (z) print '-' * 50
На бесконечность нужно минимум три петли. Чтобы сделать что-то гибкое, понадобится тонна петель. Этот пример является решением проблемы 9 проекта Эйлера и других.
#!/usr/bin/env python
def fcount(start=1):
n = float(start)
while True:
yield n
n += 1
def find_triples():
for c in fcount():
for b in fcount():
if b > c:
break
for a in fcount():
if a > b:
break
if a ** 2 + b ** 2 == c ** 2:
yield (a, b, c)
def triples_by_sum(targetsum):
for a, b, c in find_triples():
if a + b + c == targetsum:
yield a, b, c
if c > targetsum:
break
if __name__ == '__main__':
# Finds multiple triples
for a, b, c in triples_by_sum(252):
print a, b, c
# Finds single triples
a, b, c = triples_by_sum(1000).next()
print a, b, c
# Goes forever
for a, b, c in find_triples():
print a, b, c
Как насчет использования itertools.product вместо этого?
# range is [10000, 1000)
for x, y, z in itertools.product(range(10000, 1000, -1), repeat=3):
if x * x == y * y + z * z:
print(y, z, x)
с подстилкой оптимизировать:
for x, y, z in itertools.product(range(10000, 1000, -1), repeat=3):
if y >= x or z >= x or x >= (y + z) or z < y:
continue
if x * x == y * y + z * z:
print(y, z, x)
РЕДАКТИРОВАТЬ: Здесь я просто даю возможность использовать product
вместо нескольких циклов for. И вы можете найти более эффективный метод в сообщениях выше.