【发布时间】:2012-09-30 01:45:24
【问题描述】:
问题
what is the best way to generate a cartesian product of some lists, not knowing in advance how many lists there are?
如果你喜欢,你可以停止阅读这里。
背景
我没有钱上学,所以我想自学一些编程 在高速公路收费站上夜班时使用互联网。我有 决定尝试解决一些“编程挑战”问题作为练习。
编程作业
这是我要解决的问题,TopCoder 的属性:
http://community.topcoder.com/stat?c=problem_statement&pm=3496
我不会复制和粘贴完整的描述以尊重他们的版权声明 但我假设我可以总结它,前提是我不逐字使用它 (虽然是 IANAL)。
总结
如果历史股票价格的“加权总和”是获得的附录的总和 通过将这些价格的一个子集乘以相等数量的“权重” 因子,前提是后者加起来为 1.0 并从给定集合中选择 的有效值 [-1.0, -0.9, ..., 0.9, 1.0],请在所有 作为函数参数提供的历史数据,检查 5 个价格 一次,预测下一个价格并返回“加权排列” 因素”,产生最低的平均预测误差。至少会有 每次运行 6 个股票价格,因此至少可以保证一个预测,最终 结果应在 1E-9 范围内准确。
测试数据
格式:
- 一行输入数据,
list格式 - 预期结果一行
- 一个空行作为分隔符
下载自:
我的解决方案
import itertools
# For a permutation of factors to be used in a weighted sum, it should be chosen
# such than the sum of all factors is 1.
WEIGHTED_SUM_TOTAL = 1.0
FACTORS_CAN_BE_USED_IN_WEIGHTED_SUM = lambda x: sum(x) == WEIGHTED_SUM_TOTAL
# Historical stock price data should be examined using a sliding window of width
# 5 when making predictions about the next price.
N_RECENT_PRICES = 5
# Valid values for weighting factors are: [-1.0, -0.9, ..., 0.9, 1.0]
VALID_WEIGHTS = [x / 10. for x in range(-10, 11)]
# A pre-calculated list of valid weightings to consider. This is the cartesiant
# product of the set of valid weigths considering only the combinations which
# are valid as components of a weighted sum.
CARTESIAN_PRODUCT_FACTORS = [VALID_WEIGHTS] * N_RECENT_PRICES
ALL_PERMUTATIONS_OF_WEIGHTS = itertools.product(*CARTESIAN_PRODUCT_FACTORS)
WEIGHTED_SUM_WEIGHTS = filter(FACTORS_CAN_BE_USED_IN_WEIGHTED_SUM,
ALL_PERMUTATIONS_OF_WEIGHTS)
# Generator function to get sliding windows of a given width from a data set
def sliding_windows(data, window_width):
for i in range(len(data) - window_width):
yield data[i:i + window_width], data[i + window_width]
def avg_error(data):
# The supplied data will guarantee at least one iteration
n_iterations = len(data) - 5
best_average_error = None
# Consider each valid weighting (e.g. permutation of weights)
for weighting in WEIGHTED_SUM_WEIGHTS:
# Keep track of the prediction errors for this weighting
errors_for_this_weighting = []
for historical_data, next_to_predict in sliding_windows(data,
N_RECENT_PRICES):
prediction = sum([a * b for a, b in zip(weighting, historical_data)])
errors_for_this_weighting.append(abs(next_to_predict - prediction))
average_error = sum(errors_for_this_weighting) / n_iterations
if average_error == 0: return average_error
best_average_error = (average_error if not best_average_error else
min(average_error, best_average_error))
return best_average_error
def main():
with open('data.txt') as input_file:
while True:
data = eval(input_file.readline())
expected_result = eval(input_file.readline())
spacer = input_file.readline()
if not spacer:
break
result = avg_error(data)
print expected_result, result, (expected_result - result) < 1e-9
if __name__ == '__main__':
main()
我的问题
我不是要求对我的解决方案进行代码审查,因为这将是错误的 StackExchange 论坛。在这种情况下,我会将我的解决方案发布到“代码审查”。
相反,我的问题很小、准确且明确,符合本网站的格式(希望如此)。
在我的代码中,我使用 itertools 生成列表的笛卡尔积。本质上,我并没有自己解决问题的症结,而是将解决方案委托给为我做这件事的图书馆。如果我想从这些练习中学习,我认为这是错误的做法。我应该自己做最难的部分,否则为什么要锻炼呢?所以我想问你:
what is the best way to generate a cartesian product of some lists, not knowing in advance how many lists there are?
这就是我想知道的全部内容,如果您愿意,可以批评我的代码。这很受欢迎,即使它通过了所有测试(总是有更好的做事方式,特别是如果你是像我这样的初学者)但是对于这个问题对于 SO来说“恰到好处”,我只关注一个方面代码,我遇到的一个具体问题和我不满意的事情。让我告诉你更多,我也会分享规范的“你已经尝试过什么”......
很明显,如果我知道列表的数量,我可以输入一些嵌套的 for 循环,就像本练习的顶级求解器在比赛中所做的那样。我尝试编写一个函数来为 unknown 数量的列表执行此操作,但我不确定采用哪种方法。第一种方法是编写递归函数。从列表 1 中取出元素 1 并将其与列表 2 的元素 1 和列表 3 的元素 1 组合,等等。我会将每个“层”中的元素推入堆栈,并在达到所需深度时弹出它们。我想我不会担心“堆栈溢出”,因为可达到的深度是合理的。然后,我努力选择一种数据结构,以尽可能最有效(内存/空间)的方式执行此操作,而不向递归调用传递太多参数。数据结构是否应该存在于调用之外?在通话中被传递?我能达到任何水平的并行性吗?如何?有这么多的问题和这么少的答案,我意识到我需要知道更多来解决这个问题,我可以在正确的方向上轻推。你可以提供一个代码 sn-p 我会研究它。或者只是向我解释处理此类问题的正确“计算机科学”方式是什么。我确信有些事情我没有考虑。
最后,我在上面的解决方案中做考虑的是,谢天谢地 filter 过滤了一个生成器,因此完整的笛卡尔积永远不会保存在内存中(就像我做了一个 list(ALL_PERMUTATIONS_OF_WEIGHTS ) 在代码中的任何时间) 所以我只为那些实际上可以用作加权和的组合占用内存空间。如果应用于任何允许我生成笛卡尔积的系统而不使用 itertools,类似的警告会很好。
【问题讨论】:
-
你需要递归。查看DFS。
-
您所说的“最佳”最简单、最快是什么意思?
标签: python