S ...我正在尝试解决问题n。 Project Euler网站(https://projecteuler.info/problem=8中的8) 我想知道是否有一种更干净的方式来编写条件代码
n="7316717653..." # there are 1000 digits
(https://projecteuler.info/problem=8)
Max=0
s=[int(s) for s in n]
for i in range(len(s)-3):
if s[i]*s[i+1]*s[i+2]*s[i+2] > Max:
Max=s[i]*s[i+1]*s[i+2]*s[i+3]
print(Max)
# In particular
if s[i]*s[i+1]*s[i+2]*s[i+2] > Max:
Max=s[i]*s[i+1]*s[i+2]*s[i+3]
我该如何写得更好(我还必须写成 如果s [i] * s [i + 1] * s [i + 2] * s [i + 2] * s [i + 3] ... * s [i + 13] 因此,找到一种更好的方法会很不错。 预先谢谢你!
编辑: 我写的帖子非常糟糕...对不起。
我的意思是:
我可以写s [i] * s [i + 1] * s [i + 2] * s [i + 3] * s [i + 4] * s [i + 5] * s [i +6] * s [i + 7] * s [i + 8] * s [i + 9] * s [i + 10] * s [i + 11] * s [i + 12] * s [i + 13]>最大值:
或根据建议(更好,谢谢)
Max = max(Max,s [i] * s [i + 1] * s [i + 2] * s [i + 3] * s [i + 4] * s [i + 5] * s [i + 6] * s [i + 7] * s [i + 8] * s [i + 9] * s [i + 10] * s [i + 11] * s [i + 12] * s [ i + 13])
以更好的方式? 就像用自动方式做s [i + n] 13或任何时间一样。 对不起,我的英语不好。
编辑2: 您在我编辑时回答了,谢谢大家!
答案 0 :(得分:2)
您可以使用functools.reduce来计算乘积:
from functools import reduce
from operator import mul
reduce(mul, [2, 3, 4]) # calculates 2 * 3 * 4
# 24
您的代码将按照问题末尾的要求乘以13位数字:
from functools import reduce
from operator import mul
n = "7316717653..." # there are 1000 digits
s = [int(s) for s in n]
maxi = max(reduce(mul, s[i:i+13]) for i in range(len(s)-13))
print(maxi)
编辑
尽管紧凑写,但这并不是真正有效,特别是当数字序列相乘的长度变长时。
一个更有效的想法是在滑动窗口中以数字的形式查看我们的产品。当窗口向右移动一位时,乘积除以刚从左边得出的数字,然后乘以在右边输入的数字。
这样,无论序列的长度如何,我们只需要获取两个数字并在每个步骤上执行两次操作即可。
def findmax(seq, k=13):
p = reduce(mul, seq[:k])
maxi = p
for i in range(k, len(seq)):
p = p * seq[i] // seq[i-k]
if p > maxi:
maxi = p
return maxi
一些粗略的时序表明,长度为2的序列的速度已经快了2倍以上,长度为13的速度快了5倍以上。
答案 1 :(得分:2)
您可以使用numpy python库解决此问题。与列表或字符串相比,它可以更有效地处理数字数据。
例如,您可以使用以下方法解决此问题:
import numpy as np
#n = "7316717653..." # there are 1000 digits
n = '7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450'
n_as_nparray = np.array([int(character) for character in n])
every_thirteen_char = np.array([n_as_nparray[i:i+13] for i in range(len(n)-13)])
您将拥有一个包含shape = (987,13)
的数组。
然后,您的最大产品将是:
>>> every_thirteen_char.prod(axis=1).max()
23514624000
然后使用以下命令找到序列
>>> every_thirteen_char[every_thirteen_char.prod(axis=1).argmax()]
array([5, 5, 7, 6, 6, 8, 9, 6, 6, 4, 8, 9, 5])
答案 2 :(得分:1)
只需直接使用max
函数,无需使用if
语句。
Max = max(Max, s[i]*s[i+1]*s[i+2]*s[i+3])
对于累积乘积,您可以诉诸numpy
之类的库,该库具有矢量化(即really fast)函数cumprod
和prod
。例如,
import numpy as np
>>> np.cumprod([1,2,3,4,5])
array([ 1, 2, 6, 24, 120])
和
>>> np.prod([1,2,3,4,5])
120
当然,将虚拟[1,2,3,4,5]
替换为相应切片(例如s
)的s[:13]
答案 3 :(得分:1)
如果您要问如何简化s[i]*s[i+1]*s[i+2]*s[i+2]
,则可以将product
函数与列表切片一起使用。我从What's the function like sum() but for multiplication? product()?
from functools import reduce # Valid in Python 2.6+, required in Python 3
import operator
def product(sequence):
reduce(operator.mul, sequence, 1)
n="7316717653..." # there are 1000 digits
(https://projecteuler.info/problem=8)
s=[int(s) for s in n]
highest = s[0]
for i in range(1, len(s)-3):
highest = max(highest, product(s[i:i+4]))
print(highest)
但是,如果您正在寻找性能优化,那不是做到这一点的方法。这是O(n*m)
,其中m
是要相乘的子序列的长度,但是您可以利用以下事实:在转到下一个切片时,将当前乘积除以过去,然后乘以您要添加的元素,以获得O(n)
算法。
highest = product(s[0:4])
for i in range(len(s)-5):
highest = max(highest, highest/s[i]*s[i+4]))
print(highest)
哎呀,如果有0
位数字,则第二种方法不起作用。处理该问题会使其复杂化。
答案 4 :(得分:1)
尽管不如@Thierry提供的简单解决方案那么漂亮,但此解决方案的速度明显更快(约5倍)。因为包含零使乘积为零,所以我在此字符上拆分了文本。在使用reduce
获得前13个字符的乘积后,我然后通过新数字与下降的乘数之比来更新此乘积。该产品始终根据全局最大值进行测试。
big_number = '7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450'
n = 13
global_max = 0
for chunk in big_number.split('0'):
if len(chunk) < n:
continue
product = reduce(lambda x, y: x * int(y), chunk[:n], 1) # Product of first `n` integers in `chunk`.
global_max = max(global_max, product)
for i in range(n, len(chunk)):
product *= (int(chunk[i]) / int(chunk[i - n])) # Rolling product of window size `n`.
if product > global_max:
global_max = product
>>> int(global_max)
23514624000
时间
%%timeit -n 1000 # Code above.
# 437 µs ± 76.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit -n 1000
s = [int(s) for s in big_number]
maxi = max(reduce(mul, s[i:(i + 13)]) for i in range(len(s) - 13))
# 2.46 ms ± 916 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# Using numpy.
%%timeit -n 1000
n_as_nparray = np.array([int(character) for character in big_number])
every_thirteen_char = np.array([n_as_nparray[i:(i + 13)] for i in range(len(big_number) - 13)])
every_thirteen_char.prod(axis=1).max()
# 2.81 ms ± 418 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# Using pandas with a rolling window.
%%timeit -n 100
s = pd.Series([int(c) for c in big_number])
s.rolling(window=13, min_periods=1).apply(np.prod, raw=True).max().astype(int)
# 8.06 ms ± 830 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
答案 5 :(得分:0)
您要查找的if-condition-shortener是functools.reduce
和operator.mul
以及字符串切片的组合:
m = functools.reduce(operator.mul, s[i:i+13])
if m > Max:
Max = m
别忘了import functools
和operator