I've been searching through the many existing Prolog questions on SO relevant to splitting but couldn't find one as generic as the one that I want. I'd like to point out that I've been able to split lists into lists of 2/3/4 elements by using 2/3/4 variables piped before a list variable. This question is different from that only because of its genericness.
So, my list will always contain N*N items, N being unknown beforehand(usually will vary from 4 to 36, yes N is also a perfect square). I want to split it into a list of N lists containing N items each because that'll allow me to treat it as a matrix, hence allowing to transpose and certain operations of that sort. I haven't really been able to get too far with the logic because I'm relatively new to declarative programming; please see below my incomplete(faulty) attempt:
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).
Now running ?- listmodel(1,L),size(L,N),part(L,N,DL).
will produce DL=[]
because that is what it gets initialized to in the first add_tail
call in the part
predicate. I can't seem to figure out how to store all elements in a list that's preserved through the recursion.
Any help/direction of any kind will be appreciated. I'm stuck here since over 23 hours 10 minutes now.
Thanks.
This should do it:
part([], _, []). part(L, N, [DL|DLTail]) :- length(DL, N), append(DL, LTail, L), part(LTail, N, DLTail).
Base case is first/last arguments are empty lists.
Recursive step takes a fresh list of N elements, takes the first N elements from L (which will be one of the items of the third argument) and calls recursively.
Want to combine versatility and favorable termination properties? Use clpfd !
:- use_module(library(clpfd)).
First, we define list_prefix_n_suffix/4
. list_prefix_n_suffix(Zs,Xs,N,Ys)
is logically equivalent to both append (Xs,Ys,Zs), length (Xs,N)
and length (Xs,N), append (Xs,Ys,Zs)
, but has better universal termination behavior than either 1 one!
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).
Some sample queries for list_prefix_n_suffix/4
:
?- list_prefix_n_suffix([a,b,c], Xs,, Ys). . % 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, , Ys). . % 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
Based upon above list_prefix_n_suffix/4
we define 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).
Sample queries using 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
Works just like it should!
Without resorting to using alternative control-flow mechanisms like prolog-coroutining . 不求助于使用替代控制流机制,例如prolog-coroutining 。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.