I have some trouble when im trying to create a list with multiple sublists. I fail to see why my code is not working as expected.
solves(_, _, 0, _).
solves(Length, List, Stopcond, NList):- length(NL, Length),
append([NL], List, NList),
write(NList), nl,
N is Stopcond-1,
solves(Length, NList, N, NList2).
?- solves(3, [], 3, B).
I want B to be a list with three sublists, each with three intern variables.
When I write Nlist, it shows:
1. [[_G3207,_G3210,_G3213]]
2. [[_G3222,_G3225,_G3228],[_G3207,_G3210,_G3213]]
3. [[_G3237,_G3240,_G3243],[_G3222,_G3225,_G3228],[_G3207,_G3210,_G3213]]
4. B = [[_G3207, _G3210, _G3213]] .
But I don't understand why B becomes only the last element of the list. I want it to be the list on line 3. Can anyone see why and what i'm doing wrong? I'm pretty new to prolog.
I think this is what you intended
solves(_, List, 0, List).
solves(Length, List, Stopcond, NList2):- length(NL, Length),
append([NL], List, NList),
%write(NList), nl,
N is Stopcond-1,
solves(Length, NList, N, NList2).
What does your predicate try to do ( Ignoring the 3 element sublists for now )?
It appends a list of length Stopcond to the 2nd argument passed (List).
How do you recursively construct a list of length TL Given a list of length L?
You append a list of Length L with a list of Length 1 and try to construct a list of length TL-1 from our new list of length L+1.
As a base case, You know that to construct a list of length TL from a list of length TL, you just need to return the list as is.
Your predicate returns a bigger-list consisting of Stopcond smaller-lists of length Length each.
Recursively, A bigger-list of length Stopcond is a smaller-list of Length elements appended to a bigger-list of length Stopcond-1.
Base case: A bigger-list of size 0 is simply an empty list.
If we were just to consider 0's instead of the 3 element sublists,
solves(FinalList, 0, FinalList). % The result of appending a list of length 0 to the given list is the given list itself.
solves(List, StopCond, FinalList):- % Appends A list of length StopCond to List
Length1List = [0], % Create a list of length 1
append( Length1List, List, LengthPlus1List),
N is N-1,
solves( LengthPlus1List, N, FinalList).
Since you're new, It might help to write english comments against each line.
% Base case: stopping condition satisfied. List is the final List we need
solves(_, List, 0, List).
% Recursive case: We need to make one more list of length L and append/prepend it to List
solves(Length, List, Stopcond, NList2):-
length(NL, Length), % Create smaller-list of length Length
append([NL], List, NList), % Append it to the list we're building up
%write(NList), nl,
N is Stopcond-1,
solves(Length, NList, N, NList2). % Build Stopcond-1 more lists
Related
I am pretty new to Prolog, actually 4 days into it and I came across an exercise that states :
Given a list of N lists with N size each implement a predicate called reshape(X,Y)
so that it :
Collects the first elements of all lists into a list.
Collects the second elements of all lists lists into a list.
...
Collects the N elements of all lists into a list.
Collects all lists mentioned above into a new list.
An example would be :
reshape([[1,2,3],[4,5,6],[7,8,9]],X)
X = [[1,4,7],[2,5,8],[3,6,9]]
So here is my implementation :
% Insert at the end of a list
insert([],X,[X]).
insert([H|T1],X,[H|T2]) :- insert(T1,X,T2).
% Length of list
len([],L,L).
len([_|T],L,X) :-
L1 is L + 1,
len(T,L1,X).
len(L,X) :- len(L,0,X).
% Create a list of N empty lists
init_list(L,0,L) :- !.
init_list(L,N,X) :-
N1 is N-1,
insert(L,[],Y),
init_list(Y,N1,X).
init_list(N,X) :- init_list([],N,X).
% Assign each element of a list to the corresponding list.
assign([],[],[]).
assign([H1|T1],[H2|T2],[Y|T3]) :-
insert(H2,H1,Y),
assign(T1,T2,T3).
% Reshape :
reshape([],L,L).
reshape([H1|T1],X,Result):-
assign(H1,X,Y),
reshape(T1,Y,Result).
reshape(Input,Result) :-
len(Input,N),
init_list(N,X),
reshape(Input,X,Result).
So the basic idea is that I start by creating a list of N empty lists and then for each list say L of the input I assign/add each element of L to the corresponding list.
Now I would appreciate some input as I already said I am new to Prolog and can't even tell what the time complexity of my predicate is.The only thing I know for a fact is that it works.
Howerever is there a better way I can implement it?
What's the time complexity of my implementation ? It seems like polynomial time but I can't really tell.
Thanks in advance.
You can code an O(N) algorithm that just goes through each element once:
reshape([[]|Tail], []):-
maplist(=([]), Tail).
reshape(Input, [Result|RTail]):-
reshape(Input, LTail, Result),
reshape(LTail, RTail).
reshape([], [], []).
reshape([[Item|Tail]|LTail], [Tail|MTail], [Item|RTail]):-
reshape(LTail, MTail, RTail).
reshape/3 gets the list with every first element of the list of lists. Then reshape/2 builds all such lists recursively.
Test case:
?- reshape([[1,2,3],[4,5,6],[7,8,9]],X).
X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] ;
false.
I'm having difficulty with my assignment, I have to write 2 predicates:
remove_all/3 which removes all instances of a given element out of a list and output the list without the given variable, e.g.:
remove_all(a, [b,a,c,a,d], X)
gives
X = [b,c,d])
and
remove_list/3 which removes all elements of a given list out of another list and outputs the resulting list, e.g.:
remove_list([a,b], [b,a,c,a,d], X)
gives
X=[c,d].
This is what I have:
remove_all(Rema,[],[]).
remove_all(Rema,[Rema|X],Res) :-
remove_all(Rema,X,Res).
remove_all(Rema,[L|P],Res) :-
remove_all(Rema,P,NR), Res=[L|NR].
remove_list([],ListB, ListRes).
remove_list([H|Taila],ListB,ListRes) :-
member(H,ListB),
remove_all(H,ListB,ListRes),
remove_list(Taila,ListRes,ListRes) .
remove_list([S|Tailb],ListB,ListRes) :-
remove_list(Tailb, ListB, ListRes).
Now, my remove_all works fine, but not when I use it in my remove_list predicate, it will then only remove all the instances of the first element of the list which specifies which element are to be removed, for example:
?- remove_list([1,2],[1,2,3,2,1],F).
F = [2, 3, 2]
It only removes the 1's.
Anybody have any idea what to do?
I am trying to get my head wrap around lists in Prolog. To do this I am trying to create a sort of game. You pass in a list of numbers 1-9 that can be repeated, the list can be any length. The rules are that starting from the first element(e) you can only move to e+2 or e+3 until you get to the end. The goal is to "land" on the highest numbers. In essence it is kind of like hopscotch. The problem I am running into is determining all the possible permutation for paths. So far I have the following.
paths([], []). %empty list returns empty list
paths([X], [X]). %list with one element returns that one element
paths([X1, X2], [X1]). %list with 2 elements returns the first element
paths([X1, X2, X3], [X1,X3]). %list with three elements returns the first and third element
paths() :- % the recursive case for a list with 4+ elements
An list to use would be: [1,2,3,4,5,6,8,7,9,3,6,5,7,8,9]
I need to determine all possible paths using the rule mentioned about. I wish lists could be indexed in Prolog :(
Any logic guidance would be appreciated.
The requirements aren't completely clear, but it seems that:
The second argument is required to have the same first element as the
first argument (you "hop" on the first "square" first always, using
your hopscotch metaphore)
You aren't requiring that the last element of the first list be the
last element of the second list (you aren't requiring that you "land
on" the last "square").
An empty list succeeds with an empty list result (rather than just failing on an empty list - which is another valid approach).
Then this could be implemented as follows. You do not need many explicit 2- and 3-element list cases since they are handled by the recursive clause and simpler base cases.
path([], []).
path([X], [X]).
path([X,_|T], [X|R]) :- % hop over 1 element
path(T, R).
path([X,_,_|T], [X|R]) :- % hop over 2 elements
path(T, R).
For a simple example:
| ?- path([1,2,3,4,5,6], R).
R = [1,3,5] ? ;
R = [1,3,6] ? ;
R = [1,4,6] ? ;
R = [1,4]
yes
If I don't have your requirements exactly right, you should be able to adjust this to suit your needs as it shows how to handle a recursive case. It also sounds like you are headed in the direction of trying to optimize the values in your hops, which I shall also leave as an exercise.
This can also be done with a DCG (definite clause grammar)
path([]) --> [].
path([X]) --> [X].
path([X|T]) --> ([X,_] | [X,_,_]), path(T).
Which would be exercised:
| ?- phrase(path(R), [1,2,3,4,5,6]).
R = [1,3,5] ? ;
R = [1,3,6] ? ;
R = [1,4,6] ? ;
R = [1,4] ? ;
(1 ms) no
| ?-
In light of the extra requirement that the last step taken must be one that falls within the list, here is an updated version of the path/2 predicate:
path([], []).
path([X], [X]).
path([X,_], [X]).
path([X,_,Y|T], [X|R]) :- % hop over 1 element
path([Y|T], R).
path([X,_,_,Y|T], [X|R]) :- % hop over 2 elements
path([Y|T], R).
I think that there is a reason to avoid indexing: simplicity. If you decompose your problem, maybe you could start writing a step/3 predicate like
step([_,X|T],X,T).
step([_,_,X|T],X,T).
and then
paths([],[]).
paths(L,[X|Xs]) :- step(L,X,T), paths(T,Xs).
note: I don't understand very well your game, some example of playground and solution would be welcome.
%passing in a list and return all possible paths using K+2 or K+3 with K being the first element of the list.
%empty list returns empty list
%list with one element returns that one element
%list with 2 elements returns the first element
%list with three elements returns the first and third element
%list with four/four+ elements needs to be called recursively, prefix them with the first element and append them together
%RL means ReturnList
%FL means FinalList
%List is the appended list containing all the paths
paths([], []).
paths([X], [[X]]).
paths([X1, X2], [[X1]]).
paths([X1, X2, X3], [[X1,X3]]).
paths([X1, X2, X3, X4 | T], List) :-
paths([X3,X4|T], RL), paths([X4|T], RL2),
prefix_all(X1, RL, FL1), prefix_all(X1, RL2, FL2),
append(FL1, FL2, List).
So if run with the list [1,2,3,4,5] is would produce the following:
| ?- paths([1,2,3,4,5],X).
X = [[1,3,5],[1,4]] ? ;
no
I have code in PROLOG:
vals(_,[],_).
vals([H|T],[(H,C)|L],K) :- vals([H|T],L,(K,C)).
This code receivers list and list of tuples, for example:
vals([1],[(1,4),(1,2)],X).
I check if element from first list is equal to some tuples first element from the other list. In this case foundValues will return true, because 1 is equal to each tuples first element. This works fine, but instead of returning true/false, in resulting list I want to return all second element of each tuple where its first element is equal to the element from list. In this case X should be [4,2]. I am trying to do this with (K,C), but no success.
So, the question is - How to return list?
Here's an example on how to append to the list, just for 1 element.
Three cases:
For an empty list
When the element matches the first entry of the tupple
When the element not matches
Starting from this you should be able to create your example.
vals(_,[],[]).
vals(H,[(H,C)|L],[C|K]) :- vals(H,L,K).
vals(H,[(H2,_)|L],K) :-
H \= H2,
vals(H,L,K).
Example:
vals(1,[(1,2),(1,3)],X).
X = [2, 3] ;
false.
Extra:
Consider placing a cut in case 2.
Consider rewrite this with an accumulator
Im new to Prolog and was looking for some assistance. What i am trying to do is basically get a list L consisting of elements that repeat at least twice in a given list L'
Example
L'=[1,2,1,3,4,3,2] => L=[1,2,3].
So far I am able to compute the occurrence of every consecutive variables
% pack(L1,L2) :- the list L2 is obtained from the list L1 by packing
% repeated occurrences of elements into separate sublists.
% (list,list) (+,?)
pack([],[]).
pack([X|Xs],[Z|Zs]) :- transfer(X,Xs,Ys,Z), pack(Ys,Zs).
% transfer(X,Xs,Ys,Z) Ys is the list that remains from the list Xs
% when all leading copies of X are removed and transfered to Z
transfer(X,[],[],[X]).
transfer(X,[Y|Ys],[Y|Ys],[X]) :- X \= Y.
transfer(X,[X|Xs],Ys,[X|Zs]) :- transfer(X,Xs,Ys,Zs).
% encode(L1,L2) :- the list L2 is obtained from the list L1 by run-length
% encoding. Consecutive duplicates of elements are encoded as terms [N,E],
% where N is the number of duplicates of the element E.
% (list,list) (+,?)
encode(L1,L2) :- pack(L1,L), transform(L,L2).
transform([],[]).
transform([[X|Xs]|Ys],[[N,X]|Zs]) :- length([X|Xs],N), transform(Ys,Zs).
which will return the following list of touples
?- encode([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [[4,a],[1,b],[2,c],[2,a],[1,d][4,e]]
But there still remains the problem of building a list that will contain distinct elements that repeat at least twice.
If anyone can help me or point me in the general direction that would be great.
Thanks in advance
an element E of list L should:
be a member of list L',
be a member of list L'' where L'' is list L' if we remove element E.
check select/3, member/2, findall/3 and/or setof/3
You could write a procedure:
% E it's the list of are elements from L that repeat at least twice
elements_that_repeat_at_least_twice(L, E) :-
elements_that_repeat_at_least_twice(L, [], E).
elements_that_repeat_at_least_twice([H|Ls], Dupl, E) :-
...
In elements_that_repeat_at_least_twice the added list Dupl will keep each element you verify it's present multiple times. Examine each element of L, using [H|Ls].
Use memberchk/2 to verify if H is in L: then it's at least duplicate. If it's not yet in Dupl, add to it, and recurse. Remember to write the recursion base case (stop at empty list []).
Now I see you have added some code: then I complete suggestion:
elements_that_repeat_at_least_twice([], Dupl, Dupl).
elements_that_repeat_at_least_twice([H|Ls], Dupl, E) :-
( memberchk(H, Ls)
-> ( \+ memberchk(H, Dupl)
-> Dupl1 = [H|Dupl]
; Dupl1 = Dupl
)
; Dupl1 = Dupl
),
elements_that_repeat_at_least_twice(Ls, Dupl1, E).
Remember to reverse the list of duplicates when done.