Did you know ... | Search Documentation: |

Pack ltools -- README.md |

This module contains predicates for list manipulation in Prolog. It is inspired by Python's itertools and more-itertools modules.

The library was tested on SWI prolog. However, it should be easy to make it work also on other Prolog systems, since few built-in predicates were used.

In SWI, you can install it with:

?- pack_install('https://github.com/damianoazzolini/ltools').

Then

?- use_module(library(ltools)). true.

and you are ready to go.

The source code is documented and should contain the explanation of each predicate, together with examples. Furthermore, also tests can guide you with several examples.

Available predicates:

- [99, 111, 117, 110, 116, 47, 50]
- [99, 111, 117, 110, 116, 47, 51]
- [99, 121, 99, 108, 101, 47, 50]
- [114, 101, 112, 101, 97, 116, 47, 50]
- [114, 101, 112, 101, 97, 116, 47, 51]
- [97, 99, 99, 117, 109, 117, 108, 97, 116, 101, 47, 51]
- [98, 97, 116, 99, 104, 101, 100, 47, 51]
- [115, 108, 105, 99, 101, 47, 51]
- [115, 108, 105, 99, 101, 47, 52]
- [112, 97, 105, 114, 119, 105, 115, 101, 47, 50]
- [99, 104, 117, 110, 107, 101, 100, 47, 51]
- [100, 105, 118, 105, 100, 101, 47, 51]
- [115, 112, 108, 105, 116, 95, 97, 116, 95, 105, 110, 100, 101, 120, 47, 52]
- [119, 105, 110, 100, 111, 119, 47, 51]
- [119, 105, 110, 100, 111, 119, 47, 52]
- [116, 114, 105, 112, 108, 101, 119, 105, 115, 101, 47, 50]
- [105, 110, 116, 101, 114, 115, 112, 101, 114, 115, 101, 47, 51]
- [105, 110, 116, 101, 114, 115, 112, 101, 114, 115, 101, 47, 52]
- [112, 97, 100, 100, 101, 100, 95, 114, 105, 103, 104, 116, 47, 52]
- [112, 97, 100, 100, 101, 100, 95, 108, 101, 102, 116, 47, 52]
- [114, 101, 112, 101, 97, 116, 95, 101, 97, 99, 104, 47, 51]
- [99, 97, 114, 116, 101, 115, 105, 97, 110, 95, 112, 114, 111, 100, 117, 99, 116, 47, 50]
- [112, 101, 114, 109, 117, 116, 97, 116, 105, 111, 110, 115, 47, 50]
- [112, 101, 114, 109, 117, 116, 97, 116, 105, 111, 110, 115, 47, 51]
- [99, 111, 109, 98, 105, 110, 97, 116, 105, 111, 110, 115, 47, 51]
- [99, 111, 109, 98, 105, 110, 97, 116, 105, 111, 110, 115, 95, 119, 105, 116, 104, 95, 114, 101, 112, 108, 97, 99, 101, 109, 101, 110, 116, 47, 51]
- Details and usage.
count(+Start:int, -N:int) ?- count(1, N), N = 1 ; N = 2 ; N = 3 ; ...

Unifies

`N`with a number starting from`Start`and up to infinity.count(+Start:int, +Step:int, -N:int) ?- count(2,2,N), N = 2 ; N = 4 ; N = 6 ; ...

Unifies

`N`with a number starting from`Start`and up to infinity with step`Step`.cycle(+List, -El) ?- cycle([1,2], El), El = 1 ; El = 2 ; El = 1 ; El = 2 ; ...

Cycles through the elements

`El`of the list`List`.repeat(El,El) ?- repeat(1,El), El = 1 ; El = 1 ; ...

Repeats

`El`indefinitely.repeat(El,N,El) ?- repeat(1,2,El), El = 1 ; El = 1

Repeats

`El`up to N times.accumulate(+Predicate, +L:list, -V:list) ?- accumulate(plus, [1,2,4], L), L = [1, 3, 7] ?- accumulate(times, [1,2,4], L), L = [1, 2, 8]

Accumulates the list

`L`according the predicate`Predicate`.`Predicate`can be`times`

or`plus`

. This is essentially a wrapper for scanl/4.batched(+L:list, +N:int, -V:list) ?- batched([1,2,4,5,6], 3, V), V = [1,2,4] ; V = [5,6]

Creates batches of size

`N`from the list`L`, computes all on backtracking. The last one may of length less than`N`.slice(+L:list, +Start:int, +End:int, -S:list) ?- slice([1,2,4,5,6], 2, S), S = [1, 2].

Unifies

`S`with the sub list extracted from`L`between`0`

and the`End`index.slice(+L:list, +Start:int, +End:int, -S:list) ?- slice([1,2,4,5,6], 0, 10, S), S = [1, 2, 4, 5, 6].

Unifies

`S`with the sub list extracted from`L`between Start and`End`indexes counting from 1.pairwise(+List, -S:list) ?- pairwise([1,2,3], S), S = [1, 2] ; S = [2, 3]. ?- pairwise([1], S), false.

Unifies in backtracking each element of

`L`taken pairwise with`S`.cartesian_product(+List:list, -P:list) ?- cartesian_product([[1,2,3],[4,5,6]],P). P = [1, 4] ; P = [1, 5] ; P = [1, 6] ; P = [2, 4] ; P = [2, 5] P = [2, 6] ; P = [3, 4] ; P = [3, 5] ; P = [3, 6].

