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).
Related
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.
I'm writing a simple code generating a simple list with 5 numbers whose first variable should be positive and I'm trying to understand why this code fails
test([H|T]) :- H > 0, length(T,4).
when I call with
length(X,5), test(X).
it shows me the following error:
ERROR: Arguments are not sufficiently instantiated
When I debug the code, the H variable in test isn't instantiated.
Anyone know why?
The issue here is that your rule for test([H|T]) doesn't describe in Prolog that H is a positive integer. It only tests if H > 0, which fails since H has not instantiation. Just attempting to compare an uninstantiated variable with a number (H > 0 in this case) doesn't cause Prolog to assume you intended H to be a number, and further, doesn't instantiate H.
Further, your rule for test/1 doesn't describe the rest of the list (T) other than to force that it be length 4. Since you're query establishes the rule that the length of the original list be 5, this stipulation is redundant.
You appear to be wanting to define test(L) such that it means L is an arbitrary list of positive integers. This is generally done using CLP(FD):
:- use_module(library(clpfd)).
test(X) :- X ins 1..10000.
This rule says that X is a list whose values are in the range 1 to 10000. The appropriate query to generate the lists of length 5 would then be:
?- length(X, 5), test(X), label(X).
X = [1, 1, 1, 1, 1] ;
X = [1, 1, 1, 1, 2] ;
X = [1, 1, 1, 1, 3] ;
X = [1, 1, 1, 1, 4] ;
X = [1, 1, 1, 1, 5] ;
...
If you want to restrict it further and say that elements need to be unique, you can use all_different/1:
test(X) :- X ins 1..10000, all_different(X).
?- length(X, 5), test(X), label(X).
X = [1, 2, 3, 4, 5] ;
X = [1, 2, 3, 4, 6] ;
X = [1, 2, 3, 4, 7] ;
X = [1, 2, 3, 4, 8] ;
X = [1, 2, 3, 4, 9] ;
X = [1, 2, 3, 4, 10] ;
...
Using np.argpartition, it does not sort the entire array. It only guarantees that the kth element is in sorted position and all smaller elements will be moved before it. Thus, the first k elements will be the k-smallest elements
>>> num = 3
>>> myBigArray=np.array([[1,3,2,5,7,0],[14,15,6,5,7,0],[17,8,9,5,7,0]])
>>> top = np.argpartition(myBigArray, num, axis=1)[:, :num]
>>> print top
[[5 0 2]
[3 5 2]
[5 3 4]]
>>> myBigArray[np.arange(myBigArray.shape[0])[:, None], top]
[[0 1 2]
[5 0 6]
[0 5 7]]
This returns the k-smallest values of each column. Note that these may not be in sorted order.I use this method because To get the top-k elements in sorted order in this way takes O(n + k log k) time
I want to get the k-smallest values of each column in sorted order, without increasing the time complexity.
Any suggestions??
To use np.argpartition and maintain the sorted order, we need to use those range of elements as range(k) instead of feeding in just the scalar kth param -
idx = np.argpartition(myBigArray, range(num), axis=1)[:, :num]
out = myBigArray[np.arange(idx.shape[0])[:,None], idx]
You can use the exact same trick that you used in the case of rows; combining with #Divakar's trick for sorting, this becomes
In [42]: num = 2
In [43]: myBigArray[np.argpartition(myBigArray, range(num), axis=0)[:num, :], np.arange(myBigArray.shape[1])[None, :]]
Out[43]:
array([[ 1, 3, 2, 5, 7, 0],
[14, 8, 6, 5, 7, 0]])
A bit of indirect indexing does the trick. Pleaese note that I worked on rows since you started off on rows.
fdim = np.arange(3)[:, None]
so = np.argsort(myBigArray[fdim, top], axis=-1)
tops = top[fdim, so]
myBigArray[fdim, tops]
# array([[0, 1, 2],
[0, 5, 6],
[0, 5, 7]])
A note on argpartition with range argument: I strongly suspect that it is not O(n + k log k); in any case it is typically several-fold slower than a manual argpartition + argsort see here
I have a set of lists that I want to compare firstly the sum values of the lists and then individual elements in the event of two or more lists having the same value.
my_list1 = [2, 3, 2, 4, 5]
my_list2 = [1, 3, 2, 3, 2]
my_list3 = [1, 1, 2, 2, 2]
my_list4 = [3, 2, 2, 4, 5]
Logic testing for an outright winner is fine but the problem I am having is isolating the lists in the event of a draw – So in the scenario above my_list1 and my_list4 would be isolated for further logic testing as their totals both come to 16.
This is what I have so far
my_list1=[1,1,2,2,2]
my_list2=[1,1,1,1,2]
my_list3=[2,2,1,1,2]
my_list1Total=sum(my_list1)
my_list2Total=sum(my_list2)
my_list3Total=sum(my_list3)
if my_list1Total>my_list2Total and my_list1Total>my_list3Total:
print("List one has the higest score")
elif my_list2Total>my_list1Total and my_list2Total>my_list3Total:
print("List two has the higest score")
elif my_list3Total>my_list2Total and my_list3Total>my_list1Total:
print("List three has the higest score")
else:
print("Draw")
##so now I want to compare the lists with the same total but this time by the first element in the list. In this case it would be my_list1[0] and my_list3[0] that would be compared next. The winner having the highest value in position 0 of the drawing lists
I suggest creating a single list which holds all of your lists. Then you can use max on that list to find the largest element. Or, if you want the index of the list and not just its value, you can write a max-like method and use that instead.
#like the built-in function `max`,
#but returns the index of the largest element
#instead of the largest element itself.
def index_of_max(seq, key=lambda item:item):
return max(range(len(seq)), key=lambda idx: key(seq[idx]))
lists = [
[2, 3, 2, 4, 5],
[1, 3, 2, 3, 2],
[1, 1, 2, 2, 2],
[3, 2, 2, 4, 5]
]
idx = index_of_max(lists, key=lambda item: (sum(item), item[0]))
#add one to this result because Python lists are zero indexed,
#but the original numbering scheme started at one.
print "List # {} is largest.".format(idx+1)
Result:
List # 4 is largest.
A little explanation about key: it's a function that you pass to max, that it uses to determine the comparative value of two items in the sequence. It calls key(someItem) on both items, and whichever item has a larger result, is considered the maximum item between the two of them. The key function I used here returns a tuple. Due to the way tuple comparison works in Python, comparison is done by sum first, then using the first element of each list as a tie breaker.
If you're thinking "but what if the first elements are also the same? I want to use each following item as a tie breaker", then you can modify the key to compare all of them in turn.
idx = index_of_max(lists, key=lambda item: [sum(item)]+item)
I want to look in an array of elements. If an element exceeds a certain value x, replace it with another value y. It could be a bunch of elements that need to be replaced. Is there a function (code) to do this at once. I don't want to use for loop.
Does the any() function help here?
Thanks
I really don't know how one could possibly achieve such a thing without the if statement.
Don't know about any() but I gave it a try with map since you don't want a for loop. But, do note that the complexity order (Big O) is still n.
>>> array = [1, 2, 3, 4, 2, -2, -3, 8, 3, 0]
>>> array = map(lambda x: x if x < 3 else 2, array)
>>> array
[1, 2, 2, 2, 2, -2, -3, 2, 2, 0]
Basically, x if x < 3 else 2 works like If an element exceeds a certain value x, replaces it with another value y.