朱利安的做法是什么?as python do产生收益(和收益率)?
编辑:我将尝试在python中添加小例子。
想想4x4棋盘。找到每一个N动作长路棋王可以做到的。不要浪费记忆 - >制作每条路径的发电机。
如果我们用数字签署每个位置:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 16
点0有3个邻居(1,4,5)。我们可以为每个点找到每个邻居的表格:
NEIG = [[1, 4, 5], [0, 2, 4, 5, 6], [1, 3, 5, 6, 7], [2, 6, 7], [0, 1, 5, 8, 9], [0, 1, 2, 4, 6, 8, 9, 10], [1, 2, 3, 5, 7, 9, 10, 11], [2, 3, 6, 10, 11], [4, 5, 9, 12, 13], [4, 5, 6, 8, 10, 12, 13, 14], [5, 6, 7, 9, 11, 13, 14, 15], [6, 7, 10, 14, 15], [8, 9, 13], [8, 9, 10, 12, 14], [9, 10, 11, 13, 15], [10, 11, 14]]
递归函数(生成器)从点列表或从(...的生成器)点的生成器放大给定路径:
def enlarge(path):
if isinstance(path, list):
for i in NEIG[path[-1]]:
if i not in path:
yield path[:] + [i]
else:
for i in path:
yield from enlarge(i)
函数(生成器)给出具有给定长度的每个路径
def paths(length):
steps = ([i] for i in range(16)) # first steps on every point on board
for _ in range(length-1):
nsteps = enlarge(steps)
steps = nsteps
yield from steps
我们可以看到有905776个长度为10的路径:
sum(1 for i in paths(10))
Out[89]: 905776
在ipython中我们可以计时:
%timeit sum(1 for i in paths(10))
1.21 s ± 15.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我的朱莉娅实施丑陋而且复杂得多。而且似乎更慢。
答案 0 :(得分:3)
using ResumableFunctions
@resumable function fibonnaci(n::Int) :: Int
a = 0
b = 1
for i in 1:n-1
@yield a
a, b = b, a+b
end
a
end
for fib in fibonnaci(10)
println(fib)
end
答案 1 :(得分:1)
您可以使用频道:
function fibo(n)
Channel() do ch
a, b = 0, 1
for _ in 1:n
a, b = b, a + b
put!(ch, a)
end
end
end
像这样使用它:
for val in fibo(10)
print(val, " ")
end
输出:
1 1 2 3 5 8 13 21 34 55
要获得 yield from
行为,您可以只使用 for
循环。例如,要获得斐波那契数列 r
次:
function repeat_fibo(r, n)
Channel() do ch
for _ in 1:r
for val in fibo(n)
put!(ch, val)
end
end
end
end
有关详细信息,请参阅 docs。
请注意,ResumableFunctions.jl 库的一些基准测试表明,他们的解决方案比使用 Channels 快得多(参见 @gggg's answer)。也许频道性能会在未来的 Julia 版本中得到改善。
为了获得更好的频道性能,您应该设置频道的元素类型和频道的大小:例如,使用 Channel{Int64}(100)
而不是 Channel()
。
这是使用 Channels 解决国际象棋问题的 Julia 实现:
NEIG = [[1, 4, 5], [0, 2, 4, 5, 6], [1, 3, 5, 6, 7], [2, 6, 7], [0, 1, 5, 8, 9],
[0, 1, 2, 4, 6, 8, 9, 10], [1, 2, 3, 5, 7, 9, 10, 11], [2, 3, 6, 10, 11],
[4, 5, 9, 12, 13], [4, 5, 6, 8, 10, 12, 13, 14],
[5, 6, 7, 9, 11, 13, 14, 15], [6, 7, 10, 14, 15], [8, 9, 13],
[8, 9, 10, 12, 14], [9, 10, 11, 13, 15], [10, 11, 14]]
function paths(start, length)
Channel{Vector{Int64}}(100) do ch
if length == 1
put!(ch, [start])
else
for path in paths(start, length - 1)
for next_step in NEIG[path[end] + 1]
next_step in path || put!(ch, [path; next_step])
end
end
end
end
end
function paths(length)
Channel{Vector{Int64}}(100) do ch
for start in 0:15
for path in paths(start, length)
put!(ch, path)
end
end
end
end
您可以像在 Python 中一样计算所有长度为 10 的路径:
sum(1 for _ in paths(10))
你也可以计时:
@time sum(1 for _ in paths(10))
在我的机器上,这大约需要 4 秒。可能有进一步优化的方法,但这确实表明渠道性能仍有一些改进空间。
答案 2 :(得分:0)
您可以使用 Julia Iterators。
struct Fibonacci
last::Int64
end
function Base.iterate(fibo::Fibonacci)
return 1, (1, 1, 2) # the first output, and the next iteration state
end
function Base.iterate(fibo::Fibonacci, state)
i, a, b = state
if i ≤ fibo.last
return a, (i + 1, b, a + b) # the output, and the next iteration state
end
end
然后你可以像这样使用它:
for i in Fibonacci(10)
print(i, " ")
end
输出:
1 1 2 3 5 8 13 21 34 55 89
这可以带来出色的性能,但通常有点冗长,而且决定使用哪种迭代状态以及如何找到给定该状态的下一个元素也很棘手。在您的国际象棋示例中,我会避免使用这种方法,但在其他情况下,它会派上用场。