Some good answers by the rule, but cannot get them all - list

These are my rules, where my problem lies:
get_row([H|_],1,H):-!.
get_row([_|T],I,X) :-
I1 is I-1,
get_row(T,I1,X).
get_column([],_,[]).
get_column([H|T], I, [R|X]):-
get_row(H, I, R),
get_column(T,I,X).
good_by_coulmns(Solution) :-
length(Solution, Length),
forall((between(1, Length, X),
get_column(Solution, X, Y)),
all_distinct(Y)).
createRow(Solution, Domain, Row) :-
maplist(member, Row, Domain),
all_distinct(Row),
good_by_coulmns(Solution).
%, write(Solution), nl.
tryToSolve(Domains, Solution) :-
maplist(createRow(Solution),
Domains, Solution),
length(Solution, L),
length(Domains, L),
good_by_coulmns(Solution).
The problem is, that the last rule generates about 20 good answers, but, after that it goes into an infinite loop. There is a debug write in the first rule.
It writes lines like these (with always changing numbers), while looping infinitely:
[[1, 2, 3, 4], [3, 1, 4, 2], [4, 3, 2, 1], [2, 4, 1, 3], _8544, _8550, _8556, _8562]
[[1, 2, 3, 4], [3, 4, 1, 2], _8532, _8538, _8544, _8550, _8556, _8562]
The solution, we wait is a 4x4 matrix. in the first line, if we cut out the first 4 elements, it is a good solution.
The number of variables starting with _ is always increasing, while the first line of the matrix([1,2,3,4]) is never changing.
Do you have any idea, what goes wrong here?
Actual query:
tryToSolve([[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]], [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]], [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]], [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]], L).

To identify the problem, I will use a failure-slice. In this I insert false goals into your program. By inserting these goals, I will reduce the number of inferences your program needs to execute. If that number is still infinite, then the visible part contains an error1.
?- D = [1,2,3,4], D4 = [D,D,D,D], tryToSolve([D4,D4,D4,D4], L), false.
good_by_coulmns(Solution) :-
length(Solution, Length), false,
forall((between(1, Length, X),get_column(Solution, X, Y)), all_distinct(Y)).
createRow(Solution, Domain, Row) :-
maplist(member, Row, Domain),
all_distinct(Row), % false, % terminates here
good_by_coulmns(Solution), false.
tryToSolve(Domains, Solution) :-
maplist(createRow(Solution), Domains, Solution), false,
length(Solution, L),
length(Domains, L),
good_by_coulmns(Solution).
This fragment does loop already. Therefore, there must be an error in the visible part. Note the variable Solution! It should be a list of fixed length to make length(Solution, Length) terminate, after all Length occurs here for the first time.
Suggestion: Put the goals length(Domains, L), length(Solution, L) first.
Some remarks on your program: forall/2 is a highly problematic construct. Avoid it at all cost. Nicely, the fragment does not contain it - that would have made the diagnosis much more complex.
Also, try to start with a shorter problem first - this simplifies the observation of termination.
How have I placed those false goals? Well, it was a bit of intuition and trial-and-error. Strictly speaking, any1 placement of false goals is ok that results in a still looping fragment. When considering all possibilities, that is ~2lines failure slices, those that are minimal are most interesting. For more, see failure-slice.
1 Actually, the precise preconditions are a bit more complex. Roughly, the obtained fragment must be pure to a certain degree.

Related

How to put in variable as list

I'm trying to make a program that for a sublist of numbers, uses index as a variable and selects each number from the list of lists
so if my numbest = [[1, 2, 3, 4, 5], [2, 4, 6, 8, 10], [3, 5, 7, 9, 11]]
I want to be able to call the function like this
column_sum(2, [[1, 2, 3, 4, 5], [2, 4, 6, 8, 10], [3, 5, 7, 9, 11]]) will add the numbers at index 2 in each sublist (3, 6, and 7) and will return the number 16."
I can't for the life of me figure out how to print
for i in numlist:
print numbest[index]
Looks like Python, so imma say that all you need to do is have a variable that is a running total, add up all the numbers that are the values at the index you specify, and then return that value.
Alexander is also right and if his way is easier for you, you can find resources https://www.w3schools.com/python/ref_func_sum.asp and https://www.w3schools.com/python/python_lists_comprehension.asp

