我有这个代码将输入列表分成两半.好像没问题.
halve(List,A,B) :- halve(List,List,A,B), !.
halve(B,[],[],B).
halve(B,[_],[],B).
halve([H|T],[_,_|T2],[H|A],B) :-halve(T,T2,A,B).
Run Code Online (Sandbox Code Playgroud)
好的,所以我试着解码它.一开始很清楚:
"Halve采取列表和2个逻辑变量"是这样的:
halve(List,A,B)
Run Code Online (Sandbox Code Playgroud)
(1)然后连续这部分:
:- halve(List,List,A,B).
Run Code Online (Sandbox Code Playgroud)
这意味着,我正在从第一个创建新的两个列表(列表,列表)或者什么?什么exacly代表": - "?我猜新的列表=一半是A,而B,对吧?
(2)第二,拜托,我不太了解这两行:
halve(B,[],[],B).
halve(B,[_],[],B).
Run Code Online (Sandbox Code Playgroud)
也许你可以在一些例子中解释一下,好吗?
(3)嗯,我希望在您对(1)和(2)的解释之后,我将自己得到最后的部分......
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Run Code Online (Sandbox Code Playgroud)
非常非常感谢你帮助我.
好的,我们的第一个问题已经解决了.长话短说,它的工作原理如下:
halve([1,2,3,4,5],[1,2],[3,4,5]).
->true
Run Code Online (Sandbox Code Playgroud)
如果你注意到它将列表分成两半,但如果列表中有奇数个元素,则后半部分是较大的元素.
现在我想要获得的是让第一个更大.
所以我在想这个:
我要达到这个目的:
Halves_div([1,2,3],A,B).
A=[1,2],
B=[3].
Run Code Online (Sandbox Code Playgroud)
假设我的输入是列表:[1,2,3].所以我将从分割列表的头部和尾部开始:[H|T]然后我将合并H新的空列表 - 我的上半部分(A).之后我有A = [1],B = []和输入= [2,3].
合并我有:
merge([],List,List).
merge([H|T],List,[H|New]) :- merge(T,List,New).
Run Code Online (Sandbox Code Playgroud)
还有一件事 - 我需要检查上半场是否已经> =下半场,对吧?
所以这是我的想法,我唯一能帮助你的是将它写在prolog中.我有点困惑如何把它放在一起.
谢谢!
看来我对解决方案的想法太复杂了,我找到了更好的东西!
首先,Prolog子句看起来像这样:
Head :- Body
Run Code Online (Sandbox Code Playgroud)
您可以将其视为" Headif Body"或" Body隐含Head".
请注意,有时你只是
Head
Run Code Online (Sandbox Code Playgroud)
那是因为Head总是如此true.Head在这种情况下,我们宁愿称之为事实,而不是调用一个子句.
所以在这里,我们有:
halve(List,A,B) :- halve(List,List,A,B).
Run Code Online (Sandbox Code Playgroud)
这意味着halve(List, A, B)如果halve(List, List, A, B)是真的那就是真的.具体地说,它只是一种委托工作的halve/3方式halve/4,即所谓的工人谓词.
为什么我们需要一个工人谓词?好吧,因为在这里我们想使用另一个变量来计算我们A和B条款.但是我们不能这样做,halve/3因为halve/3输入列表已经采用了3个参数点,List结果的前半部分和结果A的后半部分,B.
关于这List, List件事,它只是一种说法,我们halve/4用相同的第一和第二个参数调用,就像你在任何编程语言中一样.
然后有趣的东西开始了.Prolog将尝试证明halve/4某些给定论点是正确的.让我们说来说明我们这样称呼的执行halve/3:
?- halve([1, 2], A, B).
Run Code Online (Sandbox Code Playgroud)
然后,如果您按照我之前谈到的内容,Prolog现在将尝试halve/3通过halve/4以下参数证明这是真的来证明这是真的:halve([1, 2], [1, 2], A, B)..
要做到这一点,Prolog有3个选择.第一个选择是以下条款:
halve(B,[],[],B).
Run Code Online (Sandbox Code Playgroud)
显然,那是行不通的.因为当Prolog将尝试通过统一来调整被调用者的第二个参数"in"被调用者的第二个参数时,它将失败.因为
[1, 2]无法统一[].
只剩下两个选择,下一个是:
halve(B,[_],[],B).
Run Code Online (Sandbox Code Playgroud)
同样的事情,Prolog无法统一[1, 2],[_]因为_它只是一个变量(如果你遇到麻烦,请参阅我关于匿名变量的帖子_).
因此,Prolog必须找到解决您提出的问题的唯一机会是最后一个条款,即:
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Run Code Online (Sandbox Code Playgroud)
在这里,Prolog会找到一种统一的方法,让我们看看哪种方式:
[1, 2]使用[H|T].这意味着H = 1.和T = [2].[1, 2]使用[_,_|T2].这意味着T2 = [].A = [H|A'](我引用第二个A因为变量是本地范围的,它们不一样).在这里,我们告诉我们,当我们从子句的主体计算出我们的结果时,我们将添加H它.这里H是1这样,我们已经知道的第一个元素A会1.好吧,统一成功了,太棒了!我们可以进入该条款的正文.它只halve/4是以递归方式调用这些值(上面计算):
halve([2], [], A, B).
Run Code Online (Sandbox Code Playgroud)
在这里,我们重新开始.虽然这次事情会很快,因为Prolog的第一选择将是一个很好的选择:
halve(B,[],[],B).
Run Code Online (Sandbox Code Playgroud)
可以统一到
halve([2], [], A, B).
Run Code Online (Sandbox Code Playgroud)
与这些价值观:A = []和B = [2].
这是一个很好的步骤,我们现在达到了递归的"基本情况".我们现在必须从下到上构建我们的结果.还记得当我们递归调用我们的谓词halve/4几步之后吗?我们已经说的第一个元素A是1.现在我们知道尾巴是[]如此,我们可以说明A = [1].我们没有说明任何特别的事情B因此B = [2]未被触及的结果.
现在我详细说明了执行情况,您可能想知道,为什么这样做有效?好吧,如果你注意,你会注意到第二个参数的halve/4速度是第一个参数的两倍.[H|T]VS [_, _|T2].这意味着当我们使用第二个参数到达列表的末尾时,第一个参数仍位于列表的中间位置.这样我们可以将事物分成两部分.
我希望我帮助你在这里找到一些微妙的工作.