Prolog从列表中选择3

时间:2015-11-21 00:31:56

标签: list prolog

我创建了一个prolog程序,它给出了一个List a List和Sublist将生成包含N个项目的子列表。我被告知这可以用1个事实和2个规则来完成。我得到了提示,我选择了第一个项目,或者我不会让我感到困惑。我有基本案例和第一个案例,但我希望有人可以帮我理解第二个案例。

choose(1, [H], [H]).
choose(N, [H,TL], [H|ST]) :- choose(Less1, TL, ST), Less1 is N-1.

所以我的第三条规则是要选择列表中的第二项

choose(N, [F,S|T], [S|ST]) :- choose(Less1, T, ST), Less1 is N-1.

然而,我的最后一条规则是不平衡的,整体不起作用。非常感谢任何想法!

2 个答案:

答案 0 :(得分:2)

虽然this previous answer by @madanasta应该已经指出了正确的方向,但我们在此答案中使用对其进行了扩展:

:- use_module(library(clpfd)).

我们这样定义n_from_chosen/3

n_from_chosen(0,_,[]).
n_from_chosen(N,[X|Es],[X|Xs]) :-
   N #> 0,
   N #= N0+1,
   n_from_chosen(N0,Es,Xs).
n_from_chosen(N,[_|Es],Xs) :-
   N #> 0,
   n_from_chosen(N,Es,Xs).

示例查询:

?- n_from_chosen(2,[1,2,3,4],Xs).
  Xs = [1,2]
; Xs = [1,3]
; Xs = [1,4]
; Xs = [2,3]
; Xs = [2,4]
; Xs = [3,4]
; false.

这个更通用的查询怎么样?

?- n_from_chosen(N,[1,2,3],Xs).
  N = 0, Xs = []
; N = 1, Xs = [1]
; N = 2, Xs = [1,2]
; N = 3, Xs = [1,2,3]
; N = 2, Xs = [1,  3]
; N = 1, Xs =   [2  ]
; N = 2, Xs =   [2,3]
; N = 1, Xs =     [3]
; false.

答案 1 :(得分:1)

前两个条款背后的想法原则上是正确的。但是:

  • 当必须找到长度为1的子列表但原始列表的长度不是1时,第一个子句没有用。这是有问题的。
  • 在第二个条款中,我假设你的意思是[H | TL]。

鉴于这些,您的问题的解决方案可能是:

<% if offer.merchant == 'webgains' or offer.merchant == 'aw' %>
  <a href="<%= offer.url %>&clickref=<%= current_user.id %>" target="_blank">

<% elsif offer.merchant == 'rakuten' %>
  <h1>WOOP</h1>

<% elsif offer.merchant == 'cj' %>
  <a href="<%= offer.url %>?sid=<%= current_user.id %>" target="_blank">

<% else %>
  <h1>FAIL</h1>
  <a href="<%= offer.url %>" target="_blank">
<% end %>

尝试解释:

  • 第一个子句将生成一个长度为1的子列表,给定任何包含至少一个元素的列表:它将简单地将第三个参数与仅包含原始列表头部的单个元素列表统一起来。
  • 第二个子句将处理请求长度大于1的子列表的情况,在这种情况下,它将使用包含原始列表头部的列表和尾部统一第三个参数,由于递归,它将是原始列表尾部的子列表,其长度等于请求的长度减去1。
  • 第三个子句将简单地跳过原始列表的头部,并将第三个参数与一个列表统一起来,由于递归,该列表将是原始列表的所需长度尾部的子列表

由于第三个条款,Prolog将能够为所要求的长度提供等于或大于1的替代解决方案。

一些结果:

choose(1, [H|_], [H]).
choose(N, [H|TL], [H|ST]) :- Less1 is N - 1, choose(Less1, TL, ST).
choose(N, [_|T], L) :- choose(N, T, L).

请注意,您不能像使用@repeat's solution一样使用此解决方案来解决具有未绑定长度变量的查询。要在纯Prolog中实现这一点,您必须稍微改变第二个子句背后的逻辑:

?- choose(2, [1,2,3,4], L).
L = [1, 2] ;
L = [1, 3] ;
L = [1, 4] ;
L = [2, 3] ;
L = [2, 4] ;
L = [3, 4] ;
false.

这也可能有助于澄清递归在这种情况下的工作原理。

希望这有帮助。

(免责声明:我相当肯定,人们可以更好地解释上述解决方案的工作原理(更不用说更好的解决方案)了。)