1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker and Richard O'Keefe 4 E-mail: jan@swi-prolog.org 5 WWW: https://www.swi-prolog.org 6 Copyright (c) 2002-2026, University of Amsterdam 7 VU University Amsterdam 8 SWI-Prolog Solutions b.v. 9 All rights reserved. 10 11 Redistribution and use in source and binary forms, with or without 12 modification, are permitted provided that the following conditions 13 are met: 14 15 1. Redistributions of source code must retain the above copyright 16 notice, this list of conditions and the following disclaimer. 17 18 2. Redistributions in binary form must reproduce the above copyright 19 notice, this list of conditions and the following disclaimer in 20 the documentation and/or other materials provided with the 21 distribution. 22 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 POSSIBILITY OF SUCH DAMAGE. 35*/ 36 37:- module(lists, 38 [ member/2, % ?X, ?List 39 memberchk/2, % ?X, ?List 40 append/2, % +ListOfLists, -List 41 append/3, % ?A, ?B, ?AB 42 prefix/2, % ?Part, ?Whole 43 select/3, % ?X, ?List, ?Rest 44 selectchk/3, % ?X, ?List, ?Rest 45 select/4, % ?X, ?XList, ?Y, ?YList 46 selectchk/4, % ?X, ?XList, ?Y, ?YList 47 nextto/3, % ?X, ?Y, ?List 48 delete/3, % ?List, ?X, ?Rest 49 nth0/3, % ?N, ?List, ?Elem 50 nth1/3, % ?N, ?List, ?Elem 51 nth0/4, % ?N, ?List, ?Elem, ?Rest 52 nth1/4, % ?N, ?List, ?Elem, ?Rest 53 last/2, % +List, -Element 54 proper_length/2, % @List, -Length 55 same_length/2, % ?List1, ?List2 56 reverse/2, % +List, -Reversed 57 permutation/2, % ?List, ?Permutation 58 flatten/2, % +Nested, -Flat 59 clumped/2, % +Items,-Pairs 60 subseq/3, % ?List, ?SubList, ?Complement 61 62 % Ordered operations 63 max_member/2, % -Max, +List 64 min_member/2, % -Min, +List 65 max_member/3, % :Pred, -Max, +List 66 min_member/3, % :Pred, -Min, +List 67 68 % Lists of numbers 69 sum_list/2, % +List, -Sum 70 max_list/2, % +List, -Max 71 min_list/2, % +List, -Min 72 numlist/3, % +Low, +High, -List 73 74 % set manipulation 75 is_set/1, % +List 76 list_to_set/2, % +List, -Set 77 intersection/3, % +List1, +List2, -Intersection 78 union/3, % +List1, +List2, -Union 79 subset/2, % +SubSet, +Set 80 subtract/3 % +Set, +Delete, -Remaining 81 ]). 82:- autoload(library(error), [must_be/2, instantiation_error/1]). 83:- autoload(library(pairs), [pairs_keys/2]). 84 85:- meta_predicate 86 max_member(, , ), 87 min_member(, , ). 88 89:- set_prolog_flag(generate_debug_info, false).
member(X, [One]).
121member(El, [H|T]) :- 122 member_(T, El, H). 123 124member_(_, El, El). 125member_([H|T], El, _) :- 126 member_(T, El, H).
132append([], L, L). 133append([H|T], L, [H|R]) :- 134 append(T, L, R).
143append(ListOfLists, List) :- 144 must_be(list, ListOfLists), 145 append_(ListOfLists, List). 146 147append_([], []). 148append_([L|Ls], As) :- 149 append(L, Ws, As), 150 append_(Ls, Ws).
append(Part, _, Whole).158prefix([], _). 159prefix([E|T0], [E|T]) :- 160 prefix(T0, T).
169select(X, [Head|Tail], Rest) :- 170 select3_(Tail, Head, X, Rest). 171 172select3_(Tail, Head, Head, Tail). 173select3_([Head2|Tail], Head, X, [Head|Rest]) :- 174 select3_(Tail, Head2, X, Rest).
182selectchk(Elem, List, Rest) :-
183 select(Elem, List, Rest0),
184 !,
185 Rest = Rest0.?- select(b, [a,b,c,b], 2, X). X = [a, 2, c, b] ; X = [a, b, c, 2] ; false.
206select(X, XList, Y, YList) :- 207 select4_(XList, X, Y, YList). 208 209select4_([X|List], X, Y, [Y|List]). 210select4_([X0|XList], X, Y, [X0|YList]) :- 211 select4_(XList, X, Y, YList).
217selectchk(X, XList, Y, YList) :-
218 select(X, XList, Y, YList),
219 !.225nextto(X, Y, [X,Y|_]). 226nextto(X, Y, [_|Zs]) :- 227 nextto(X, Y, Zs).
\+ Elem \=
H, which implies that Elem is not changed.
242delete([], _, []). 243delete([Elem|Tail], Del, Result) :- 244 ( \+ Elem \= Del 245 -> delete(Tail, Del, Result) 246 ; Result = [Elem|Rest], 247 delete(Tail, Del, Rest) 248 ). 249 250 251/* nth0/3, nth1/3 are improved versions from 252 Martin Jansche <martin@pc03.idf.uni-heidelberg.de> 253*/
264nth0(Index, List, Elem) :- 265 ( integer(Index) 266 -> '$seek_list'(Index, List, RestIndex, RestList), 267 nth0_det(RestIndex, RestList, Elem) % take nth det 268 ; var(Index) 269 -> List = [H|T], 270 nth_gen(T, Elem, H, 0, Index) % match 271 ; must_be(integer, Index) 272 ). 273 274nth0_det(0, [Elem|_], Elem) :- !. 275nth0_det(N, [_|Tail], Elem) :- 276 M is N - 1, 277 M >= 0, 278 nth0_det(M, Tail, Elem). 279 280nth_gen(_, Elem, Elem, Base, Base). 281nth_gen([H|Tail], Elem, _, N, Base) :- 282 M is N + 1, 283 nth_gen(Tail, Elem, H, M, Base).
293nth1(Index, List, Elem) :-
294 ( integer(Index)
295 -> Index0 is Index - 1,
296 '$seek_list'(Index0, List, RestIndex, RestList),
297 nth0_det(RestIndex, RestList, Elem) % take nth det
298 ; var(Index)
299 -> List = [H|T],
300 nth_gen(T, Elem, H, 1, Index) % match
301 ; must_be(integer, Index)
302 ).?- nth0(I, [a,b,c], E, R). I = 0, E = a, R = [b, c] ; I = 1, E = b, R = [a, c] ; I = 2, E = c, R = [a, b] ; false.
?- nth0(1, L, a1, [a,b]). L = [a, a1, b].
323nth0(V, In, Element, Rest) :- 324 var(V), 325 !, 326 generate_nth(0, V, In, Element, Rest). 327nth0(V, In, Element, Rest) :- 328 must_be(nonneg, V), 329 find_nth0(V, In, Element, Rest).
335nth1(V, In, Element, Rest) :- 336 var(V), 337 !, 338 generate_nth(1, V, In, Element, Rest). 339nth1(V, In, Element, Rest) :- 340 must_be(positive_integer, V), 341 succ(V0, V), 342 find_nth0(V0, In, Element, Rest). 343 344generate_nth(I, I, [Head|Rest], Head, Rest). 345generate_nth(I, IN, [H|List], El, [H|Rest]) :- 346 I1 is I+1, 347 generate_nth(I1, IN, List, El, Rest). 348 349find_nth0(0, [Head|Rest], Head, Rest) :- !. 350find_nth0(N, [Head|Rest0], Elem, [Head|Rest]) :- 351 M is N-1, 352 find_nth0(M, Rest0, Elem, Rest).
semidet if List is a list and multi if List is a partial list.
364last([X|Xs], Last) :- 365 last_(Xs, X, Last). 366 367last_([], Last, Last). 368last_([X|Xs], _, Last) :- 369 last_(Xs, X, Last).
proper_length(List, Length) :-
is_list(List),
length(List, Length).
383proper_length(List, Length) :-
384 '$skip_list'(Length0, List, Tail),
385 Tail == [],
386 Length = Length0.398same_length([], []). 399same_length([_|T1], [_|T2]) :- 400 same_length(T1, T2).
410reverse(Xs, Ys) :- 411 reverse(Xs, Ys, [], Ys). 412 413reverse([], [], Ys, Ys). 414reverse([X|Xs], [_|Bound], Rs, Ys) :- 415 reverse(Xs, Bound, [X|Rs], Ys).
If both Xs and Ys are provided and both lists have equal length
the order is |Xs|^2. Simply testing whether Xs is a permutation
of Ys can be achieved in order log(|Xs|) using msort/2 as
illustrated below with the semidet predicate is_permutation/2:
is_permutation(Xs, Ys) :- msort(Xs, Sorted), msort(Ys, Sorted).
The example below illustrates that Xs and Ys being proper lists is not a sufficient condition to use the above replacement.
?- permutation([1,2], [X,Y]). X = 1, Y = 2 ; X = 2, Y = 1 ; false.
451permutation(Xs, Ys) :- 452 '$skip_list'(Xlen, Xs, XTail), 453 '$skip_list'(Ylen, Ys, YTail), 454 ( XTail == [], YTail == [] % both proper lists 455 -> Xlen == Ylen 456 ; var(XTail), YTail == [] % partial, proper 457 -> length(Xs, Ylen) 458 ; XTail == [], var(YTail) % proper, partial 459 -> length(Ys, Xlen) 460 ; var(XTail), var(YTail) % partial, partial 461 -> length(Xs, Len), 462 length(Ys, Len) 463 ; must_be(list, Xs), % either is not a list 464 must_be(list, Ys) 465 ), 466 perm(Xs, Ys). 467 468perm([], []). 469perm(List, [First|Perm]) :- 470 select(First, List, Rest), 471 perm(Rest, Perm).
[] is distinct
from '[]'.
Ending up needing flatten/2 often indicates, like append/3 for appending two lists, a bad design. Efficient code that generates lists from generated small lists must use difference lists, often possible through grammar rules for optimal readability.
487flatten(List, FlatList) :- 488 flatten(List, [], FlatList0), 489 !, 490 FlatList = FlatList0. 491 492flatten(Var, Tl, [Var|Tl]) :- 493 var(Var), 494 !. 495flatten([], Tl, Tl) :- !. 496flatten([Hd|Tl], Tail, List) :- 497 !, 498 flatten(Hd, FlatHeadTail, List), 499 flatten(Tl, Tail, FlatHeadTail). 500flatten(NonList, Tl, [NonList|Tl]). 501 502 503 /******************************* 504 * CLUMPS * 505 *******************************/
Item-Count pairs that represents the run
length encoding of Items. For example:
?- clumped([a,a,b,a,a,a,a,c,c,c], R). R = [a-2, b-1, a-4, c-3].
519clumped(Items, Counts) :- 520 clump(Items, Counts). 521 522clump([], []). 523clump([H|T0], [H-C|T]) :- 524 ccount(T0, H, T1, 1, C), 525 clump(T1, T). 526 527ccount([H|T0], E, T, C0, C) :- 528 E == H, 529 !, 530 C1 is C0+1, 531 ccount(T0, E, T, C1, C). 532ccount(List, _, List, C, C).
545subseq(L, S, C), is_list(L) => subseq_(L, S, C). 546subseq(L, S, C), is_list(S), is_list(C) => subseq_(L, S, C). 547subseq(L, S, C) => 548 must_be(list_or_partial_list, L), 549 must_be(list_or_partial_list, S), 550 must_be(list_or_partial_list, C), 551 instantiation_error(L). 552 553subseq_([], [], []). 554subseq_([H|T0], T1, [H|C]) :- 555 subseq_(T0, T1, C). 556subseq_([H|T0], [H|T1], C) :- 557 subseq_(T0, T1, C). 558 559 560 /******************************* 561 * ORDER OPERATIONS * 562 *******************************/
572max_member(Max, [H|T]) => 573 max_member_(T, H, Max). 574max_member(_, []) => 575 fail. 576 577max_member_([], Max0, Max) => 578 Max = Max0. 579max_member_([H|T], Max0, Max) => 580 ( H @=< Max0 581 -> max_member_(T, Max0, Max) 582 ; max_member_(T, H, Max) 583 ).
594min_member(Min, [H|T]) => 595 min_member_(T, H, Min). 596min_member(_, []) => 597 fail. 598 599min_member_([], Min0, Min) => 600 Min = Min0. 601min_member_([H|T], Min0, Min) => 602 ( H @>= Min0 603 -> min_member_(T, Min0, Min) 604 ; min_member_(T, H, Min) 605 ).
?- max_member(@=<, X, [6,1,8,4]). X = 8.
619max_member(Pred, Max, [H|T]) => 620 max_member_(T, Pred, H, Max). 621max_member(_, _, []) => 622 fail. 623 624max_member_([], _, Max0, Max) => 625 Max = Max0. 626max_member_([H|T], Pred, Max0, Max) => 627 ( call(Pred, H, Max0) 628 -> max_member_(T, Pred, Max0, Max) 629 ; max_member_(T, Pred, H, Max) 630 ).
?- min_member(@=<, X, [6,1,8,4]). X = 1.
644min_member(Pred, Min, [H|T]) => 645 min_member_(T, Pred, H, Min). 646min_member(_, _, []) => 647 fail. 648 649min_member_([], _, Min0, Min) => 650 Min = Min0. 651min_member_([H|T], Pred, Min0, Min) => 652 ( call(Pred, Min0, H) 653 -> min_member_(T, Pred, Min0, Min) 654 ; min_member_(T, Pred, H, Min) 655 ). 656 657 658 /******************************* 659 * LISTS OF NUMBERS * 660 *******************************/
666sum_list(Xs, Sum) :- 667 sum_list(Xs, 0, Sum). 668 669sum_list([], Sum0, Sum) => 670 Sum = Sum0. 671sum_list([X|Xs], Sum0, Sum) => 672 Sum1 is Sum0 + X, 673 sum_list(Xs, Sum1, Sum).
682max_list([H|T], Max) => 683 max_list(T, H, Max). 684max_list([], _) => fail. 685 686max_list([], Max0, Max) => 687 Max = Max0. 688max_list([H|T], Max0, Max) => 689 Max1 is max(H, Max0), 690 max_list(T, Max1, Max).
700min_list([H|T], Min) => 701 min_list(T, H, Min). 702min_list([], _) => fail. 703 704min_list([], Min0, Min) => 705 Min = Min0. 706min_list([H|T], Min0, Min) => 707 Min1 is min(H, Min0), 708 min_list(T, Min1, Min).
718numlist(L, U, Ns) :- 719 must_be(integer, L), 720 must_be(integer, U), 721 L =< U, 722 numlist_(L, U, Ns). 723 724numlist_(U, U, List) :- 725 !, 726 List = [U]. 727numlist_(L, U, [L|Ns]) :- 728 L2 is L+1, 729 numlist_(L2, U, Ns). 730 731 732 /******************************** 733 * SET MANIPULATION * 734 *********************************/
log(N) and the predicate may cause a
resource-error. There are no other error conditions.
743is_set(Set) :-
744 '$skip_list'(Len, Set, Tail),
745 Tail == [], % Proper list
746 sort(Set, Sorted),
747 length(Sorted, Len).log(N).
767list_to_set(List, Set) :- 768 must_be(list, List), 769 number_list(List, 1, Numbered), 770 sort(1, @=<, Numbered, ONum), 771 remove_dup_keys(ONum, NumSet), 772 sort(2, @=<, NumSet, ONumSet), 773 pairs_keys(ONumSet, Set). 774 775number_list([], _, []). 776number_list([H|T0], N, [H-N|T]) :- 777 N1 is N+1, 778 number_list(T0, N1, T). 779 780remove_dup_keys([], []). 781remove_dup_keys([H|T0], [H|T]) :- 782 H = V-_, 783 remove_same_key(T0, V, T1), 784 remove_dup_keys(T1, T). 785 786remove_same_key([V1-_|T0], V, T) :- 787 V1 == V, 788 !, 789 remove_same_key(T0, V, T). 790remove_same_key(L, _, L).
802intersection([], _, Set) => 803 Set = []. 804intersection([X|T], L, Intersect) => 805 ( memberchk(X, L) 806 -> Intersect = [X|R], 807 intersection(T, L, R) 808 ; intersection(T, L, Intersect) 809 ).
820union([], L0, L) => 821 L = L0. 822union([H|T], L, Union) => 823 ( memberchk(H, L) 824 -> union(T, L, Union) 825 ; Union = [H|R], 826 union(T, L, R) 827 ).
838subset([], _) => true. 839subset([E|R], Set) => 840 memberchk(E, Set), 841 subset(R, Set).
853subtract([], _, R) => 854 R = []. 855subtract([E|T], D, R) => 856 ( memberchk(E, D) 857 -> subtract(T, D, R) 858 ; R = [E|R1], 859 subtract(T, D, R1) 860 )
List Manipulation
This library provides commonly accepted basic predicates for list manipulation in the Prolog community. Some additional list manipulations are built-in. See e.g., memberchk/2, length/2.
The implementation of this library is copied from many places. These include: "The Craft of Prolog", the DEC-10 Prolog library (LISTRO.PL) and the YAP lists library. Some predicates are reimplemented based on their specification by Quintus and SICStus.