Prolog:将列表拆分为N个列表的列表,每个列表包含N个项目

时间:2016-01-25 16:53:12

标签: list prolog sudoku declarative

我一直在搜索与分裂有关的许多现有的Prolog问题但是找不到一个像我想要的那样通用的问题。我想指出,我已经能够通过使用列表变量之前管道传输的2/3/4变量将列表拆分为2/3/4元素列表。这个问题与此不同,仅仅是因为它的通用性。

所以,我的列表将始终包含N * N个项目,N事先未知(通常从4到36不等,是N也是一个完美的正方形)。我想将其拆分为N个列表的列表,每个列表包含N个项目,因为它允许我将其视为矩阵,因此允许转置和某种类型的操作。我还没有真正理解逻辑,因为我对声明性编程相对较新;请看下面我的不完整(错误)尝试:

listmodel(1,L):- L = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16].
size(L,N) :- length(L,N1), N is round(sqrt(N1)).

% add_tail(+Liste, +Element, -ResultantList)
add_tail([],L,[L]).
add_tail([X|L1],L2,[X|LI]):-add_tail(L1,L2,LI).

% partition the list containing N*N items into a list of N lists containing N elements each.
% part(+Liste, +Size, -ResultantList)
part([],_,DL).
part(L,N,DL) :-
    length(P,N), % P(refix) initialized
    append(P,S,L), % S(uffix) contains rest of L, using append in (-,-,+) mode
    add_tail(DL,P,DL1), %add P(first N elements) as first element of DL.
    part(S,N,DL1).

现在运行?- listmodel(1,L),size(L,N),part(L,N,DL).会生成DL=[],因为这是add_tail谓词中第一个part调用初始化的内容。我似乎无法弄清楚如何将所有元素存储在通过递归保留的列表中。

任何形式的帮助/方向都将受到赞赏。我现在被困在这里超过23小时10分钟。

感谢。

2 个答案:

答案 0 :(得分:2)

这应该这样做:

part([], _, []).
part(L, N, [DL|DLTail]) :-
   length(DL, N),
   append(DL, LTail, L),
   part(LTail, N, DLTail).

基本案例是第一个/最后一个参数是空列表。

递归步骤获取N个元素的新列表,从L中获取前N个元素(这将是第三个参数的项目之一)并递归调用。

答案 1 :(得分:2)

想要结合多功能性有利的终止属性? 使用

:- use_module(library(clpfd)).

首先,我们定义 list_prefix_n_suffix/4。  list_prefix_n_suffix(Zs,Xs,N,Ys)在逻辑上等同于append(Xs,Ys,Zs), length(Xs,N)length(Xs,N), append(Xs,Ys,Zs),但具有比 1 一个更好的通用终止行为!

list_prefix_n_suffix(Zs, Xs, N, Ys) :-
   list_prefix_n0_n_suffix(Zs, Xs, 0,N, Ys).

list_prefix_n0_n_suffix(Zs, Xs, N0,N, Ys) :-
   zcompare(Order, N0, N),
   rel_list_prefix_n0_n_suffix(Order, Zs, Xs, N0,N, Ys).

rel_list_prefix_n0_n_suffix(=, Ys, [], _,_, Ys).
rel_list_prefix_n0_n_suffix(<, [Z|Zs], [Z|Xs], N0,N, Ys) :-
   N1 #= N0 + 1,
   list_prefix_n0_n_suffix(Zs, Xs, N1,N, Ys).

list_prefix_n_suffix/4的一些示例查询:

?- list_prefix_n_suffix([a,b,c], Xs,-1, Ys).
false.                                          % OK: too small

?- list_prefix_n_suffix([a,b,c], Xs, 0, Ys).
Xs = [], Ys = [a,b,c].                          % succeeds deterministically

?- list_prefix_n_suffix([a,b,c], Xs, 4, Ys).
false.                                          % OK: too big

?- list_prefix_n_suffix([a,b,c], Xs, N, Ys).
   Xs = []     , N = 0, Ys = [a,b,c]
;  Xs = [a]    , N = 1, Ys =   [b,c]
;  Xs = [a,b]  , N = 2, Ys =     [c]
;  Xs = [a,b,c], N = 3, Ys =      []
;  false.                                       % terminates universally

根据上述list_prefix_n_suffix/4,我们定义了list_rows_width/3

list_rows_width([], [], _N).
list_rows_width([E|Es0], [[R|Rs]|Rss], N) :-
   list_prefix_n_suffix([E|Es0], [R|Rs], N, Es),
   list_rows_width(Es, Rss, N).

使用list_rows_width/3的示例查询:

?- list_rows_width([a,b,c,d,e,f], Rows, 4).
false.                                          % OK: 6 is not divisible by 4

?- list_rows_width([a,b,c,d,e,f], Rows, 3).
Rows = [[a,b,c],[d,e,f]].                       % succeeds deterministically

?- list_rows_width([a,b,c,d,e,f,g,h,i,j,k,l], Rows, N).
   N =  1, Rows = [[a],[b],[c],[d],[e],[f],[g],[h],[i],[j],[k],[l]]
;  N =  2, Rows = [[a,  b],[c,  d],[e,  f],[g,  h],[i,  j],[k,  l]]
;  N =  3, Rows = [[a,  b,  c],[d,  e,  f],[g,  h,  i],[j,  k,  l]]
;  N =  4, Rows = [[a,  b,  c,  d],[e,  f,  g,  h],[i,  j,  k,  l]]
;  N =  6, Rows = [[a,  b,  c,  d,  e,  f],[g,  h,  i,  j,  k,  l]]
;  N = 12, Rows = [[a,  b,  c,  d,  e,  f,  g,  h,  i,  j,  k,  l]]
;  false.                                       % terminates universally

就像应该的那样工作!

脚注1:无需使用之类的替代控制流机制。 功能