1

我试图找到一个值score,它可以从两个相等长度的列表中强制计算Xs, Ys为:

for i in len(Xs):
    if Xs[i] == Ys[i]:
        score++
    else:
        score--

所以这个想法是基本上从左到右检查两个列表中的每个元素,如果这些元素相同,则增加分数,否则减少分数。例如:

score([1,2,3], [1,2,3]) == 3
score([1,2,3], [1,2,1]) == 1
score([1,2,3], [3,2,1]) == -1
score([1,2,3], [3,1,2]) == -3

我想我实际上设法将程序编写为:

score(Xs, Ys, C) ?=>
    Xs = [], Ys = [], C = 0.

score(Xs, Ys, C) =>
    Xs = [XH|XT],
    Ys = [YH|YT],
    if (XH #= YH) then
        C #= C1 + 1
    else
        C #= C1 - 1
    end,
    score(XT, YT, C1).

当我查询分数时,代码给出了正确的结果:

score([1,2,3], [1,2,3], S).
    S = 3 ?;

score([1,2,3], [1,2,1], S).
    S = 1 ?;

score([1,2,3], [3,2,1], S).                                      
    S = -1 ?;

score([1,2,3], [3,1,2], S).                                      
    S = -3 ?;

但是,当我尝试生成产生分数的列表时,代码只生成分数为 3 的相同列表:

S :: -3..3, Ls = new_list(3), Ls :: 1..3, score([1,2,3], Ls, S), solve([Ls, S]).

S = 3
Ls = [1,2,3] ?;

no

我想生成所有列表,对应于所有可能的分数,我觉得我必须修改基本情况,但我不知道如何:)

编辑:我也尝试做一个尾递归类型的解决方案,它在查询分数时再次给出正确的结果,但它只能生成相同的列表。

score(Xs, Ys, C) ?=>
    score_helper(Xs, Ys, 0, C).

score_helper([], _, Cur, C) ?=>
    C = Cur.

score_helper(Xs, Ys, Cur, C) ?=>
    Xs = [XH|XT],
    Ys = [YH|YT],
    if (XH = YH) then
        score_helper(XT, YT, Cur+1, C)
    else
        score_helper(XT, YT, Cur-1, C)
    end.
4

1 回答 1

1

如果您正在使用约束求解器(例如cp,sat等),那么只需使用即可sum完成这项工作:

import cp. 

go ?=> 
  X=new_list(3),
  Y=new_list(3),
  X::1..3, 
  Y::1..3, 
  Z #= sum([cond(X[I] #= Y[I], 1,-1) : I in 1..3]),
  solve(X++Y),
  println([x=X,y=Y,z=Z]), 
  fail,
  nl.
go => true.

要点是可以X[I] #= Y[I]在列表理解中使用约束(此处)。

还是要求它不应该使用约束?

编辑:另一种CP方法如下(使用Picat v3支持的“Prolog”样式。这使用等价(#<=>)进行检查:

go3 ?=>
  Y = [1,2,3],
  X = new_list(3),
  X :: 1..3,
  Score :: [-1,1],
  score3(X,Y,0,Score),
  solve(X ++ [Score]),
  println(x=X),
  println(score=Score),
  nl,
  fail,
  nl.
go3 => true.


score3([], [], Score,Score).
score3([XH|XT], [YH|YT], Score0, Score) :-
  (XH #= YH) #<=> (Score1 #= Score0 + 1),
  score3(XT, YT, Score1,Score).

您的方法的一个问题是您将约束相等检查 ( #=) 与传统相等 ( ==and =) 混合在一起,这可能不会给出预期的结果。

这是另一种使用相同原理但在foreach循环内的方法:

 go2 ?=>
   Y = [1,2,3],
   N = Y.len,
   X = new_list(N),
   X :: 1..max(Y),
   Scores = new_list(N),
   Scores :: [-1,1],
   foreach(I in 1..X.len)
      X[I] #= Y[I] #<=> Scores[I] #= 1
   end,
   Z #= sum(Scores),
   solve(X ++ Scores),
   println([x=X,y=Y,scores=Scores,z=Z]),
  fail,
  nl.
go2 => true.
于 2021-01-15T09:28:52.433 回答