Writting in sub-ndarray of a ndarray in the most pythonian way. Python 2

I have a ndarray like this one:
number_of_rows = 3
number_of_columns = 3
a = np.arange(number_of_rows*number_of_columns).reshape(number_of_rows,number_of_columns)
a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
But I want something like this:
array([[0, 100, 101],
[3, 102, 103],
[6, 7, 8]])
To do that I want to avoid to do it one by one, I rather prefer to do it in arrays or matrices, because later I want to extend the code.
Nothe I have change a submatrix of the initial matrix (in mathematical terms, in terms of this example ndarray). In the example the columns considered are [1,2] and the rows [0,1].
columns_to_keep = [1,2]
rows_to_keep = [0,1]
My first try was to do:
a[rows_to_keep,:][:,columns_to_keep] = np.asarray([[100,101],[102,103]])
However this doesn't modify the initial a, I am not having any error, so a=
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
So I have implemented a piece of code that goes do the job:
b = [[100, 101],[102, 103]]
for i in range(len(rows_to_keep)):
a[i,columns_to_keep] = b[i]
Al thought the previous lines do the job I am wondering how to do it slicing and in a faster fashion. Also in a way that with:
columns_to_keep = [0,2]
rows_to_keep = [0,2]
the desired output is
array([[100, 1, 101],
[3, 4, 5],
[102, 7, 103]]).
Many thanks!
Indexing with lists like [1,2] is called advanced indexing. By itself it produces a copy, not a view. You have to use one indexing expression, not two to assign or change values. That is a[[1,2],:] is a copy, a[[1,2],:][:,[1,2]] += 100 modifies that copy, not the original a.
In [68]: arr = np.arange(12).reshape(3,4)
Indexing with slices; this is basic indexing:
In [69]: arr[1:,2:]
Out[69]:
array([[ 6, 7],
[10, 11]])
In [70]: arr[1:,2:] += 100
In [71]: arr
Out[71]:
array([[ 0, 1, 2, 3],
[ 4, 5, 106, 107],
[ 8, 9, 110, 111]])
Doing the same indexing with lists requires arrays that 'broadcast' against each other. ix_ is a handy way of generating these:
In [73]: arr[np.ix_([1,2],[2,3])]
Out[73]:
array([[106, 107],
[110, 111]])
In [74]: arr[np.ix_([1,2],[2,3])] -= 100
In [75]: arr
Out[75]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
Here's what ix_ produces - a tuple of arrays, one is (2,1) in shape, the other (1,2). Together they index a (2,2) block:
In [76]: np.ix_([1,2],[2,3])
Out[76]:
(array([[1],
[2]]), array([[2, 3]]))
For the continuous rows and columns case, you can use basic slicing like this:
In [634]: a
Out[634]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [635]: b = np.asarray([[100, 101],[102, 103]])
In [636]: a[:rows_to_keep[1]+1, columns_to_keep[0]:] = b
In [637]: a
Out[637]:
array([[ 0, 100, 101],
[ 3, 102, 103],
[ 6, 7, 8]])

Prolog exercise with Lists

I would be grateful if someone help me with the underneath exercise
If I have the prolog predicate **split_list(Limit,List,High,Low) (split_list/4)**
which has an integer list List, and one integer Limit, "returns" to list
High all the data of list List which are greater or equal to Limit and
the list Low which data are less of Limit. For instance:
?- split_list(2, [0, 2, 1, 3, 4], High, Low).
High = [2, 3, 4]
Low = [0, 1]
i) Give the backtracking definition of the predicate with less possible
controls.
ii)Define a predicate split_list_alt/3 with the same declarative meaning of [i)] (non Recursion definition)
//annotation:use predicates collection solutions(non backtracking)For instance:
?- split_list(0, [0, 2, 1, 3, 4], High, Low).
High = [0, 2, 1, 3, 4]
Low = []
Yes
You can use the following list of predicates to achieve this.
split_list(_,[],[],[]):-
!.
split_list(N,[LH|LT],[LH|AT],B):-
LH>=N,!,
split_list(N,LT,AT,B).
split_list(N,[LH|LT],A,[LH|BT]):-
split_list(N,LT,A,BT).

