用Prolog/clpfd求解工程中的Euler#303
这里是“小数字的倍数” 对于正整数n,定义f(n)为n的最小正倍数,以10为底,仅使用数字≤ 二, 因此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(n,fn):- F#>0, FN#=F*N, 长度(Ds,u), (Ds,FN), Ds ins 0..2, 标记([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_-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 我能做些什么来应对上述挑战“find:sum(n=1到10000)(f(n)/n)” 如何在合理的时间内解决更多更大的实例用Prolog/clpfd求解工程中的Euler#303,prolog,clpfd,Prolog,Clpfd,这里是“小数字的倍数” 对于正整数n,定义f(n)为n的最小正倍数,以10为底,仅使用数字≤ 二, 因此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.
请和我分享你的想法!提前谢谢你 在9点时速度慢,而且有一种模式。。 所以 但我相信让序言找到这种模式并调整搜索会更好。。不知道你会怎么做
一般来说,它必须重新计算大量结果。它在9的速度很慢,并且有一个模式。。 所以 但我相信让序言找到这种模式并调整搜索会更好。。不知道你会怎么做
一般来说,它必须重新计算大量结果。我无法发现此问题的重复关系。所以,一开始我认为回忆录可以加快速度。不是真的 这段代码基于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
我找不出这个问题的递归关系。所以,一开始我认为回忆录可以加快速度。不是真的 这段代码基于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
好啊但是为什么在这些情况下它会变慢。。。因为f(n)有很多数字?顺便说一句,使用时保持稳定!一般的经验法则是,在剪切之前进行“输入统一”和测试,然后才进行“输出统一”。你的意思是。。n_fn(9,X):-!,X=12222。etc更好?没错<代码>n_fn(91231)应尽快失败。与
n_fn(912222):-代码>这不会发生。在这种情况下,只会浪费一些CPU周期。一般来说(用红色切割),程序的正确性受到威胁!好啊但是为什么在这些情况下它会变慢。。。因为f(n)有很多数字?顺便说一句,使用时保持稳定!一般的经验法则是,在剪切之前进行“输入统一”和测试,然后才进行“输出统一”。你的意思是。。n_fn(9,X):-!,X=12222。etc更好?没错<代码>n_fn(91231)
应尽快失败。与n_fn(912222):-代码>这不会发生。在这种情况下,只会浪费一些CPU周期。一般来说(用红色切割),程序的正确性受到威胁!