【问题标题】:Format minimal path格式化最小路径
【发布时间】:2019-04-24 23:22:05
【问题描述】:

所以我一直在努力帮助我更好地理解 Prolog。我采取了传统的水壶问题,但增加了一些难度。因此,我的代码运行良好。剩下要做的就是为输出做一些漂亮的格式化。目前,它只显示了我的代码中找到的最小路径来填充水罐。 (见下面的例子)

到目前为止,我想到了一种可以做到的方法,但我不知道如何在 Prolog 中做到这一点。

我的最佳路径的最终列表格式如下:[ [x(a,b),y(c,d),z(e,f)], [], [], ...]

我想达到这种格式(更详细的输出见下文):

a -> b
c -> d
etc
  • 首先,我将第一个作为液体打印出来(在我们的例子中,1。否则,列表中的第一个元素是初始模式)。然后,我获取第一个子列表,并与之前的一个进行比较,看看哪个水壶确实转移到另一个并打印出来。然后,继续直到列表为空。

目前显示如下:

?- problem.
[[jug(3,0),jug(5,0),jug(8,8)],[jug(3,0),jug(5,5),jug(8,3)],
 [jug(3,3),jug(5,2),jug(8,3)],[jug(3,0),jug(5,2),jug(8,6)],
 [jug(3,2),jug(5,0),jug(8,6)],[jug(3,2),jug(5,5),jug(8,1)],
 [jug(3,3),jug(5,4),jug(8,1)],[jug(3,0),jug(5,4),jug(8,4)]]
true .

对于当前的 jugs 配置来说,这是正确的路径。 (稍后我会添加一个处理 n 壶的方法)

这是我希望它显示的方式(在我的代码中,您可以看到我想要的每个索引):

?- problem.
1 -> 2
2 -> 3
3 -> 1
2 -> 3
1 -> 2
2 -> 3
3 -> 1
true.

我很想得到这方面的帮助,因为我正在尝试的一切都是一团糟。

谢谢男孩/女孩

【问题讨论】:

  • 我觉得这里的主要问题是数据格式不方便。当你倒它们时,你实际上并不知道你在操纵哪个壶,而且你的解决方案也没有这些信息。我认为你应该增加你的数据结构,这样你就知道哪个水壶是哪个(也许[3-jug(3,0), 2-jug(5,0), 1-jug(8,8)]),然后在你倒酒的时候,你可以保留一份发生的事情的侧面清单,而不是试图事后弄清楚。
  • @DanielLyons:我只会使用jug(Column,MaxWater,CurrentWater),因为 OP 代码目前依赖于 MaxWater 被严格定义为使代码正常工作(例如,请参阅 @ 中对 sort/2 的调用987654329@)。然后对于每个过渡,他可以使用Column 值来记录每个步骤。
  • @gusbro 实际上听起来不错。但我不知道我将如何实现它。我知道水壶在哪里,它们的顺序相同。简单地说,我不知道如何比较它们。我目前的计划在纸面上很好,很容易用命令式语言实现。我必须得到每个的索引,并比较它们是否改变了。如果他们这样做了,那么我就占据它的位置并使用 write()。这样我可以产生一个好看的输出。唯一就是不知道怎么做,怎么获取列表中元素的索引等等等等。
  • @GuillaumeLevesque:您是否尝试过您的程序具有不同的初始/结束状态(例如交换第一个和第二个罐子)?
  • 你在论文中说的算法在prolog中也很容易编写。您还必须考虑到一个水罐“失去”水而另一个水罐“获得”水来编写过渡。但是,如果您在构建链时只跟踪该信息会更容易,因为此时您已经拥有所有信息。

标签: prolog water-jug-problem


【解决方案1】:

如果你有一个实际的解决路径(我相信你的代码对于某些初始/结束状态不会产生正确的结果),你可以编写如下过程:

show([_]).
show([S1, S2|Tail]):-
  show1(S1, S2, 3, Gain, Loss),  # 3 here is the number of jugs
  write(Loss), write(' -> '), write(Gain),nl,
  show([S2|Tail]).

show1([], [], _, _, _).
show1([jug(Max1,Cur1)|S1], [jug(Max2,Cur2)|S2], Idx, Gain, Loss):-
  succ(NIdx, Idx),
  (Max1-Cur1=Max2-Cur2 -> true;
   (Cur2 > Cur1 -> Gain=Idx ;
    Loss=Idx
  )),
  show1(S1, S2, NIdx, Gain, Loss).

但是,我建议您在构建解决方案路径时改进原始代码以计算这些值。

示例运行:

show([[jug(3,0),jug(5,0),jug(8,8)],[jug(3,0),jug(5,5),jug(8,3)], 
     [jug(3,3),jug(5,2),jug(8,3)],[jug(3,0),jug(5,2),jug(8,6)], 
     [jug(3,2),jug(5,0),jug(8,6)],[jug(3,2),jug(5,5),jug(8,1)], 
     [jug(3,3),jug(5,4),jug(8,1)],[jug(3,0),jug(5,4),jug(8,4)]]).
1 -> 2
2 -> 3
3 -> 1
2 -> 3
1 -> 2
2 -> 3
3 -> 1
true.

【讨论】:

  • 刚试了一下,好像代码无限循环。我会试着找出原因。
  • @GuillaumeLevesque:你确定那个节目是循环播放的吗?这没有意义。
【解决方案2】:

查看模式以检查两个相邻元素

show(L) :-
    findall(T, (append(_,[A,B|_],L), transition(A,B,T)), Ts),
    maplist(writeln, Ts).

transition(
    [jug(3,A),jug(5,B),jug(8,C)],
    [jug(3,U),jug(5,V),jug(8,Z)],
    S->T
) :-
    P=[A^U,B^V,C^Z],
    nth0(L,P,X^M), X>M,
    nth0(R,P,Y^N), Y<N,
    S is 3-L, T is 3-R.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多