Prolog中的固定列表输出
我正在努力解决荷兰国旗问题。基本上,给定一个列表,我想按照红-白-蓝的顺序对它们进行排序。红色、白色和蓝色由它们的谓词(即红色(x)、白色(x)等)定义 目前,我有以下代码:Prolog中的固定列表输出,prolog,dutch-national-flag-problem,dcg,logical-purity,Prolog,Dutch National Flag Problem,Dcg,Logical Purity,我正在努力解决荷兰国旗问题。基本上,给定一个列表,我想按照红-白-蓝的顺序对它们进行排序。红色、白色和蓝色由它们的谓词(即红色(x)、白色(x)等)定义 目前,我有以下代码: red(1). white(2). blue(3). dutch(Xs,Ys):- getRed(Xs,[], Red), getWhite(Xs,[],White), getBlue(Xs,[],Blue), append([], Red, Y1), append(Y1, White, Y2), a
red(1).
white(2).
blue(3).
dutch(Xs,Ys):-
getRed(Xs,[], Red), getWhite(Xs,[],White), getBlue(Xs,[],Blue),
append([], Red, Y1), append(Y1, White, Y2), append(Y2, Blue, Ys).
getRed([],Rs,Rs).
getRed([X|Rest], Acc, Rs) :- red(X), getRed(Rest, [X,Acc] , Rs).
getRed([X|Rest], Acc, Rs) :- getRed(Rest, Acc, Rs).
getWhite([],Rs,Rs).
getWhite([X|Rest], Acc, Rs) :- white(X), getWhite(Rest, [X,Acc], Rs).
getWhite([X|Rest], Acc, Rs) :- getWhite(Rest, Acc, Rs).
getBlue([],Rs,Rs).
getBlue([X|Rest], Acc, Rs) :- blue(X), getBlue(Rest, [X,Acc], Rs).
getBlue([X|Rest], Acc, Rs) :- getBlue(Rest, Acc, Rs).
我的输出如下所示:
?- dutch([1,2,3],R).
R = [1, [], 2, [], 3, []]
R = [1, [], 2, []]
R = [1, [], 3, []]
R = [1, []]
R = [2, [], 3, []]
R = [3, []]
R = []
我想让它看起来像这样:
R = [1, 2, 3]
我已经尝试了几种方法来强制输出我想要的内容,但都没有成功
编辑:看起来我可以通过使用蛮力解决方案来解决这个问题:排列所有可能的集合,并评估集合是否符合“荷兰国旗”的顺序。但是有更好的解决方案吗?我发现您的代码中有两个错误: 1) 您的终端子句
getRed([],Rs,Rs)
,getWhite([],Rs,Rs)
,getBlue([],Rs,Rs)
接受空列表作为值结果(当Rs
等于[]
时);我建议将它们改写为
getRed([],Rs,Rs) :- Rs \= [].
getWhite([],Rs,Rs) :- Rs \= [].
getBlue([],Rs,Rs) :- Rs \= [].
getRed([X|Rest], Acc, Rs) :- red(X), getRed(Rest, [X|Acc], Rs).
getWhite([X|Rest], Acc, Rs) :- white(X), getWhite(Rest, [X|Acc] , Rs).
getBlue([X|Rest], Acc, Rs) :- blue(X), getBlue(Rest, [X|Acc], Rs).
2) 在接受子句中(当X
是搜索的颜色时),当您应该使用管道([X,Acc]
;should([X | Acc]
)时,用逗号将其添加到累加器中;我建议将其重写为
getRed([],Rs,Rs) :- Rs \= [].
getWhite([],Rs,Rs) :- Rs \= [].
getBlue([],Rs,Rs) :- Rs \= [].
getRed([X|Rest], Acc, Rs) :- red(X), getRed(Rest, [X|Acc], Rs).
getWhite([X|Rest], Acc, Rs) :- white(X), getWhite(Rest, [X|Acc] , Rs).
getBlue([X|Rest], Acc, Rs) :- blue(X), getBlue(Rest, [X|Acc], Rs).
离题:没有理由将Red
附加到空列表中;结果列表(Y1
)本身就是Red
;我建议重新组合
append([], Red, Y1), append(Y1, White, Y2), append(Y2, Blue, Ys)
如下
append(Red, White, Mid), append(Mid, Blue, Ys)
getRed([X|Rest], Acc, Rs) :- \+ red(X), getRed(Rest, Acc, Rs).
getWhite([X|Rest], Acc, Rs) :- \+ white(X), getWhite(Rest, Acc, Rs).
getBlue([X|Rest], Acc, Rs) :- \+ blue(X), getBlue(Rest, Acc, Rs).
---编辑---
不确定您到底想要什么,但我怀疑第三个版本的子句中有第三个错误:whenX
未累积
我认为您应该添加一个检查,以确保X
不是搜索到的颜色;我建议将它们重写如下
append(Red, White, Mid), append(Mid, Blue, Ys)
getRed([X|Rest], Acc, Rs) :- \+ red(X), getRed(Rest, Acc, Rs).
getWhite([X|Rest], Acc, Rs) :- \+ white(X), getWhite(Rest, Acc, Rs).
getBlue([X|Rest], Acc, Rs) :- \+ blue(X), getBlue(Rest, Acc, Rs).
---编辑2---
我认为您的getRed/3
、getWhite/3
和getBlue/3
子句中不需要累加器
我建议一个只有两个参数的版本
red(1).
white(2).
blue(3).
dutch(Xs,Ys):-
getRed(Xs, Red), getWhite(Xs, White), getBlue(Xs, Blue),
append(Red, White, Mid), append(Mid, Blue, Ys).
getRed([],[]).
getRed([X|Rest], [X|Rs]) :- red(X), getRed(Rest, Rs).
getRed([X|Rest], Rs) :- \+ red(X), getRed(Rest, Rs).
getWhite([],[]).
getWhite([X|Rest], [X|Rs]) :- white(X), getWhite(Rest, Rs).
getWhite([X|Rest], Rs) :- \+ white(X), getWhite(Rest, Rs).
getBlue([],[]).
getBlue([X|Rest], [X|Rs]) :- blue(X), getBlue(Rest, Rs).
getBlue([X|Rest], Rs) :- \+ blue(X), getBlue(Rest, Rs).
纯溶液
前言
我想在现有解决方案的基础上添加一个纯,关系解决方案
理想情况下,您可以在所有方向中使用Prolog谓词,现在我将展示一个实现,它允许您这样做:不仅可以根据您的条件对实例化列表进行排序,还可以生成解和完成部分实例化解
为了做到这一点,我使用了来自的元谓词if\u3
具体化谓词
我从谓词的具体化版本开始,还冒昧地使用更能说明问题的名称红色
、白色
和蓝色
,来表示颜色:
red(R, T) :- =(R, red, T).
white(W, T) :- =(W, white, T).
blue(B, T) :- =(B, blue, T).
我留下来,让这更简洁,作为一个简单的练习
解决方案
通过这些构建块,我们可以表达整体解决方案:
dutch(Colors, Ds) :-
phrase(reds(Rs), Colors),
phrase(whites(Ws), Colors),
phrase(blues(Bs), Colors),
phrase((Rs,Ws,Bs), Ds).
荷兰语(颜色,Ds):-
短语(红色(Rs)、颜色),
短语(白色(Ws)、颜色),
短语(蓝色(Bs),颜色),
短语((Rs,Ws,Bs),Ds)。
例子
当然,这适用于简单的实例化情况,如:
?- dutch([red,white,blue], Ds).
Ds = [red, white, blue] ;
false.
-荷兰语([红、白、蓝]、Ds)。
Ds=[红、白、蓝];
错。
现在重点是:这个也适用于最常见的情况,其中所有参数都是变量:
?-长度(Cs,u),荷兰语(Cs,Ds)。
Cs=Ds,Ds=[];
Cs=Ds,Ds=[红色];
Cs=Ds,Ds=[白色];
Cs=Ds,Ds=[蓝色];
Cs=[[u G1322],
Ds=[],
dif(_G1322,蓝色),
dif(_G1322,白色),
dif(红色);
Cs=Ds,Ds=[红色,红色];
Cs=Ds,Ds=[红色,白色];
Cs=Ds,Ds=[红色,蓝色];
Cs=[红色,_G1340],
Ds=[红色],
dif(_G1340,蓝色),
dif(_G1340,白色),
dif(_G1340,红色)。
通过添加更多目标,我们可以专门化此查询,以观察现在生成的具体解决方案:
?- length(Cs, _), Cs = [_,_,_|_], dutch(Cs, Ds), ground(Cs).
Cs = Ds, Ds = [red, red, red] ;
Cs = Ds, Ds = [red, red, white] ;
Cs = Ds, Ds = [red, red, blue] ;
Cs = [red, white, red],
Ds = [red, red, white] ;
Cs = [red, blue, red],
Ds = [red, red, blue] .
?-长度(Cs,Cs=[(Cs,Cs),荷兰(Cs,Ds),地面(Cs)。
Cs=Ds,Ds=[红色,红色,红色];
Cs=Ds,Ds=[红,红,白];
Cs=Ds,Ds=[红,红,蓝];
Cs=[红、白、红],
Ds=[红,红,白];
Cs=[红色,蓝色,红色],
Ds=[红色,红色,蓝色]。
将此与无法用于公平枚举解决方案的进行比较:
?- length(Xs, _), Xs = [_,_,_|_], dutch(Xs, Ys).
Xs = Ys, Ys = [1, 1, 1] ;
Xs = Ys, Ys = [1, 1, 1, 1] ;
Xs = Ys, Ys = [1, 1, 1, 1, 1] ;
Xs = Ys, Ys = [1, 1, 1, 1, 1, 1] ;
Xs = Ys, Ys = [1, 1, 1, 1, 1, 1, 1] .
?-长度(Xs,ux),Xs=[x,x,124; x],荷兰语(Xs,Ys)。
Xs=Ys,Ys=[1,1,1];
Xs=Ys,Ys=[1,1,1,1];
Xs=Ys,Ys=[1,1,1,1,1];
Xs=Ys,Ys=[1,1,1,1,1,1];
Xs=Ys,Ys=[1,1,1,1,1,1]。
总结
因此,通过保留,我们得到了一个更通用的逻辑程序,我们可以在各个方向上使用它
诚然,您并没有要求这种通用性。然而,既然我们在做,为什么要放弃它呢?感谢您提供的prolog提示!我对prolog非常陌生,对编程实践不太了解。在大多数情况下,我只是试图让代码运行,并且匆忙地进行更改以测试不同的实现。我将继续这些是我对未来任何代码的想法。@Terence-你很好;添加了另一个建议