Prolog: Create a List from a selection of a given List - list

I want to write a predicate in Prolog, which creates a all possible segments of a given Size of a given List and returns the un-selected elements as a List.
My Code so far:
select_seg(List, Segment, Rest, Size ):-
select_seg(List, Segment, Rest, Size, Size).
select_seg(_,_,_,_, 0):- !.
select_seg(List, [Head_Segs|Tail_Segs],[Head_Rest|Tail_Rest], Size,Acc ):-
select(Head_Segs, List, Head_Rest),
Acc >= 0,
New_Acc is Acc - 1,
select_seg(Head_Rest, Tail_Segs, Tail_Rest, Size, New_Acc).
When I call this predicate with:
select_seg([1,2,3,4,5,6,7,8,9], Seg, R ,3 ).
It returns:
Seg = [1, 2, 3|_],
R = [[2, 3, 4, 5, 6, 7, 8, 9], [3, 4, 5, 6, 7, 8, 9], [4, 5, 6, 7, 8, 9]|_] ;
Seg = [1, 2, 4|_],
R = [[2, 3, 4, 5, 6, 7, 8, 9], [3, 4, 5, 6, 7, 8, 9], [3, 5, 6, 7, 8, 9]|_] ;
Seg = [1, 2, 5|_],
R = [[2, 3, 4, 5, 6, 7, 8, 9], [3, 4, 5, 6, 7, 8, 9], [3, 4, 6, 7, 8, 9]|_] ;
This is desired output, except that the list of remaining elements contain three lists for each element in the Segment the List of remaining elements, but should only contain the last one as following:
Seg = [1, 2, 3|_],
R = [4, 5, 6, 7, 8, 9]|_] ;
Seg = [1, 2, 4|_],
R = [3, 5, 6, 7, 8, 9]|_] ;
Seg = [1, 2, 5|_],
R = [3, 4, 6, 7, 8, 9]|_] ;
I tried everything, but I am not able to come up with the right solution.

It's combining select with a variant of select:
select_len_seg(Len, L, Seg, Rem) :-
length(Seg, Len),
select_len_seg_(Seg, L, L, Rem).
select_len_seg_([], _, R, R).
select_len_seg_([H|T], F, R, Rem) :-
% Preventing "duplicates" such as [3,2,1]
select_forward(H, F, F0),
select(H, R, R0),
select_len_seg_(T, F0, R0, Rem).
select_forward(E, [H|T], F) :-
select_forward_(T, H, E, F).
select_forward_(T, H, H, T).
select_forward_([H|T], _, E, F) :-
select_forward_(T, H, E, F).
Results in swi-prolog:
?- select_len_seg(3, [1,2,3,4,5,6,7,8,9], S, R).
S = [1, 2, 3],
R = [4, 5, 6, 7, 8, 9] ;
S = [1, 2, 4],
R = [3, 5, 6, 7, 8, 9] ;
...
S = [6, 7, 9],
R = [1, 2, 3, 4, 5, 8] ;
S = [6, 8, 9],
R = [1, 2, 3, 4, 5, 7] ;
S = [7, 8, 9],
R = [1, 2, 3, 4, 5, 6] ;
false.

Related

convert data from 2d to 3d numpy array

If I have a 2d array like:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
And I want to end up with a 3d array like:
array([[[0, 4, 8],
[1, 5, 9]],
[[2, 6, 10],
[3, 7, 11]]])
How should I reshape the array to get what I want?
Reshape and permute axes -
In [11]: a # Input array
Out[11]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [12]: a.reshape(-1,2,2).transpose(1,2,0)
Out[12]:
array([[[ 0, 4, 8],
[ 1, 5, 9]],
[[ 2, 6, 10],
[ 3, 7, 11]]])
With np.moveaxis -
np.moveaxis(a.reshape(-1,2,2), 0,-1)
Generalizing it and assuming that you want the length along the first axis as half of no. of columns -
In [16]: m,n = a.shape
In [17]: a.reshape(m,-1,2).transpose(1,2,0)
Out[17]:
array([[[ 0, 4, 8],
[ 1, 5, 9]],
[[ 2, 6, 10],
[ 3, 7, 11]]])
If that length is supposed to be 2 -
In [15]: a.reshape(m,2,-1).transpose(1,2,0)
Out[15]:
array([[[ 0, 4, 8],
[ 1, 5, 9]],
[[ 2, 6, 10],
[ 3, 7, 11]]])

Nested lists addition

I have a nested list called a:
a = [[0, 1, 2, 3, 4], [10, 11, 12, 13, 14]]
My desired output is a new list (b) containing the first list in a: [0, 1, 2, 3, 4]. Then I want to append to this list all of the values in [10, 11, 12, 13, 14] added to the last number in [0, 1, 2, 3, 4]:
b = [0, 1, 2, 3, 4, 14, 15, 16, 17, 18]
# Your First List
a =[[0, 1, 2, 3, 4], [10, 11, 12, 13, 14]]
# Your Second List which is initalized as empty.
b = []
# Adding first list from (a) which is a[0] into second list
# a[0] = [0, 1, 2, 3, 4]
# a[1] = [10, 11, 12, 13, 14]
b.extend(a[0])
# b = [0, 1, 2, 3, 4]
# I then want to append to this list all of the values in [10, 11, 12, 13, 14] added
# the last number in [0, 1, 2, 3, 4].
# a[0] = [0, 1, 2, 3, 4]
# a[0][-1] = 4
last_val = a[0][-1]
second_list = a[1] # [10, 11, 12, 13, 14]
for item in second_list:
b.append(item+last_val)
print(b)
# b = [0, 1, 2, 3, 4, 14, 15, 16, 17, 18]

