【问题标题】:Combinations of multiple lists - Prolog多个列表的组合 - Prolog
【发布时间】:2020-06-20 04:16:40
【问题描述】:

我需要在列表列表中找到组合。例如,给出以下列表,

List = [[1, 2], [1, 2, 3]]

这些应该是输出,

Comb = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]

另一个例子:

List = [[1,2],[1,2],[1,2,3]]

Comb = [[1,1,1],[1,1,2],[1,1,3],[1,2,1],[1,2,2],[1,2,3]....etc]

我知道如何为具有两个子列表的列表执行此操作,但它需要适用于任意数量的子列表。

我是 Prolog 新手,请帮忙。

【问题讨论】:

  • List = [[1,2],[1,2],[1,2,3]], bagof(Es, maplist(member,Es,List), Ess).
  • @GuyCoder:你的解决方案怎么样?
  • @GuyCoder:任何基于本身不太符合标准的系统的扩展肯定是相当可疑的。如果遇到困难,必须查阅下面扩展的 Prolog。
  • @GuyCoder:那么你认为这对 OP 来说会很容易吗?
  • @GuyCoder:提醒:您提供了一笔交易。我完成了我的职责。

标签: list prolog


【解决方案1】:

为了完整起见,这里是我的评论版本的增强版本。注意nilmemberd_t/2,它的灵感来自memberd_t/2

nilmemberd_t([], false).
nilmemberd_t([X|Xs], T) :-
   if_(nil_t(X), T = true, nilmemberd_t(Xs, T)).

nil_t([], true).
nil_t([_|_], false).

list_comb(List, []) :-
   nilmemberd_t(List, true).
list_comb(List, Ess) :-
   bagof(Es, maplist(member,Es,List), Ess).

以上版本显示我的评论回复中“仅”缺少第一个子句。可能更短:

nilmemberd([[]|_]).
nilmemberd([[_|_]|Nils]) :-
   nilmemberd(Nils).

这应该适用于没有限制的 Prologs。有了约束,必须重新考虑 bagof/3,因为复制约束是一个不明确的地形。

【讨论】:

  • @rep:你的意思是你有资格获得承诺的赏金?
  • 不!但我认为我应该发布一个 lambda 变体作为单独的答案。 (只是 4 有趣,不值得赏金)
  • 大概,你做了所有这些而不是仅仅使用findall而不是bagof,以避免findall( Es, maplist( member,Es, [[1,2],t,[1]]), Ess).错误地使用[]成功而不是失败。但是您的版本也同样错误地使用[] 成功地获得[[1,2],[],t,[1]]
  • 我的意思是,因为bagof 错误地在[[1,1],[],[1]] 上失败,但findall 正确(在这种情况下)在[] 上成功。
  • @Will: bagof/3 正确处理变量,而 findall/3 疯狂地复制它们
【解决方案2】:

这是一种使用maplist/3append/2 的方法:

列表梳([],[[]])。 list_comb([Xs|Xss], Ess) :- Xs = [_|_], list_comb(Xss, Ess0), 地图列表(aux_x_comb(Ess0),Xs,Esss1), 追加(Ess1,Ess)。 aux_x_comb(Ess0, X, Ess1) :- 地图列表(head_tail_list(X),Ess0,Ess1)。 头尾列表(X,Xs,[X|Xs])。

示例查询:

?- list_comb([[a,b],[f,g],[x,y,z]], Ess).
Ess = [[a,f,x],[a,f,y],[a,f,z],
       [a,g,x],[a,g,y],[a,g,z],
       [b,f,x],[b,f,y],[b,f,z],
       [b,g,x],[b,g,y],[b,g,z]].

这是它的工作原理! 例如,考虑以下目标:

  • list_comb([[a,b],[f,g],[x,y,z]], Ess)

  • list_comb([ [f,g],[x,y,z]], Ess0)

