尝试编写谓词gradeMap(L,R),其中L是百分比等级值列表,R是相应等级字母列表(a-f)

时间:2017-11-30 05:22:52

标签: prolog

我正在尝试创建一个谓词gradeMap(L,R),其中我提供了一个成绩列表,它返回一个包含映射成绩的列表R.我想这就像一张地图,我知道基本情况是什么,我知道如何递归,但我不知道如何处理每个百分比存储相应的字母等级。

代码是部分的,尚未完全实现(我被困住)。

 gradeMap(L,R).
 gradeMap([],[]). %base case 
 gradeMap([H|T],R):-
 %handle percentages
 recurse and add the grade to the list R

期望的输出:

?- gradeMap([0, 16, 49, 55, 63, 78, 92], R).
R=[f,f,f,d,c,b,a]

2 个答案:

答案 0 :(得分:4)

我建议使用CLP(FD)。您可以定义描述百分比和字母之间关系的谓词,然后使用maplist / 3来描述百分比列表和字母列表之间的关系:

:- use_module(library(clpfd)).
:- use_module(library(apply)).   % for maplist

percentage_letter(P,f) :-
   P in 0..49.
percentage_letter(P,d) :-
   P in 50..59.
percentage_letter(P,c) :-
   P in 60..69.
percentage_letter(P,b) :-
   P in 70..79.
percentage_letter(P,a) :-
   P in 80..100.

percentages_letters(P,L) :-
   maplist(percentage_letter,P,L).

我冒昧地使百分比范围不相交。只需根据您的需求进行调整。这个谓词有两种方式:

?- percentages_letters([0, 16, 49, 55, 63, 78, 92],L).
L = [f, f, f, d, c, b, a] ;
false.

?- percentages_letters(P,[f, f, f, d, c, b, a]).
P = [_G835, _G838, _G841, _G844, _G847, _G850, _G853],
_G835 in 0..49,
_G838 in 0..49,
_G841 in 0..49,
_G844 in 50..59,
_G847 in 60..69,
_G850 in 70..79,
_G853 in 80..100.

但是,字母到百分比方向会产生剩余目标,因为字母没有唯一的解决方案。如果要获取具体值,可以使用标签(L)。

?- percentages_letters(P,[f, f, f, d, c, b, a]), label(P).
P = [0, 0, 0, 50, 60, 70, 80] ;
P = [0, 0, 0, 50, 60, 70, 81] ;
P = [0, 0, 0, 50, 60, 70, 82] ;
P = [0, 0, 0, 50, 60, 70, 83] ;
P = [0, 0, 0, 50, 60, 70, 84] ;
P = [0, 0, 0, 50, 60, 70, 85] ;
P = [0, 0, 0, 50, 60, 70, 86] ;
P = [0, 0, 0, 50, 60, 70, 87] ;
.
.
.

最常见的查询会生成所有可能的列表,但会以不公平的方式枚举它们:

?- percentages_letters(P,L).
P = L, L = [] ;
P = [_G47],
L = [f],
_G47 in 0..49 ;
P = [_G75, _G78],
L = [f, f],
_G75 in 0..49,
_G78 in 0..49 ;
.
.
.

您可以通过为目标长度添加前缀来获得公平的列表:

?- length(P,_), percentages_letters(P,L).
P = L, L = [] ;
P = [_G48],
L = [f],
_G48 in 0..49 ;
P = [_G48],
L = [d],
_G48 in 50..59 ;
P = [_G48],
L = [c],
_G48 in 60..69 ;
.
.
.
P = [_G234, _G237],
L = [b, f],
_G234 in 70..79,
_G237 in 0..49 ;
.
.
.
P = [_G370, _G373, _G376, _G379],
L = [f, d, a, c],
_G370 in 0..49,
_G373 in 50..59,
_G376 in 80..100,
_G379 in 60..69 ;
.
.
.

答案 1 :(得分:0)

gradeMap(L,R) :- maplist(grade,L,R).

grade(V,a) :- between(81,100,V).
grade(V,b) :- between(71,80,V).
grade(V,c) :- between(61,70,V).
grade(V,d) :- between(51,60,V).
grade(V,f) :- between(0,50,V).

或者,如果您的Prolog没有between / 3

grade(V,a) :- V>=81,V=<100.
... etc etc

修改

中间/ 3方法的一个问题是,不必要的只为整数工作。 另一个问题是,我对范围的选择不佳。我会纠正

grade(V,a) :- V>=80.
grade(V,b) :- V>=70, V<80.
...
grade(V,f) :- V<50.