Skipping list of lists elements

I have this nested list:
list = [[1, 2, 3, 4],
[2, 7, 2, 1],
[3, 3, 7, 5],
[4, 4, 1, 7]]
And I'm trying to skip the first list of this nested list, and the first element of each list. I want it to become like this:
list = [[7, 2, 1],
[3, 7, 5],
[4, 1, 7]]
So far I have this:
% skip first list in list of lists
skip_first_list([_|Tail], Tail).
% attemping to skip first element in each of the lists
skip_first_list([[_ | HeadTail] | Tail], X) :-
skip_first_list(Tail, R),
append(R, [HeadTail], X).
Which does not produce the correct result:
?- skip_first_list([[1, 2, 3, 4], [2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]], X).
X = [[2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]] ;
X = [[3, 3, 7, 5], [4, 4, 1, 7], [2, 3, 4]] ;
X = [[4, 4, 1, 7], [7, 2, 1], [2, 3, 4]] ;
X = [[3, 7, 5], [7, 2, 1], [2, 3, 4]] ;
false.
Whereas I'm after this answer:
X = [[7, 2, 1], [3, 7, 5], [4, 1, 7]]
My result so far seems to be showing I'm appending in a reverse/incorrect order, How can I fix this? I don't really understand what order Prolog evaluates expressions. Any any would be appreciated.
Well the specification is that you provide a list of lists and that:
the first sublist is ignored (not part of the output); and
that for the remaining sublists, all heads are ignored as well.
So we better split this into two predicates:
remove_heads/2, which removes the heads of all sublists; and
remove_upper_left/2 which remove the first sublist, and then uses the above predicate to pop the heads of the sublists.
We can perform remove_heads/2 for instance with recursion:
remove_heads([],[]).
remove_heads([[_|H]|T],[H|T2]) :-
remove_heads(T,T2).
finally our remove_upper_left/2 simply ignores the head of the list, and makes a call to remove_heads with the tail:
remove_upper_left([_|T],T2) :-
remove_heads(T,T2).
Or in full:
remove_heads([],[]).
remove_heads([[_|H]|T],[H|T2]) :-
remove_heads(T,T2).
remove_upper_left([_|T],T2) :-
remove_heads(T,T2).
This then produces:
?- remove_upper_left([[1, 2, 3, 4], [2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]],X).
X = [[7, 2, 1], [3, 7, 5], [4, 1, 7]].
and works in the opposite direction as well:
?- remove_upper_left(X, [[1, 2, 3, 4], [2, 7, 2, 1], [3, 3, 7, 5], [4, 4, 1, 7]]).
X = [_G1364, [_G1370, 1, 2, 3, 4], [_G1376, 2, 7, 2, 1], [_G1382, 3, 3, 7, 5], [_G1388, 4, 4, 1|...]].
So here it prepends a variable to every list, and prepends a variable (possibly a sublist) to the output.
Furthermore we have here two predicates at the price of one: we can also use remove_heads/2 in the future if we want to pop the heads of all the sublists in a list of lists.

Understanding Python list.append behavior

Why in the following example is appending to the big_l in the for loop changes also the last lists already added to the big_l?
l=[1,2,3,4,5]
big_l=[]
def f(ll):
x=ll.pop(0)
ll.append(x)
return ll
for i in range(4):
big_l.append(l)
print l,big_l
l=f(l)
It prints:
[1, 2, 3, 4, 5] - [[1, 2, 3, 4, 5]]
[2, 3, 4, 5, 1] - [[2, 3, 4, 5, 1], [2, 3, 4, 5, 1]]
[3, 4, 5, 1, 2] - [[3, 4, 5, 1, 2], [3, 4, 5, 1, 2], [3, 4, 5, 1, 2]]
[4, 5, 1, 2, 3] - [[4, 5, 1, 2, 3], [4, 5, 1, 2, 3], [4, 5, 1, 2, 3], [4, 5, 1, 2, 3]]

Reverse Part of a List

Take list foo
foo = [5, 6, 7, 8, 9, 10, 11, 12]
How can I reverse only the elements of indices x to y within the list?
For example:
x = 1
y = 5
# reverse foo[x:y]
foo = [5, 9, 8, 7, 6, 10, 11, 12]
Python allows you to assign to slices
Slicings may be used as expressions or as targets in assignment or del
statements
thus it's possible to do everything on one line:
foo[x:y] = foo[y-1:x-1:-1]
Note thatfoo[y-1:x-1:-1] has the same meaning as foo[x:y][::-1].
It's as simple as:
foo[x:y] = foo[y - 1:x - 1:-1]
For example:
>>> foo = [5, 6, 7, 8, 9, 10, 11, 12]
>>> foo[1:5] = foo[4:0:-1]
>>> foo
[5, 9, 8, 7, 6, 10, 11, 12]
def reverse(l, x, y):
l[x:y+1] = l[y:x-1:-1]
foo = [5, 6, 7, 8, 9, 10, 11, 12]
x = 1
y = 4
reverse(foo, x, y)
print(foo) # [5, 9, 8, 7, 6, 10, 11, 12]