我需要创建一个接收数字列表的谓词,并仅打印以7结尾的数字,并且其数字之和大于100
我使谓词分离,但我需要帮助建立两个谓词的联合,我的意思是两个谓词只进入一个谓词,这是我到目前为止所做的:
%sum of digits greater than 100
multi(X):-
0 is X mod 100
sum([],0).
sum([P|Q],Z).
multi(P), sum(Q,Z1), Z is P + Z1.
sum([P|Q],Z).
not multi(P), sum(Q,Z).
%print the numbers that end in 7
end(Y):-
7 is Y mod 10.
listend([],0).
listend([P|Q]):-
end(P),write(P), nl, listend(Q).
listend([P|Q]):-
not(end(P)), listend(Q).
答案 0 :(得分:4)
使用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).
一些简单的查询 1 :
?- 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 ...
现在,进入&#34;过滤&#34;你的问题的一部分......它就像 1,2,3 一样简单。
首先,我们根据(@)/1
定义(@)/2
。它适合reification scheme(if_/3
,(=)/3
等)已经已用于很多logically-pure Prolog answers on StackOverflow.
@(G_0, T) :- @var(T), @G_0, T = true.
其次,我们定义了clpfd谓词(#=)/2
和(#>)/2
的具体版本。
#=(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)
答案 1 :(得分:2)
这对我有用:
?- filter([147, 24, 57, 17, 3667], X), write(X), nl, fail.
sumdigits(0, 0).
sumdigits(X, Z) :-
X > 0,
Z1 is X mod 10,
X2 is X // 10,
sumdigits(X2, Z2),
Z is Z1 + Z2.
filter([], []).
filter([H|X], [H|Y]) :-
sumdigits(H, D),
D > 10,
7 is H mod 10, !,
filter(X, Y).
filter([_|X], Y) :- filter(X, Y).
我明白了:
[147, 57, 3667]
No.
我认为你的意思是数字的总和大于10而不是100。