When changing data inside a list using a for loop, how do you append the list to a dictionary each time the loop iterates?

Basically, wanted to iterate over a list of numerical data to change it's contents, where the numerical at the start of the list is moved to the last, and then the data is shifted to the left. Whilst I have achieved this, as the printed contents of the loop gives the desired results, when trying to append the contents of said loop to said dictionary, it only does this for the final iteration. Here's my code:
minor=[1,2,3,4,5,6]
MNP = {'scale degree' : []
}
def patterns(scale):
for i in scale:
print (scale)
scale.insert(len(scale),scale[0])
del(scale[0])
MNP['scale degree'].append(scale)
using the function patterns, this is the output:
>>> patterns(minor)
the list, minor, is at the top of the page by the way.
output:
[1, 2, 3, 4, 5, 6]
[2, 3, 4, 5, 6, 1]
[3, 4, 5, 6, 1, 2]
[4, 5, 6, 1, 2, 3]
[5, 6, 1, 2, 3, 4]
[6, 1, 2, 3, 4, 5]
Yet when I try to print the contents of the list, scale degree, in the MNP dict, the result is:
MNP['scale degree']
[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]]
I am very perplexed by this result, it's as if the output changes depending on the operation called upon it?
Thank you for any help in advance. It's also worth noting that I've been stuck with this for a good amount of time, so if there's any resources out there that may help me understand similar occurrences i certainly wouldn't pass that up.
The reason this happens is because what you store in MNP['scale degree'] is only a reference to scale. So when you change scale, so do the entries in MNP['scale degree']. What you need to do to avoid this is copying scale each time you append it (i.e. creating a new list instead of adding a reference). You can do this with the copy module:
import copy
minor=[1,2,3,4,5,6]
MNP = {'scale degree' : []
}
def patterns(scale):
for i in scale:
print (scale)
scale.insert(len(scale),scale[0])
del(scale[0])
MNP['scale degree'].append(copy.copy(scale))
patterns(minor)
print(MNP['scale degree'])

Creating lists from elements in a bigger list

I have a list whose size is a multiple of 16. What I want to do is go through the list and get 16 elements and create a list from those values, and then store those values somewhere. After that I can either ignore them or remove them from the list, and continue this process until the bigger list is empty. What I was trying to do was to go through the list, and keep a counter of some sort to keep track of the number of elements that have been appended to the list. However, I have been stuck from there. Any ideas on how to accomplish on what I am trying to do? Any ideas would be greatly appreciated.
lst = [[1, 4, 0], [2, 4, 0], [3, 4, 0], [4, 4, 0], [1, 3, 0], [2, 3, 0], [3, 3, 0], [4, 3, 0], [1, 2, 0], [2, 2, 0], [3, 2, 0], [4, 2, 0], [1, 1, 0], [2, 1, 0], [3, 1, 0], [4, 1, 0],[1, 4, 0], [2, 4, 0], [3, 4, 0], [4, 4, 0], [1, 3, 0], [2, 3, 0], [3, 3, 0], [4, 3, 0], [1, 2, 0], [2, 2, 0], [3, 2, 0], [4, 2, 0], [1, 1, 0], [2, 1, 0], [3, 1, 0], [4, 1, 0]]
If I understand you correctly, you start with a list of size n, where n % 16 == 0. You want to end with n/16 lists of size 16. You can accomplish this pretty easily with a double for loop. The outer loop should go for n/16 iterations. the inner loop should go for 16 iterations. The outer loop creates a new list with each iteration. the inner loop takes elements from the original list and appends them to the newly created list.
Thank you for taking the time to respond to my question. After clicking on random links on the right hand side I came to answer that did exactly what I needed to happen.
Here is the solution to my problem:
[input[i:i+n] for i in range(0, len(input), n)]
The solution above goes through input and creates a list of size n.