вопрос о циклах в 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)

Использование xrange вместо range должно использовать меньше памяти, особенно если вы хотите попробовать большие диапазоны.

Используя тот же алгоритм (см. Другие ответы, чтобы узнать о лучших подходах), вы можете использовать itertools.count, чтобы получить цикл, который выполняется вечно.

import itertools

for x in itertools.count(1):
    for y in xrange(1, x):
         for z in xrange(1, y):
              if x*x == y*y + z*z:
                  print x, y, z

Как правило, нельзя. Три переменные, три петли.

Но это частный случай, как никто не указал. Решить эту проблему можно двумя петлями.

Также нет смысла проверять 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. И вы можете найти более эффективный метод в сообщениях выше.