1

我正在尝试将 S1 与 A1、S2 与 A2、...、S5 与 A5 进行比较,并获得相互匹配的对的总数。但是解释器显示“语法错误,操作员预期”。有什么简单的方法可以解决这个问题吗?我的代码有什么问题?谢谢!

grade(S1, S2, S3, S4, S5, A1, A2, A3, A4, A5, N):-
   S1 = A1, grade2(S2, S3, S4, S5, A2, A3, A4, A5, N+1).

grade(S1, S2, S3, S4, S5, A1, A2, A3, A4, A5, N):-
   \+ S1=A1, grade2(S2, S3, S4, S5, A2, A3, A4, A5, N).

grade2(S2, S3, S4, S5, A2, A3, A4, A5, N):-
   S2=A2, grade3(S3, S4, S5, A3, A4, A5, N+1).

grade2(S2, S3, S4, S5, A2, A3, A4, A5, N):-
   \+ S2=A2, grade3(S3, S4, S5, A3, A4, A5, N).

grade3(S3, S4, S5, A3, A4, A5, N):-
   S3=A3, grade4(S4, S5, A4, A5, N+1).

grade3(S3, S4, S5, A3, A4, A5, N):-
   \+ S3=A3, grade4(S4, S5, A4, A5, N).

grade4(S4, S5, A4, A5, N):-
   S4=A4, grade5(S5, A5, N+1).

grade4(S4, S5, A4, A5, N):-
   \+ S4=A4, grade5(S5, A5, N).

grade5(S5, A5, N):-
   S5=A5, N is 1. 

grade5(S5, A5, N):-
   \+ S5=A5, N is 0.
4

3 回答 3

1

使用 SWI-Prolog 和模块 lambda,您可以编写:

:- use_module(library(lambda)).

grade(S1, S2, S3, S4, S5, A1, A2, A3, A4, A5, N) :-
    foldl(\X^Y^Z^T^(X = Y ->  T is Z+1 ;   T = Z),
         [S1, S2, S3, S4, S5],
         [A1, A2, A3, A4, A5],
         0, N).
于 2013-10-14T07:31:06.047 回答
0

我无法重现您的错误。但是,由于您计算 N 值的方式,它现在无法工作。如果您进行跟踪,您应该能够看到哪里出错了。

无论如何,尽管您似乎事先知道要比较多少对,但更通用的方法是将这些对放在两个列表中,甚至更好的是,放在一个对列表中:

[S1-A1, S2-A2, ...]

这里-只是一种写法-(S, A),以及通常的 Prolog 表示“对”的方式。一旦对列表采用这种形式,您就可以显式编写:

grade([], 0).
grade([S-A|Rest], N) :-
    (   S == A
    ->  Add = 1
    ;   Add = 0
    ),
    grade(Rest, N0),
    N is N0 + Add.

请注意,除非您有一个额外的参数来收集到目前为止的结果,否则您不能使用尾递归:

grade([], N, N).
grade([S-A|Rest], Acc, N) :-
    (   S == A
    ->  NewAcc is Acc + 1
    ;   NewAcc = Acc
    ),
    grade(Rest, NewAcc, N).

(调用谓词时需要“初始化”累加器)

?- grade(List, 0, N).

所以对于你的情况:

  • 使用您的初始方法,但修复如何使用所示的两种方法中的任何一种计算 N
  • 将您的配对列表表示为实际的配对列表
  • 如果您正在使用列表,还有其他可用的技术,例如,请参见 library(aggregate)。可能对更复杂的同类问题有用。
于 2013-10-14T06:41:18.733 回答
0

我没有从您的代码中得到任何语法错误,但它无法执行:您的第一条规则(例如)应该是

grade(S1, S2, S3, S4, S5, A1, A2, A3, A4, A5, N):-
  S1 = A1, grade2(S2, S3, S4, S5, A2, A3, A4, A5, M),
  N is M+1.

您在唯一没用的地方使用了 is/2 。最后一条规则可以阅读

grade5(S5, S5, 1):-!.
grade5(_, _, 0).

然后为了一些更容易阅读的代码(理解太多无用细节的代码对我可怜的大脑是有害的......),使用 library(aggregate)

grade(S1, S2, S3, S4, S5, A1, A2, A3, A4, A5, N):-
  aggregate_all(count,
    (nth1(I,[S1,S2,S3,S4,S5],X),
     nth1(I,[A1,A2,A3,A4,A5],X)
    ), N).

我明白了

4 ?- grade(a,b,c,d,e, u,v,c,d,x, N).
N = 2.
于 2013-10-14T06:43:27.643 回答