在另一个

时间:2015-04-24 06:14:59

标签: prolog

鉴于列表清单,我想替换A中的所有B,其中AB是prolog变量。

例如,如果列表是[[1,2,D,C],[A,D],[4,A],[1,2,A]] 我希望结果为[[1,2,D,C],[B,D],[4,B],[1,2,B]]

为此,我写了以下内容,将AB的所有/*substitude_single(+OldVar,+NewVar,+OldList,-NewList) */ substitute_single(_,_,[],[]). substitute_single(A,B,[A|As],[B|Bs]):- substitute_single(A,B,As,Bs). substitute_single(A,B,[X|As],[X|Bs]):- substitute_single(A,B,As,Bs). 替换为一个列表:

substitute(_,_,[],[]).
substitute(A,B,[P|Ps],[Q|Qs]):-
   substitute_single(A,B,P,Q),
   substitute(A,B,Ps,Qs).

现在我在主列表的每个元素上应用它,这是一个列表本身:

substitute_single(A,B,[C,A,D,1],X)

例如,当我在A = 1, C = 1, D = 1, X = [B, B, B, B] ; 上测试我的代码时出现问题,我得到了很多解决方案,有些正在对变量应用值。例如,我得到:

A = D,
C = D,
X = [B, B, B, 1] 

或:

X = [C, B, D, 1] 

并且只有在许多其他解决方案之后,我才得到:

substitute_single(A,B,[A|As],[B|Bs]):-
   substitute_single(A,B,As,Bs),
   !.

这是我喜欢的解决方案。然而,还有更多的解决方案(我不希望)追随它。

所以我试图削减程序,以防止它产生更多的解决方案:

A = 1,
C = 1,
D = 1,
X = [B, B, B, B].

但是现在,虽然我只得到一个解决方案,但它不是我想要的那个!

(对于上面的例子,我得到的解决方案是

A

我不知道应该如何或在哪里更改我的程序,因此它只会给我我想要的解决方案?

(注意:Bsubstitute_single(A,3,[C,A,D,1],X)可能是变量或常量,例如:[C,3,D,1])应生成<html> <head> <title>Form Data</title> </head> <body> <form action="form.php" method="post"> Server Name: <input type="text" name="server_name"> <br /> IP Address: <input type="text" name="ip_address"> <br /> Server Role: <input type="text" name="server_role"> <br /> <input type="submit" name="submit"> </form> <?php if (isset($_POST['submit'])) { $dbhost = "localhost"; $dbuser = "root"; $dbpass = "abcx"; $dbname = "serverasset_inventory"; $connection = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname); $sql = "INSERT INTO asset_inventory (server_name,ip_address,server_role) VALUES ('$_POST[server_name]','$_POST[ip_address]'),'$_POST[server_role]')"; $state = mysqli_query($connection,$sql); mysqli_close($connection); } ?> </body> </html>

3 个答案:

答案 0 :(得分:3)

您的解决方案的问题在于您将术语统一应用为等式测试,而您需要的是对具有==/2谓词的严格相同术语的测试。

为了在单个列表中交换两个可能是变量的术语,假设一个正确关闭的列表和一个模式+,?,?, - 以下谓词就足够了

exchgterms([],_,_,[]).
exchgterms([X|Xs],A,B,[C|Ys]) :-
  ( X == A -> C=B ;
    ( X == B -> C=A ; C=X ) ),
  exchgterms(Xs,A,B,Ys).

您可以从这里开始解决您的问题,并根据您的需要进行更改,特别是如果您的谓词必须采用不同的模式。

<强>更新

我更改了谓词的名称以强调它也适用于交换非变量的术语。

应该很清楚它应该在substitute_single/4的第二个子句中用不同顺序的substitute/4替换substitute(_,_,[],[]). substitute(A,B,[L|Ls],[R|Rs]) :- exchgterms(L,A,B,R), substitute(A,B,Ls,Rs). ,所以你寻求的解决方案是

substitute/4

我建议你改变LinkedList中参数的顺序,以便第3个参数成为第1个参数。在这种形式下,大多数Prolog系统都会知道如果这个参数被实例化,就像这里的情况那样,这两个子句是相互排斥的,这将有助于更有效的执行。

答案 1 :(得分:1)

substVarInTerm/4就是我想出来的。

:- use_module(library(apply)).

substVarInTerm(A,B,Term0,Term) :-
   term_variables(Term0,Vars0),
   exclude(==(A),Vars0,Vars),
   copy_term(A^Vars^Term0,B^Vars^Term).

请注意,如果第一个参数不是变量,substVarInTerm/4

其他用例您只需罚款

?- substVarInTerm(A,B,[[1,2,D,C],[A,D],[4,A],[1,2,A]],R).
R = [[1, 2, D, C], [B, D], [4, B], [1, 2, B]].

?- substVarInTerm(A,B,[C,A,D,1],X).
X = [C, B, D, 1].

?- substVarInTerm(A,3,[C,A,D,1],X).
X = [C, 3, D, 1].

答案 2 :(得分:-2)

尝试将X \ = B添加到第二个子句中:

substitute_single(A,B,[X|As],[X|Bs]):-
   X \= B,
   substitute_single(A,B,As,Bs).

当X不是B时,它不会分支到新的解决方案。