Python - 如何减少大 O 并提高多个嵌套 for 循环的效率?
Python - How to decrease big O and increase efficiency in multiple nested for loops?
我写了一个 python 脚本来计算满足以下条件的所有可能性:
- a^(2) + b^(2) + c^(2) + d^(2) + e^(2) = f^(2)
- a、b、c、d、e、f 是不同的非零整数
- a,b,c,d,e 是孪生素数之间的偶数(例如 11 和 13 是孪生素数,因此 12 是一个有效的可能性)
- f ≤ 65535
- a的位数之和==b的位数之和==c的位数之和==d的位数之和==e的位数之和== f
的位数之和
我不确定加入标准5是否会有任何结果,但我希望至少能及时了解。理想情况下,还应满足以下条件:
- 对 a、b、c、d、e、f 使用相同值但顺序不同的结果不应出现在结果中;理想情况下,它们也应该从 for 循环中排除
- 结果应按 a 的最低值排在第一位,b 的最低值排在第一位,依此类推
我的问题是,如何减少操作时间并提高效率?
import itertools
import time
start_time = time.time()
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return True
def generate_twin_primes(start, end):
for i in range(start, end):
j = i + 2
if(is_prime(i) and is_prime(j)):
n = text_file2.write(str(i+1) + '\n')
def sum_digits(n):
r = 0
while n:
r, n = r + n % 10, n // 10
return r
def is_sorted(vals):
for i in range(len(vals)-2):
if vals[i] < vals[i+1]:
return False
return True
def pythagorean_sixlet():
valid = []
for a in x:
for b in x:
for c in x:
for d in x:
for e in x:
f = (a * a + b * b + c * c + d * d + e * e)**(1/2)
if f % 1 == 0 and all(x[0]!=x[1] for x in list(itertools.combinations([a, b, c, d, e], 2))):
if sum_digits(a) == sum_digits(b) == sum_digits(c) == sum_digits(d) == sum_digits(e) == sum_digits(int(f)):
valid.append([a, b, c, d, e, int(f)])
for valid_entry in valid:
if is_sorted(valid_entry):
with open("output.txt", "a") as text_file1:
text_file1.write(str(valid_entry[0]) + " " + str(valid_entry[1]) + " " + str(valid_entry[2]) + " " + str(valid_entry[3]) + " " + str(valid_entry[4]) + " | " + str(valid_entry[5]) + '\n')
text_file1.close()
#input #currently all even numbers between twin primes under 1000
text_file2 = open("input.txt", "w")
generate_twin_primes(2, 1000)
text_file2.close()
# counting number of lines in "input.txt" and calculating number of potential possibilities to go through
count = 0
fname = "input.txt"
with open(fname, 'r') as f:
for line in f:
count += 1
print("Number of lines:", count)
print("Number of potential possibilites:", count**5)
with open('input.txt', 'r') as f:
x = f.read().splitlines()
x = [int(px) for px in x]
pythagorean_sixlet()
print("--- %s seconds ---" % (time.time() - start_time))
好吧,这听起来很像硬件问题,所以我们不能轻易放弃农场...:)
需要考虑的几件事:
- 如果你想检查独特的组合,可能性的数量比
count**5
减少了很多,对吗?
- 您正在循环的最内部进行所有检查。您能否在此过程中进行一些检查,这样您就不必生成和测试 all 的可能性,即 "expensive."
- 如果您确实选择在内部检查唯一性,请找到一种更好的方法来进行所有组合……这非常昂贵。提示:如果你把已有的数字组成一组,它会告诉你什么?
实施以上部分内容:
Number of candidate twin primes between [2, 64152]: 846
total candidate solutions: 1795713740 [need to check f for these]
elapsed: 5.957056045532227
size of result set: 27546
20 random selections from the group:
(40086.0, [3852, 4482, 13680, 20808, 30852])
(45774.0, [6552, 10458, 17028, 23832, 32940])
(56430.0, [1278, 13932, 16452, 27108, 44532])
(64746.0, [15732, 17208, 20772, 32562, 46440])
(47610.0, [3852, 9432, 22158, 24372, 32832])
(53046.0, [3852, 17208, 20772, 23058, 39240])
(36054.0, [4518, 4932, 16452, 21492, 22860])
(18396.0, [3258, 4518, 5742, 9342, 13680])
(45000.0, [2970, 10890, 16650, 18540, 35730])
(59976.0, [2970, 9342, 20772, 35802, 42282])
(42246.0, [3528, 5652, 17208, 25308, 28350])
(39870.0, [3528, 7308, 16362, 23292, 26712])
(64656.0, [8820, 13932, 16452, 36108, 48312])
(61200.0, [198, 882, 22158, 35532, 44622])
(55350.0, [3168, 3672, 5652, 15732, 52542])
(14526.0, [1278, 3528, 7128, 7560, 9432])
(65106.0, [5652, 30852, 31248, 32832, 34650])
(63612.0, [2088, 16830, 26730, 33750, 43650])
(42066.0, [2088, 13932, 15642, 23832, 27540])
(31950.0, [828, 3582, 13932, 16452, 23292])
--- 2872.701852083206 seconds ---
[Finished in 2872.9s]
我写了一个 python 脚本来计算满足以下条件的所有可能性:
- a^(2) + b^(2) + c^(2) + d^(2) + e^(2) = f^(2)
- a、b、c、d、e、f 是不同的非零整数
- a,b,c,d,e 是孪生素数之间的偶数(例如 11 和 13 是孪生素数,因此 12 是一个有效的可能性)
- f ≤ 65535
- a的位数之和==b的位数之和==c的位数之和==d的位数之和==e的位数之和== f 的位数之和
我不确定加入标准5是否会有任何结果,但我希望至少能及时了解。理想情况下,还应满足以下条件:
- 对 a、b、c、d、e、f 使用相同值但顺序不同的结果不应出现在结果中;理想情况下,它们也应该从 for 循环中排除
- 结果应按 a 的最低值排在第一位,b 的最低值排在第一位,依此类推
我的问题是,如何减少操作时间并提高效率?
import itertools
import time
start_time = time.time()
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return True
def generate_twin_primes(start, end):
for i in range(start, end):
j = i + 2
if(is_prime(i) and is_prime(j)):
n = text_file2.write(str(i+1) + '\n')
def sum_digits(n):
r = 0
while n:
r, n = r + n % 10, n // 10
return r
def is_sorted(vals):
for i in range(len(vals)-2):
if vals[i] < vals[i+1]:
return False
return True
def pythagorean_sixlet():
valid = []
for a in x:
for b in x:
for c in x:
for d in x:
for e in x:
f = (a * a + b * b + c * c + d * d + e * e)**(1/2)
if f % 1 == 0 and all(x[0]!=x[1] for x in list(itertools.combinations([a, b, c, d, e], 2))):
if sum_digits(a) == sum_digits(b) == sum_digits(c) == sum_digits(d) == sum_digits(e) == sum_digits(int(f)):
valid.append([a, b, c, d, e, int(f)])
for valid_entry in valid:
if is_sorted(valid_entry):
with open("output.txt", "a") as text_file1:
text_file1.write(str(valid_entry[0]) + " " + str(valid_entry[1]) + " " + str(valid_entry[2]) + " " + str(valid_entry[3]) + " " + str(valid_entry[4]) + " | " + str(valid_entry[5]) + '\n')
text_file1.close()
#input #currently all even numbers between twin primes under 1000
text_file2 = open("input.txt", "w")
generate_twin_primes(2, 1000)
text_file2.close()
# counting number of lines in "input.txt" and calculating number of potential possibilities to go through
count = 0
fname = "input.txt"
with open(fname, 'r') as f:
for line in f:
count += 1
print("Number of lines:", count)
print("Number of potential possibilites:", count**5)
with open('input.txt', 'r') as f:
x = f.read().splitlines()
x = [int(px) for px in x]
pythagorean_sixlet()
print("--- %s seconds ---" % (time.time() - start_time))
好吧,这听起来很像硬件问题,所以我们不能轻易放弃农场...:)
需要考虑的几件事:
- 如果你想检查独特的组合,可能性的数量比
count**5
减少了很多,对吗? - 您正在循环的最内部进行所有检查。您能否在此过程中进行一些检查,这样您就不必生成和测试 all 的可能性,即 "expensive."
- 如果您确实选择在内部检查唯一性,请找到一种更好的方法来进行所有组合……这非常昂贵。提示:如果你把已有的数字组成一组,它会告诉你什么?
实施以上部分内容:
Number of candidate twin primes between [2, 64152]: 846
total candidate solutions: 1795713740 [need to check f for these]
elapsed: 5.957056045532227
size of result set: 27546
20 random selections from the group:
(40086.0, [3852, 4482, 13680, 20808, 30852])
(45774.0, [6552, 10458, 17028, 23832, 32940])
(56430.0, [1278, 13932, 16452, 27108, 44532])
(64746.0, [15732, 17208, 20772, 32562, 46440])
(47610.0, [3852, 9432, 22158, 24372, 32832])
(53046.0, [3852, 17208, 20772, 23058, 39240])
(36054.0, [4518, 4932, 16452, 21492, 22860])
(18396.0, [3258, 4518, 5742, 9342, 13680])
(45000.0, [2970, 10890, 16650, 18540, 35730])
(59976.0, [2970, 9342, 20772, 35802, 42282])
(42246.0, [3528, 5652, 17208, 25308, 28350])
(39870.0, [3528, 7308, 16362, 23292, 26712])
(64656.0, [8820, 13932, 16452, 36108, 48312])
(61200.0, [198, 882, 22158, 35532, 44622])
(55350.0, [3168, 3672, 5652, 15732, 52542])
(14526.0, [1278, 3528, 7128, 7560, 9432])
(65106.0, [5652, 30852, 31248, 32832, 34650])
(63612.0, [2088, 16830, 26730, 33750, 43650])
(42066.0, [2088, 13932, 15642, 23832, 27540])
(31950.0, [828, 3582, 13932, 16452, 23292])
--- 2872.701852083206 seconds ---
[Finished in 2872.9s]