Prolog平均规则
Prolog Average Rules
以下一组 Prolog 规则适用于 average([3,4,5],A).
这样的输入,因此 A = 4.0
.
但是,如果我尝试类似 average([3,4,X],4).
的操作,以下错误是 returned:
average([X|Xs],A) :- sum([X|Xs],S), length([X|Xs],L), {S/L=A}.
ERROR: is/2: Arguments are not sufficiently instantiated
我如何修改我的代码以允许 average([3,4,X],4)
到 return X
的正确值?
库(clpqr)的简单解决方案:
add(A, B, +(A,B)).
list_average([X|Xs], A) :-
length([X|Xs], Len),
foldl(add, Xs, X, Sum),
{Sum =:= A*Len}.
如果由于某种原因你不想使用这个库,你可以试试下面的代码。
这可能会解决您的问题,但我对这段代码不满意。当然还有其他人知道得更多:
list_average(L, A) :-
( is_list(L)
-> length(L, Len),
term_variables(L-A, Vars),
solve(Vars, L, A, Len)
; instantiation_error(L)
).
solve([], L, A, Len) :-
sum_list(L, Sum),
A =:= Sum / Len. % Validate provided average
solve([X|Xs], L, A, Len) :-
partition(number, L, Nums, Vars),
length(Vars, T),
sum_list(Nums, Sum),
( var(A)
-> maplist(=(A), Vars), % all variables are as the average
A is Sum / (Len - T)
; maplist(=(X), Xs), % all free variables in list are same
X is (Len*A - Sum) / T
).
这样的查询是可能的:
?- list_average([2,3,4,5], A).
A = 3.5.
?- list_average([2,3,4,5], 3).
false.
?- list_average([2,X,4,5], 3).
X = 1.
?- list_average([2,X,4,Y], 3).
X = Y, Y = 3.
?- list_average([2,X,4,Y], A).
X = Y, Y = A, A = 3.
?- list_average([2,X,4,Y], 6).
X = Y, Y = 9.
在进行数值求解之前,它会自动尝试将所有自由变量绑定到一个自由变量。
它与 Boris 解决方案完全相同,但我使用库 lambda :
:- use_module(library(clpr)).
:- use_module(library(lambda)).
average(L, A) :-
length(L, Len),
foldl(\X^Y^Z^{Z = X+Y}, L, 0, TT),
{A * Len = TT}.
错误评论后编辑更正。
以下一组 Prolog 规则适用于 average([3,4,5],A).
这样的输入,因此 A = 4.0
.
但是,如果我尝试类似 average([3,4,X],4).
的操作,以下错误是 returned:
average([X|Xs],A) :- sum([X|Xs],S), length([X|Xs],L), {S/L=A}.
ERROR: is/2: Arguments are not sufficiently instantiated
我如何修改我的代码以允许 average([3,4,X],4)
到 return X
的正确值?
库(clpqr)的简单解决方案:
add(A, B, +(A,B)).
list_average([X|Xs], A) :-
length([X|Xs], Len),
foldl(add, Xs, X, Sum),
{Sum =:= A*Len}.
如果由于某种原因你不想使用这个库,你可以试试下面的代码。 这可能会解决您的问题,但我对这段代码不满意。当然还有其他人知道得更多:
list_average(L, A) :-
( is_list(L)
-> length(L, Len),
term_variables(L-A, Vars),
solve(Vars, L, A, Len)
; instantiation_error(L)
).
solve([], L, A, Len) :-
sum_list(L, Sum),
A =:= Sum / Len. % Validate provided average
solve([X|Xs], L, A, Len) :-
partition(number, L, Nums, Vars),
length(Vars, T),
sum_list(Nums, Sum),
( var(A)
-> maplist(=(A), Vars), % all variables are as the average
A is Sum / (Len - T)
; maplist(=(X), Xs), % all free variables in list are same
X is (Len*A - Sum) / T
).
这样的查询是可能的:
?- list_average([2,3,4,5], A).
A = 3.5.
?- list_average([2,3,4,5], 3).
false.
?- list_average([2,X,4,5], 3).
X = 1.
?- list_average([2,X,4,Y], 3).
X = Y, Y = 3.
?- list_average([2,X,4,Y], A).
X = Y, Y = A, A = 3.
?- list_average([2,X,4,Y], 6).
X = Y, Y = 9.
在进行数值求解之前,它会自动尝试将所有自由变量绑定到一个自由变量。
它与 Boris 解决方案完全相同,但我使用库 lambda :
:- use_module(library(clpr)).
:- use_module(library(lambda)).
average(L, A) :-
length(L, Len),
foldl(\X^Y^Z^{Z = X+Y}, L, 0, TT),
{A * Len = TT}.
错误评论后编辑更正。