答案 0 :(得分:1)
答案 1 :(得分:0)
像Mark Hills这样的算法问题。在Rascal中,一些短代码仍然需要很多嵌套循环,几乎隐式。基本上,您在列表中的模式侧使用的新变量上的每个*
拼接运算符都会生成一个级别的循环嵌套,除了最后一个只是列表的其余部分。
在findClone2
的代码中,您首先生成所有子列表组合,然后使用if
构造过滤它们。这是一个正确的算法,但可能很慢。这是你的代码:
void findClone2(list[str] In, list[str] whatWeSearchFor)
{
for ([*str head, *str mid, *str end] := In)
if (mid == whatWeSearchFor)
println("gotcha");
}
您会看到它如何在In
上嵌套循环,因为它在模式中有两个有效的*
运算符。因此,代码在O(n^2)
中运行,其中n是In
的长度。即它具有In
列表大小的二次运行时行为。 In
是一个很重要的列表,所以这很重要。
在以下新代码中,我们首先使用较少的代码行生成答案时进行过滤:
public void findCloneLinear(list[str] In, list[str] whatWeSearchFor)
{
for ([*str head, *whatWeSearchFor, *str end] := In)
println("gotcha");
}
第二个*
运算符不会生成新循环,因为它不是新鲜的。它只是"粘贴"给定的列表值进入模式。所以现在实际上只有一个有效*
生成一个循环,它是head
上的第一个循环。这个使算法循环遍历列表。第二个*
测试whatWeSearchFor
之后的head
元素是否正好在whatWeSearchFor
之后(这是*_
的大小为线性,然后是最后{{1}只需完成列表即可完成更多内容。
了解克隆有时在哪里也很好:
public void findCloneLinear(list[str] In, list[str] whatWeSearchFor)
{
for ([*head, *whatWeSearchFor, *_] := In)
println("gotcha at <size(head)>");
}
Rascal没有一个优化编译器(可能)可能会在内部将您的算法转换为等效的优化算法。因此,作为Rascal程序员,您仍然需要知道循环对算法复杂性的影响,并且知道*
是一个非常简短的循环表示法。