我们如何从Ess0Ess

  1. 我们看看答案 后一个查询:

    ?- list_comb([[f,g],[x,y,z]], Ess0)。
    Ess0 = [[f,x],[f,y],[f,z], [g,x],[g,y],[g,z]]。
  2. ...将a放在[f,x]之前,...,[g,z]...

    ?- maplist(head_tail_list(a),
               [[f,x],[f,y],[f,z],
                [g,x],[g,y],[g,z]], X)。
    X = [[a,f,x],[a,f,y],[a,f,z],
         [a,g,x],[a,g,y],[a,g,z]].
  3. ...然后对b 执行相同操作。

    maplist(aux_x_comb) 帮助我们处理所有项目:

    ?- maplist(aux_x_comb([[f,x],[f,y],[f,z],
                           [g,x],[g,y],[g,z]]),
               [a,b],X)。
    X = [[[a,f,x],[a,f,y],[a,f,z],
          [a,g,x],[a,g,y],[a,g,z]],
         [[b,f,x],[b,f,y],[b,f,z],
          [b,g,x],[b,g,y],[b,g,z]]].
  4. 要从列表列表中获取列表,请使用append/2

我希望这个解释更清楚而不是令人困惑:)

【讨论】:

  • Ess 对终止没有影响 - 至少在某些情况下
【解决方案3】:

@false 方法的一个转折:

%list_comb( ++LL, -Ess)
list_comb( LL, Ess):-
    is_list( LL),
    maplist( is_list, LL),
    findall( Es, maplist( member, Es, LL), Ess).

测试:

41 ?- list_comb( [[1,2],[1],[1]], X).
X = [[1, 1, 1], [2, 1, 1]].

42 ?- list_comb( [[1,2],[1],[1,2,3]], X).
X = [[1, 1, 1], [1, 1, 2], [1, 1, 3], [2, 1, 1], [2, 1, 2], [2, 1, 3]].

43 ?- list_comb( [[1,2],[],[1,2,3]], X).
X = [].

44 ?- list_comb( [[1,2],t,[1,2,3]], X).
false.

45 ?- list_comb( t, X).
false.

【讨论】:

  • 通过排除变量,谓词变得像函数程序一样被建模-但没有...-呃-非严格性。
【解决方案4】:

这个答案寻找提供的赏金“一个纯粹的解决方案,也考虑到Ess”。 这里我们将this previous answer 概括如下:

list_crossproduct(Xs, []) :-
   member([], Xs).
list_crossproduct(Xs, Ess) :-
   Ess = [E0|_],
   same_length(E0, Xs),
   maplist(maybelonger_than(Ess), Xs),
   list_comb(Xs, Ess).

maybelonger_than(Xs, Ys) :-
   maybeshorter_than(Ys, Xs).

maybeshorter_than([], _).
maybeshorter_than([_|Xs], [_|Ys]) :-
   maybeshorter_than(Xs, Ys).

list_crossproduct/2 通过早期关联XsEss 获得双向。

?- list_comb(Xs, [[1,2,3],[1,2,4],[1,2,5]])。 不终止 % 糟糕! ?- list_crossproduct(Xs, [[1,2,3],[1,2,4],[1,2,5]])。 Xs = [[1],[2],[3,4,5]] % 现在也可以了 ;错误的。

有多个答案的示例查询:

?- list_crossproduct(Xs, [[1,2,3],[1,2,4],[1,2,5],X,Y,Z]).
   X = [1,2,_A],
   Y = [1,2,_B],
   Z = [1,2,_C], Xs = [[1],[2],[3,4,5,_A,_B,_C]]
;  X = [1,_A,3],
   Y = [1,_A,4],
   Z = [1,_A,5], Xs = [[1],[2,_A],[3,4,5]]
;  X = [_A,2,3],
   Y = [_A,2,4],
   Z = [_A,2,5], Xs = [[1,_A],[2],[3,4,5]]
;  false.

【讨论】:

  • 兴趣:最好使用nilmemberd(Xs) 而不是member([],Xs)
猜你喜欢
  • 1970-01-01
  • 2016-01-12
  • 2013-02-07
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 2017-11-27
相关资源
最近更新 更多