可以操作findall生成的列表吗?

时间:2013-07-09 21:09:26

标签: list prolog

上下文在我的计划中有以下内容:我有一些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'].

2 个答案:

答案 0 :(得分: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'].

答案 1 :(得分:0)

通过使用名为:

的注册表结构,我发现自己是另一种解决方案
reg(C, N)

其中C是此人的姓名,N是此人的姓名在findall生成的列表中显示的次数(使用{{1}对于此解决方案的效果,它仅用于订购目的)。

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