我正在解决项目Euler问题(在我学习C#之前做了23个第一个问题)而且我对我解决问题5的性能低下来感到困惑.
其内容如下:
2520是可以除以1到10中的每个数字而没有任何余数的最小数字.
可以被1到20的所有数字整除的最小正数是多少?
现在我的C#令人难以置信的原始蛮力解决方案在大约25秒内完成了这个问题.
var numbers = Enumerable.Range(1, 20);
int start = 1;
int result;
while (true)
{
if (numbers.All(n => start % n == 0))
{
result = start;
break;
}
start++;
}
Run Code Online (Sandbox Code Playgroud)
现在我的F#解决方案也使用暴力强制,但至少它会有更多的歧视,所以它"应该"在我的脑海中运行得更快,但它在约45秒时出现,所以它几乎是C#的两倍慢.
let p5BruteForce =
let divisors = List.toSeq ([3..20] |> List.rev)
let isDivOneToTwenty n =
let dividesBy =
divisors |> Seq.takeWhile(fun x -> n % x = 0)
Seq.length dividesBy = Seq.length divisors
let findNum n =
let rec loop n =
match isDivOneToTwenty n with
| true -> n
| false -> loop (n + 2)
loop n
findNum 2520
Run Code Online (Sandbox Code Playgroud)
PS - 我知道我的解决方案可能会更好,在这种情况下,我只是想知道一个更好的蛮力解决方案可能比原始解决方案慢得多.
Lee*_*Lee 11
您可以使用List.forall而不是转换为seq然后执行Seq.length:
let divisors = [3..20] |> List.rev
let isDivOneToTwenty n = divisors |> List.forall (fun d -> n % d = 0)
Run Code Online (Sandbox Code Playgroud)
Seq.length将需要遍历整个序列以确定元素的数量,同时forall可以在元素未通过谓词时返回.
你也可以这样写findNum:
let rec findNum n = if isDivOneToTwenty n then n else findNum (n + 2)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
655 次 |
| 最近记录: |