仅显示一些有效的表达式

时间:2016-08-20 03:41:50

标签: prolog

我有一些事实:

num(one)
num(two)
num(three)

然后我有一个谓词:

validValue(value(Num, Num1, Num2, Num2, Num4)) :-
num(Num), num(Num1), num(Num2), num(Num3), num(num4).

我现在想编写一个输出有效

的查询
value(num,num1,num2,num3,num4) 

但我希望它只显示带有num(两个)和num(三个)的有效输出。 例如,有效:

value(two,one,one,one,three) 

无效

value(two,one,one,one,one)

我的思路是将X指定为两个,Y指定为三个,或者其他类似的指定并使用

validValue(value(X)).

但这显然只等于:

validValue(value(two)).

任何人都能告诉我我做错了什么? 非常感谢,谢谢。

2 个答案:

答案 0 :(得分:3)

在“生成和测试”方法中,您需要测试某个术语的参数是否适用。

对于列表,这很容易。要说List至少包含Element中的一个,您可以使用memberchk/2

memberchk(Element, List)

您还可以使用univ运算符=../2从术语的参数中创建列表:

Value =.. [value|Vs]

换句话说,你可以写:

is_valid(Value) :-
    Value =.. [value|Vs],
    memberchk(two, Vs), memberchk(three, Vs).

唯一的好处是,如果术语更改arity(突然间你有一个或多或少的值),则不必重新编写谓词。

要创建一个谓词,检查列表的每个成员是否至少出现一次作为术语中的参数,您可以写:

any_nums_value(Nums, Value) :-
    Value =.. [value|Vs],
    member(N, Nums),
    memberchk(N, Vs).

然后:

% generate
?- valid(V).
V = value(one, one, one, one, one) ;
V = value(one, one, one, one, two) ;
V = value(one, one, one, one, three) ;
V = value(one, one, one, two, one) .

% generate and test
?- valid(V), any_nums_value([two, three], V).
V = value(one, one, one, one, two) ;
V = value(one, one, one, one, three) ;
V = value(one, one, one, two, one) ;
V = value(one, one, one, two, two) .

在上面的any_nums_value/2中,联合member(N, Nums), memberchk(N, Vs)表示:

  

Nums中有Vs成员至少出现一次Nums

如果你需要说:

  

Vs的每位成员至少在all_nums_value(Nums, Value) :- Value =.. [value|Vs], maplist(list_check_member(Vs), Nums). list_check_member(List, Member) :- memberchk(Member, List).

中出现一次

然后你需要写:

list_check_member/2

maplist是必要的,以便参数顺序适合?- valid(V), all_nums_value([two, three], V). V = value(one, one, one, two, three) ; V = value(one, one, one, three, two) ; V = value(one, one, two, one, three) ; V = value(one, one, two, two, three) . % and so on 的工作方式。

然后:

valid/1

顺便说一下,我已将valid(value(A,B,C,D,E)) :- maplist(num, [A,B,C,D,E]). 定义为:

valid_n(V, N) :-
    length(Vs, N),
    maplist(num, Vs),
    V =.. [value|Vs].


?- valid_n(V, 3).
V = value(one, one, one) ;
V = value(one, one, two) ;
V = value(one, one, three) ;
V = value(one, two, one) .
% and so on

?- valid_n(V, 10).
V = value(one, one, one, one, one, one, one, one, one, one) .
% and so on

如果你想制作lentgth N的有效值,你可以写:

>>> from unidecode import unidecode
>>> unidecode('serhat kılıç')
'serhat kilic'
>>> unidecode('serhat kilic')
'serhat kilic'
>>> # as a bonus it does much more, like
>>> unidecode('北亰')
'Bei Jing '

答案 1 :(得分:2)

Soo如果我理解正确的话会这样:

%% facts
num(one).
num(two).
num(three).

two(two).
three(three).

%% rules
validValue(Val) :-
    contains_two(Val),
    contains_three(Val),
    valid_numbers(Val).

valid_numbers(value(Num, Num1, Num2, Num3, Num4)):-
    num(Num),
    num(Num1),
    num(Num2),
    num(Num3),
    num(Num4).


contains_two(value(Num, Num1, Num2, Num3, Num4)):-
    two(Num);
    two(Num1);
    two(Num2);
    two(Num3);
    two(Num4).

contains_three(value(Num, Num1, Num2, Num3, Num4)):-
    three(Num);
    three(Num1);
    three(Num2);
    three(Num3);
    three(Num4).


test:-
    validValue(value(two,one,one,one,three)),
\+ validValue(value(two,one,one,one,one)).

这将验证包含三和二的所有值,并且所有数字都是有效数字。

您还可以进行查询以查找有效数字,例如:

?- validValue(value(Num, Num1, Num2, Num3, Num4)).
Num = two,
Num1 = three,
Num2 = Num3, Num3 = Num4, Num4 = one 

如果您想要所有可能的数字,可以查询:

?- findall(X, validValue(X), Result).
Result = [value(two, three, one, one, one), value(two, three, one, one, two), value(two, three, one, one, three), value(two, three, one, two, one), value(two, three, one, two, two), value(two, three, one, two, three), value(two, three, one, three, one), value(two, three, one, three, two), value(..., ..., ..., ..., ...)|...].