因此,我在这段代码中的主要目标是检查随机生成的数字(s
)是否大于随机生成的数字列表中的任何其他组成部分。如果是这种情况,那么应该将检查过的数字添加到标记为“已用”的单个随机生成的数字中,并从列表中退出,然后该过程应该再次开始。在有两个或更多的数字低于单个随机生成的数字的情况下,这两个数字都应该被“标记”并从列表中退出,但只有两个数字中最大的一个应该添加到单个生成的数字中,以便下一次循环。最后,它应该说明需要多少次循环才能使列表中的所有随机数“标记”并使用,或者循环通过而没有任何数字被“标记”。
由于这个解释可能不清楚,我将在这里举一个例子。假设生成的单个数字(s
)为0.2,而随机生成的数字列表为(0.2,0.3,0.4,0.5)。该算法首先将s
与0.2进行比较,当它相等时,s
将变为0.2 + 0.2 = 0.4,0.2将被“标记”并从池中退出,新的循环将开始。在下一个循环中,算法将检查0.3和0.4是否都等于或小于新的s
( 0.4 ),因此两者都将被“标记”,退役,并且s
将变为0.2 +0.4= 0.6。在最后一个周期中,0.5将被标记并退役,s
将变为0.2 + 0.5 = 0.7,需要3个循环来标记所有数字。
到目前为止,我已经想出了这个(请忽略关于随机数生成的规范)
import random
import numpy as np
for x in range(0, 101):
s = random.gauss(0.5, 1)
s = round(s, 2)
if s < 0:
s = 0
if s > 1:
s = 1
print("This is S")
print(s)
ai = []
ai_size = 10
for i in range(ai_size):
num = float(random.gauss(0.5,1))
num = round(num, 2)
if num < 0:
num = 0
if num > 1:
num = 1
ai.append(num)
print("This is the vector of Ai")
print(ai)
ai = sorted(ai)
print("This is the vector numerically ordered")
print(ai)
ai_mean = (np.mean(ai))
ai_var = (np.var(ai))
print(ai_mean)
print(ai_var)
rev = 0
loop = 0
for i in ai:
if s >= i:
s += i
rev += 1
loop += 1
print("This is evolving S")
print(s)
else:
break
print("Loop is over")
print("This is the number of elements within the list that are marked")
print(rev)
print("This is the number of loops")
print(loop)
ai_percentage = rev / ai_size * 100
print("This is the percentage")
print(ai_percentage)
这段代码的问题主要是,当在任何给定的循环中有多个应该标记和退出的数字时,它只会在进入下一个循环之前检查第一个数字,这意味着它总是以相同数量的循环和已经标记的数字结束(而在许多情况下,循环的数量应该更少)。它还使S成为所有标记数字的连续和(在前面的示例中,它将执行0.2 + 0.2 + 0.3 + 0.4 + 0.5),而不是保持原始S不变,只添加最高标记数字,正如我之前在示例中所解释的那样。
任何关于这方面的想法或技巧都将不胜感激。
发布于 2020-08-28 19:42:00
所以这个问题有两个部分:
让我们先从概念上解决你提到的连续求和问题。因为我们不想不断地对它们求和,所以我们必须保留两个不同的部分,“基数”和“增量”。我将使用base_s
作为基础,使用delta_s
作为增量:
import random
import numpy as np
for x in range(0, 101):
base_s = random.gauss(0.5, 1)
base_s = round(s, 2)
if base_s < 0:
base_s = 0
if base_s > 1:
base_s = 1
delta_s = 0.0
print("This is S")
print(base_s + delta_s)
# ...
rev = 0
loop = 0
for i in ai:
if base_s + delta_s >= i:
delta_s = i
rev += 1
loop += 1
print("This is evolving S")
print(base_s + delta_s)
else:
break
# ...
现在我们已经解决了小部分,让我们关注如何处理同时验证条件的多个元素。首先,python有一个名为filter
的内置函数,它允许我们获得验证某些条件的序列的一部分。filter
的第一个参数是一个将为每个元素调用的函数,如果返回True
,则包含该元素,否则将忽略该元素。list(filter(lambda x: x <= base_s + delta_s, ai))
将返回[0.2]
。list(...)
将把它转换回一个列表,因为它返回一种特殊类型的序列,而lambda x: x <= base_s + delta_s
只是一种定义函数的内联方式,对于小于或等于s(基加增量)的元素,该函数返回true。
现在让我们把它变成一个有用的函数。它将执行单循环迭代,因此我们将其称为iterate
。第一个参数是数字列表,第二个参数是基数S,第三个参数是增量S(默认为0.0)。我们还将使用循环和rev count (默认为1)作为第四个和第五个参数。它将返回剩余的项、最后的s以及循环和转速计数器。
def iterate(items, base_s, delta_s=0.0, loop=0, rev=0):
# Compute s
s = base_s + delta_s
# Get the elements lower or equal to S
extracted = list(filter(lambda x: x <= s, items))
# If there are no elements, we don't have to iterate any longer
if len(extracted) == 0:
return items, s, loop, rev
# Remove the lower or equal elements
items = list(filter(lambda x: x > s, items))
# Find the biggest extracted element as this will be the new delta_s
delta_s = max(extracted)
# Update loop and rev counters
loop += 1
rev += len(extracted)
# Once everything is updated we can call the same function again to do another loop
return iterate(items, base_s, delta_s, loop, rev)
我们已经有了我们的函数,当调用一次时,它会根据需要进行任意多次的迭代。这些函数之所以被称为递归函数,是因为它们调用自己。第一个iterate
调用将调用第二个,依此类推,当一个调用到达if len(extracted) == 0
时,这意味着不需要进行迭代,接下来的调用将一个接一个地返回,以给出最终结果。
它实际上可以变得更短(我保留了更长的时间,以便更容易理解):
def iterate(items, base_s, delta_s=0.0, loop=0, rev=0):
s = base_s + delta_s
extracted = list(filter(lambda x: x <= s, items))
if len(extracted) == 0:
return items, s, loop, rev
return iterate(list(filter(lambda x: x > s, items)), base_s, max(extracted), loop + 1, rev + len(extracted))
要使用它来解决您的示例,您可以调用:
remaining_items, s, loop, rev = iterate([0.2, 0.3, 0.4, 0.5], 0.2)
我留下你的练习,把它引入你的代码,如果你发现它有任何问题,请留下评论,我会帮助你的。
https://stackoverflow.com/questions/63632212
复制相似问题