用Prolog/clpfd求解工程中的Euler#303

用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.

这里是“小数字的倍数”

对于正整数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)”

如何在合理的时间内解决更多更大的实例


请和我分享你的想法!提前谢谢你

在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周期。一般来说(用红色切割),程序的正确性受到威胁!