我写了两个版本,一个在 C++ 中,使用动态编程/记忆,另一个在 Prolog 中,没有使用它,所以它们不能直接比较。
C++:
#include <iostream>
#include <vector>
const unsigned long N = 4294967296;
bool terminates(unsigned long x) { // x should be less than N
std::vector<bool> visited(N, false);
while(x != 77) {
if(visited[x])
return false;
visited[x] = true;
x = (x*12367+3466) % N;
}
return true;
}
int main() {
std::cout << terminates(819688) << std::endl; // prints 0
std::cout << terminates(955725) << std::endl; // prints 1
}
这在 7 秒内完成。
序言:
非记忆版本背后的想法是只循环N+1
步骤。如果它在那之前没有终止,它根本不会终止,因为只有N
状态。
terminates(X, R) :- terminates(X, 4294967297, R).
terminates(77, _, true) :- !.
terminates(_, 0, false) :- !.
terminates(_, I, false) :- I =< 0, !.
terminates(X, I, R) :-
I2 is I-1,
X2 is (X*12367+3466) mod 4294967296,
terminates(X2, I2, R).
这些查询中的第一个需要更长的时间:
?- terminates(819688, R).
R = false.
?- terminates(955725, R).
R = true.
table
显然,使用or可以在 Prolog 中进行assertz
记忆,但我认为你会比 C++ 更快地遇到内存问题。C++ 的vector<bool>
每个元素只使用 1 位!(unordered_map
在这里使用是错误的,因为它的查找速度较慢并且使用更多的内存)