Related
I'd like to create a predicate arrayLEQ(L,N) that is true when L = [1,2,3,...,N].
I tried to do it recursively:
arrayLEQ(L,N) :- arrayLEQ([],L,1,N).
arrayLEQ(L1,L2,N,N) :- append(L1,[N],L2).
arrayLEQ(L1,L2,F,N) :- Fnext is F+1, append(L1,[F],L1n), arrayLEQ(L1n,L2,Fnext,N).
At first I thought that it will work, but sadly it doesn't.
When I do:
?- arrayLEQ(L,5) I get L = [1,2,3,4,5] which is the right answer, but Prolog is ready to look for another answer, which is not wanted.
Would you mind explaining to me what I did wrong and why Prolog tries to look for another answer to this predicate, even if it doesn't exist.
Let's have a look at tracer after the first query succeed:
?- arrayLEQ(L,5).
L = [1,2,3,4,5].
more
Redo:arrayLEQ([1, 2, 3, 4], _5040, 5, 5)
Call:_5844 is 5+1
Exit:6 is 5+1
Call:lists:append([1, 2, 3, 4], [5], _5854)
Exit:lists:append([1, 2, 3, 4], [5], [1, 2, 3, 4, 5])
Call:...
Call:_5880 is 6+1
Exit:7 is 6+1
Call:lists:append([1, 2, 3, 4, 5], [6], _5890)
Exit:lists:append([1, 2, 3, 4, 5], [6], [1, 2, 3, 4, 5, 6])
Call:arrayLEQ([1, 2, 3, 4, 5, 6], _5040, 7, 5)
Call:_5922 is 7+1
Exit:8 is 7+1
Call:lists:append([1, 2, 3, 4, 5, 6], [7], _5932)
Exit:lists:append([1, 2, 3, 4, 5, 6], [7], [1, 2, 3, 4, 5, 6, 7])
Call:arrayLEQ([1, 2, 3, 4, 5, 6, 7], _5040, 8, 5)
Call:_5970 is 8+1
Exit:9 is 8+1
and so on...
You can see that your program keeps adding element into the list, without stopping. So there are two solutions:
Adding a cut (!): arrayLEQ(L1,L2,N,N):- !, append(L1,[N],L2). It works but maybe (in my opinion) there is a better solution.
When adding an element, you don't check if you have already passed the threshod you set (in this case 5). So you just have to add F < N before doing Fnext is F+1. So: arrayLEQ(L1,L2,F,N) :- F < N, Fnext is F+1, append(L1,[F],L1n), arrayLEQ(L1n,L2,Fnext,N). (personally i prefer this solution)
So the query now (with second solution):
?- arrayLEQ(L,5).
L = [1, 2, 3, 4, 5].
more.
false.
I suggest you to not use append/3 because in this case is not necessary at all and write someting like this:
orderedList(L,N):-
orderedList(L,1,N).
orderedList([N],N,N). %you can add a cut ! here, to avoid further search
orderedList([H|T],C,N):-
C < N,
H is C,
C1 is C+1,
orderedList(T,C1,N).
?- orderedList(L,5).
L = [1, 2, 3, 4, 5]
more
false
Then if you need to return an empty list, wou can add a predicate to handle this case easily... BTW check also the question linked in the comments by #repeat
I am trying to change a[0][0] without changing the matrix b. Is there an easy way to do this? I tried to use b = list(a) and b = a[:] but no luck.
a = [[1,2,3,4],[1,2,3,4]]
b = a
print(a)
print(b)
a[0][0] = "WWWW"
print(a)
print(b)
Output:
[[1, 2, 3, 4], [1, 2, 3, 4]]
[[1, 2, 3, 4], [1, 2, 3, 4]]
[['WWWW', 2, 3, 4], [1, 2, 3, 4]]
[['WWWW', 2, 3, 4], [1, 2, 3, 4]]
This worked but it seems like there could be a better way?
a = [[1,2,3,4],[1,2,3,4]]
b = [[0,0,0,0], [0,0,0,0]]
for i in range(len(a)):
for j in range(len(a[i])):
b[i][j] = a[i][j]
print(a)
print(b)
a[0][0] = "WWWW"
print(a)
print(b)
Output:
[[1, 2, 3, 4], [1, 2, 3, 4]]
[[1, 2, 3, 4], [1, 2, 3, 4]]
[['WWWW', 2, 3, 4], [1, 2, 3, 4]]
[[1, 2, 3, 4], [1, 2, 3, 4]]
Lists are mutable.
This link explains in detail what mutable objects are
This doesn't work in your code because, you are using nested lists. If you were to do just a[0]="something", this wouldn't reflect in b however if you do something like this a[0][0]="wow" this would.
b = a[:]
The nested list in both a and b still point towards the same block of memory.
To solve this try:
import copy
a = [[1,2,3,4],[1,2,3,4]]
b = copy.deepcopy(a)
Explained in detail here
How can I go about splitting a list into 2 separate lists based on every 5 numbers. This is what im trying to get it to look like.
list = [a,a,a,a,a,b,b,b,b,b,c,c,c,c,c,d,d,d,d,d]
newlista = [a,a,a,a,a,c,c,c,c,c]
newlistb = [b,b,b,b,b,d,d,d,d,d]
Ive been looking at itertools, not sure if im on the right path.
You can do this with list comprehension and slices:
In [1]: a, b, c, d, = 1, 2, 3, 4
In [2]: l = [a,a,a,a,a,b,b,b,b,b,c,c,c,c,c,d,d,d,d,d]
In [3]: [l[i:i+5] for i in range(0,15,10)]
Out[3]: [[1, 1, 1, 1, 1], [3, 3, 3, 3, 3]]
In [4]: [l[i:i+5] for i in range(5,20,10)]
Out[4]: [[2, 2, 2, 2, 2], [4, 4, 4, 4, 4]]
I have a big list of around 2000 numbers in the list. This is just an example of what I want.
I have list1=[1,2,3,4] and list2=[1,3,2,5]. I want it so that list1[i] will be used list2[i] times in the new list.
So for this example the new list would be:list3=[1,2,2,2,3,3,4,4,4,4,4]
The new list3 has 1x1, 3x2, 2x3, 5x4.
This isn't pretty and isn't particularly easy to understand, but works:
>>> list1 = [1, 2, 3, 4]
>>> list2 = [1, 3, 2, 5]
>>> import itertools
>>> list3 = list(itertools.chain(*[[list1[i]] * count for i, count in enumerate(list2)]))
>>> list3
[1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4]
Brief explanation...
You can multiply a list:
>>> [1] * 3
[1, 1, 1]
Using this in the list comprehension will get you a list-of-lists:
>>> [[list1[i]] * count for i, count in enumerate(list2)]
[[1], [2, 2, 2], [3, 3], [4, 4, 4, 4, 4]]
You can then use itertools to flatten the list as above.
list1=[1,2,3,4]
list2=[1,3,2,5]
list3 = []
for a, b in zip(list1, list2):
for i in range(b):
list3.append(a)
list3 == [1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4]
Another alternative:
list1=[1,2,3,4]
list2=[1,3,2,5]
z=[]
for x,y in zip(list1,list2):
z.extend([x] * y)
print z
Is there any way to select the second, third (etc) value from a value in a list in Groovy? I'm still very new to programming in general and am just wondering if there is an easy way to do this.
For example, if I have the list
[1, 2, 3, 4, 5, 6]
I want to select the next two values after each value using a for loop:
for 1: (1, 2, 3)
for 2: (2, 3, 4)
...and so on.
Is that easily possible? Thanks in advance!
If you're using groovy 1.8.1 or later, you can use the take and drop methods:
def foo = [1, 2, 3, 4, 5, 6]
foo.size().times { i ->
println foo.drop(i).take(3)
}
This will result in
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6]
[6]
If you want the iteration to stop at the last group of three, try something like this:
def foo = [1, 2, 3, 4, 5, 6]
if (foo.size() > 2) {
(foo.size() - 2).times { i ->
println foo.drop(i).take(3)
}
}
which gives
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
If you're not using Groovy 1.8.1+, then you can acheive a similar result by writing a function like so:
List split( List foo, int size ) {
(0..foo.size()-size).collect { foo[ it..it+size-1 ] }
}
Then, you can call this like:
split( [1, 2, 3, 4, 5, 6], 3 )
to print
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]