此处出现Project Euler Problem 303,“带小数字的倍数”。
对于正整数n,将f(n)定义为n的最小正数,用基数10表示,仅使用数字≤2。
因此f(2)= 2,f(3)= 12,f(7)= 21,f(42)= 210,f(89)= 1121222。
这是我已编写/我想改进的代码:
:- use_module(library(clpfd)). n_fn(N,FN) :- F #> 0, FN #= F*N, length(Ds, _), digits_number(Ds, FN), Ds ins 0..2, labeling([min(FN)], Ds).
该代码已经可用于解决少量小问题实例:
?- n_fn(2,X). X = 2 ?- n_fn(3,X). X = 12 ?- n_fn(7,X). X = 21 ?- n_fn(42,X). X = 210 ?- n_fn(89,X). X = 1121222
我可以做些什么来解决上述挑战“发现:总和(n = 1到10000)(f(n)/ n)”?
如何在合理的时间内解决更多更大的实例?
请与我分享您的想法!提前谢谢!
答案 0 :(得分:2)
9点慢,有一个模式.. 所以..
n_fn(9,12222):-!.
n_fn(99,1122222222):-!.
n_fn(999,111222222222222):-!.
n_fn(9999,11112222222222222222):-!.
但我相信让prolog找到这个模板并调整搜索会更好..不知道你会怎么做!
一般来说,它必须重新计算很多结果。
答案 1 :(得分:2)
我无法发现此问题的重现关系。所以,最初我认为记忆可以加快速度。不是......
此代码基于clp(fd),比你的......
略快n_fn_d(N,FN) :-
F #> 0,
FN #= F*N,
digits_number_d([D|Ds], Ts),
D in 1..2,
Ds ins 0..2,
scalar_product(Ts, [D|Ds], #=, FN),
labeling([min(FN)], [D|Ds]).
digits_number_d([_], [1]).
digits_number_d([_|Ds], [T,H|Ts]) :-
digits_number_d(Ds, [H|Ts]), T #= H*10.
当我使用clp(fd)来解决Euler的问题时,我偶然发现性能不佳......有时候,简单的“生成和测试”与本机算法结合起来会产生影响。
这个更简单,'原生'基于:
n_fn_e(N,FN) :-
digits_e(FN),
0 =:= FN mod N.
digits_e(N) :-
length([X|Xs], _),
maplist(code_e, [X|Xs]), X \= 0'0,
number_codes(N, [X|Xs]).
code_e(0'0).
code_e(0'1).
code_e(0'2).
它的速度更快:
test(N) :-
time(n_fn(N,A)),
time(n_fn_d(N,B)),
time(n_fn_e(N,C)),
writeln([A,B,C]).
?- test(999).
% 473,671,146 inferences, 175.006 CPU in 182.242 seconds (96% CPU, 2706593 Lips)
% 473,405,175 inferences, 173.842 CPU in 178.071 seconds (98% CPU, 2723188 Lips)
% 58,724,230 inferences, 25.749 CPU in 26.039 seconds (99% CPU, 2280636 Lips)
[111222222222222,111222222222222,111222222222222]
true