使用clpfd!
:- use_module (library(clpfd)).
我們這樣做是這樣的:
n_base10(N, Ds) :-
n_base_digits(N, 10, Ds).
n_base_digits(Expr, Base, Ds) :-
Base #> 1,
Ds = [_|_],
N #= Expr,
N #>= 0, % N is non-negative
n_base_ref_acc_digits(N, Base, Ds, [], Ds).
n_base_ref_acc_digits(N, Base, Ref, Ds0, Ds) :-
zcompare(Order, N, Base),
order_n_base_ref_acc_digits(Order, N, Base, Ref, Ds0, Ds).
order_n_base_ref_acc_digits(<, N, _, [_] , Ds0, [N|Ds0]).
order_n_base_ref_acc_digits(=, _, _, [_,_] , Ds0, [1,0|Ds0]).
order_n_base_ref_acc_digits(>, N, Base, [_|Rs], Ds0, Ds) :-
N0 #= N // Base,
N1 #= N mod Base,
n_base_ref_acc_digits(N0, Base, Rs, [N1|Ds0], Ds).
一些簡單的查詢:
?- n_base10(_, []).
false.
?- X #< 0, n_base10(X, Ds).
false.
?- n_base10(123, [1,2,3]).
true.
?- n_base10(123, Ds).
Ds = [1,2,3].
?- n_base10(N, [1,7,9]).
N = 179
; false.
?- n_base10(459183754813957135135239458256, Ds).
Ds = [4,5,9,1,8,3,7,5,4,8,1,3,9,5,7,1,3,5,1,3,5,2,3,9,4,5,8,2,5,6].
有關使用比其他10個基地如何?
?- member (Base,[2,8,10,16,36]), n_base_digits(N,Base,[1,2,3,4]).
Base = 8, N = 668
; Base = 10, N = 1234
; Base = 16, N = 4660
; Base = 36, N = 49360
; false.
?- member(Base,[2,8,10,16,36]), n_base_digits(101,Base,Ds).
Base = 2, Ds = [1,1,0,0,1,0,1]
; Base = 8, Ds = [1,4,5]
; Base = 10, Ds = [1,0,1]
; Base = 16, Ds = [6,5]
; Base = 36, Ds = [2,29].
好的!按預期工作。
讓我們找到數字總和大於100
和7
的整數作爲最不重要的十進制數字!
?- set_prolog_flag (toplevel_print_anon , false).
true.
?- _S #> 100,
n_base10(N, _Ds),
lists:last (_Ds, 7),
clpfd:sum (_Ds, #=, _S),
clpfd:labeling ([ff,min(N)], _Ds).
N = 499999999997
; N = 589999999997
; N = 598999999997
...
現在,你的問題的 「過濾」 的一部分......這是爲1,2,3一樣簡單。
首先,我們根據(@)/1
定義(@)/2
。它適合clpfd謂詞(#=)/2
和(#>)/2
的reification scheme(的if_/3
,(=)/3
等),已經已經在很多logically-pure Prolog answers on StackOverflow.
@(G_0, T) :- @var(T), @G_0, T = true.
二的被使用,我們定義具體化版本。
#=(X, Y, T) :- X #= Y #<==> B, bool01_t (B, T).
#>(X, Y, T) :- X #> Y #<==> B, bool01_t(B, T).
最後,使用Prolog lambdas,tfilter/3
和','/3
,我們來電諮詢:
?- use_module(library(lambda)).
true.
?- Zs0 = [ /* Es: list of sample integers */
499999999997, /* (digit sum = 101) */
9899999999970, /* (digit sum = 105) */
516666669999997, /* (digit sum = 103) */
5000007, /* (digit sum = 12) */
598999999997 /* (digit sum = 101) */
],
tfilter(\N^( /* N: candidate integer */
@n_base10(N, Ds), /* Ds: base-10 representation */
@lists:last (Ds, D1), /* D1: least significant digit */
D1 #= 7, /* D1: equal to 7 */
@clpfd:sum (Ds, #=, S), /* S: digit sum */
S #> 100 /* S: greater than 100 */
),
Zs0,
Zs).
Zs0 = [499999999997,9899999999970,516666669999997,5000007,598999999997],
Zs = [499999999997, 516666669999997, 598999999997].
就像一個魅力!
注:1:使用SWI-Prolog的7.3版本。10(64位AMD64)
程序文本中存在語法錯誤。 – repeat