Prolog中的固定列表输出

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

我正在努力解决荷兰国旗问题。基本上,给定一个列表,我想按照红-白-蓝的顺序对它们进行排序。红色、白色和蓝色由它们的谓词(即红色(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), 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).
---编辑---

不确定您到底想要什么,但我怀疑第三个版本的子句中有第三个错误:when
X
未累积

我认为您应该添加一个检查,以确保
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-你很好;添加了另一个建议