鉴于列表清单,我想替换A
中的所有B
,其中A
和B
是prolog变量。
例如,如果列表是[[1,2,D,C],[A,D],[4,A],[1,2,A]]
我希望结果为[[1,2,D,C],[B,D],[4,B],[1,2,B]]
为此,我写了以下内容,将A
中B
的所有/*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
)
我不知道应该如何或在哪里更改我的程序,因此它只会给我我想要的解决方案?
(注意:B
和substitute_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>
)
答案 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时,它不会分支到新的解决方案。