Computes the cartesian product of the input list of lists.

permutations(+List:list, -P:list) permutations(+List:list, +Len:int -P:list) ?- permutations([1, 2, 3, 4], 2, Res). Res = [1, 2] ; Res = [1, 3] ; Res = [1, 4] ; Res = [2, 1] ; Res = [2, 3] ; Res = [2, 4] ; Res = [3, 1] ; Res = [3, 2] ; Res = [3, 4] ; Res = [4, 1] ; Res = [4, 2] ; Res = [4, 3]

Computes the permutations of length

`Len`of the input list`List`. If`Len`is not provided, it defaults to the length of the input list`List`.combinations(+List:list, +Len:int -P:list) ?- combinations([1, 2, 3, 4], 2, Res). Res = [1, 2] ; Res = [1, 3] ; Res = [1, 4] ; Res = [2, 3] ; Res = [2, 4] ; Res = [3, 4]

Computes the combinations of the input list

`List`.combinations_with_replacements(+List:list, +Len:int -P:list) ?- combinations_with_replacements([1, 2, 3, 4], 2, Res). Res = [1, 1] ; Res = [1, 2] ; Res = [1, 3] ; Res = [1, 4] ; Res = [2, 2] ; Res = [2, 3] ; Res = [2, 4] ; Res = [3, 3] ; Res = [3, 4] Res = [4, 4]

Computes the combinations with replacements of the input list

`List`.chunked(+List:list, +Size:int, -Chunk:list) ?- chunked([1, 2, 3, 4, 5, 6], 3, L). L = [1, 2, 3] ; L = [4, 5, 6] ?- chunked([1, 2, 3, 4, 5], 3, L). L = [1, 2, 3] L = [4, 5]

Splits the list

`List`into chunks of size`Size`and unifies the result with`Chunk`. If the length of the list is not divisible by`Size`, the last chunk will be of length less than`Size`.divide(+List:list, +Parts:int, -Divided:list) ?- divide([1, 2, 3, 4, 5, 6], 2, L). L = [1, 2, 3] ; L = [4, 5, 6] ?- divide([1, 2, 3, 4, 5,6,7], 3, L). L = [1, 2, 3] ; L = [4, 5, 6] ; L = [7]

Divides the list

`List`into`Parts`parts of equal length. If the length of the list is not divisible by`Parts`, the last part will be shorter.split_at_index(+List:list, +Pos:int, -L0:list, -L1:List) ?- split_at_index([1, 2, 3, 4, 5, 6], 2, L0,L1). L0 = [1, 2], L1 = [3, 4, 5, 6] ?- split_at_index([1, 2, 3, 4, 5, 6], 0, L0,L1). L0 = [], L1 = [1, 2, 3, 4, 5, 6] ?- split_at_index([1, 2, 3, 4, 5, 6], 7, L0,L1). false

Splits the list

`List`at position`Pos`, starting from 0, and unifies`L0`and`L1`with the resulting lists. The index`Pos`will be in`L1`. Fails if`Pos`is greater that the length of the list.window(+List:list, +Size:int, +Step:int, -Res:list) window(+List:list, +Size:int, -Res:list) ?- window([1, 2, 3], 2, 1, Res). Res = [1, 2] ; Res = [2, 3] ?- window([1, 2, 3], 2, 2, Res). Res = [1, 2] ?- window([1, 2, 3, 4], 2, 2, Res). Res = [1, 2] ; Res = [3, 4]

Unifies

`Res`with a sliding window of size`Size`of`List`, which increments each time by`Step`. If`Step`is not provided, it defaults to 1.triplewise(+List, -S:list) ?- triplewise([1, 2, 3, 4], Res). Res = [1, 2, 3] ; Res = [2, 3, 4] ?- triplewise([1, 2], Res). false

Unifies in backtracking each element of

`L`taken triplewise with`S`.intersperse(+List:list, +Value, +Step:int, -Res). intersperse(+List:list, +Value, -Res). ?- intersperse([1, 2, 3, 4], 10, 3, Res) Res = [1, 2, 3, 10, 4] ?- intersperse([1, 2, 3, 4], 10, 1, Res). Res = [1, 10, 2, 10, 3, 10, 4, 10]

Interleaves the elements of the list

`List`with the element`Value`each`Step`positions and unifies the result with Res. If`Step`is not provided it defaults to 1.padded_right(+List:list, +Element, +Length:int, -Res:list). padded_left(+List:list, +Element, +Length:int, -Res:list). ?- padded_right([1, 2, 3, 4], a, 1, Res). Res = [1, 2, 3, 4] ?- padded_left([1, 2, 3, 4], a, 1, Res). Res = [1, 2, 3, 4] ?- padded_right([1, 2, 3, 4], a, 7, Res). Res = [1, 2, 3, 4, a, a, a] ?- padded_left([1, 2, 3, 4], a, 7, Res). Res = [a, a, a, 1, 2, 3, 4]

Unifies the list

`Res`with the list`List`padded right (resp. left) with the element`Element`repeated until length`Length`is reached.repeat_each(+List:list, +Times:int, -Res:list) ?- repeat_each([1, 2, 3, 4], 3, Res). Res = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4] ?- repeat_each([1, 2, 3, 4], 1, Res). Res = [1, 2, 3, 4]

Repeats each element in the list

`List``Times`times and unifies the result with`Res`.

Pull requests or issues, also to request further predicates - anything is welcome.

This software is provided as it is. It may contain bugs.