0

我的程序中的上下文如下:我有一些students,一定的country和一定years的研究,在这个序言代码中如下:

student('Steve Morris').
student('Joe Jez').
student('Carlos Sethi').
student('Natasha Carter').

country('Steve Morris', usa).
country('Joe Jez', usa).
country('Carlos Sethi', usa).
country('Natasha Carter', france).

years('Steve Morris', 3).
years('Joe Jez', 1). 
years('Carlos Sethi', 4).
years('Natasha Carter', 4). 

scholarship(A) :- country(A,B), B = france.
scholarship(A) :- years(A,C), C > 2.

我想给我的一个学生一个而且只有一个奖学金。为此,我将使用一些提高“奖学金系数”的规则,获得更大奖学金系数的学生将获得奖学金

第一条规定学生必须来自法国,第二条规定学生必须有两年以上的学习。

所以,当我执行时scholarship(X),这就是我得到的:

?- scholarship(X).
X = 'Natasha Carter' ;    % Only student who matches the first rule
X = 'Steve Morris' ;      % All students from now on, match the second rule
X = 'Carlos Sethi' ;
X = 'Natasha Carter'.

话虽如此,我正在尝试做一个程序,试图获得最终获得奖学金的学生的名字。首先,我首先尝试执行一个谓词findall来过滤所有符合这些规则的学生,并将其放在一个列表中:

?- findall(X, scholarship(X), L).
L = ['Natasha Carter', 'Steve Morris', 'Carlos Sethi', 'Natasha Carter'].

这是一个预期的结果,因为使用scholarship(X).

现在,看起来我需要生成的列表来过滤结果并满足我正在寻找的内容。请记住,在上面的示例中,我期望达到的结果至少是一个表明学生及其奖学金因素的列表,如下所示(不一定准确):

[['Natasha Carter', 2], ['Steve Morris', 1], ['Carlos Sethi', 1]].

它是一种操纵 findall 生成的列表的方法吗?或者我当然需要另一种方法来解决这个问题?

编辑:问题建模有一点很重要:所有规则都具有相同的奖学金因子值,因此当学生满足一条规则时,无论哪一条,奖学金因子都应该上升到 1。

问题更新:感谢 Mog,我有一个解决问题的方法,msort/2使用辅助列表应用,这就是我所拥有的:

?- findall(X, scholarship(X), L), msort(L, L1).
L = ['Natasha Carter', 'Steve Morris', 'Carlos Sethi', 'Natasha Carter'],
L1 = ['Carlos Sethi', 'Natasha Carter', 'Natasha Carter', 'Steve Morris'].
4

2 回答 2

1

更简单的方法应该是增加scholarship(X)一个排名(我添加了规则'index'),然后使用 setof 得到一个排序列表,从低到高排名:

scholarship(1,A) :- country(A,B), B = france.
scholarship(2,A) :- years(A,C), C > 2.

?- setof(R-X, scholarship(R,X), L).

请注意,我利用 setof 执行的排序将列表元素更改为更有用的格式。

编辑:对不起,我提出了一个无用的修改。一个更合适的答案会建议

?- findall(N-X, (bagof(_, scholarship(X), T), length(T, N)), L).
L = [1-'Carlos Sethi', 2-'Natasha Carter', 1-'Steve Morris'].
于 2013-07-09T21:23:08.857 回答
0

我通过使用名为的注册表结构找到了自己的替代解决方案:

reg(C, N)

其中C是人名,N是人名出现在生成的列表中的次数findall(使用msort/2,对于此解决方案的效果,它仅用于排序目的)。

listsort(L1) :- findall(X, scholarship(X), L), msort(L, L1).

compress([],[]).
compress([X|Xs],Ys):-comp(Xs,X,1,Ys).

comp([],C,N,[reg(C,N)]).
comp([X|Xs],X,N,Ys):-N1 is N+1, comp(Xs,X,N1,Ys).
comp([X|Xs],Y,N,[reg(Y,N)|Ys]):-  X\=Y, comp(Xs,X,1,Ys).

predic(S2) :- listsort(S1), compress(S1, S2).

所以原始问题的输出看起来与提议的问题相似(唯一的区别是在原始问题中,注册表按以下顺序排序N

?- predic(K).
K = [reg('Carlos Sethi', 1), reg('Natasha Carter', 2), reg('Steve Morris', 1)] 
于 2013-07-15T03:16:41.317 回答