Return the third to last elements of given list in Prolog - prolog

I am new in using Prolog, I want to write a program that compute the third to last element of a given list.
for instance
ThirdLast ([1, 2, 3, 4, 5] , Ans).
will give me:
Ans = [3, 4, 5]
I did this but is not working
len([],0).
len([_|T],N) :- len(T,X), N is X+1.
ThirdLast([ ],0)
ThirdLast([H|L1], X):-(len(L1,N)==2), X is H.
ThirdLast ([H|L1],X):-(len(L1,N)>2),ThirdLast (L1,X).
any ideas?

You can do it with a simple rule that ignores the first two elements:
tail3([_,_|T], T).
The first two elements get unified with _, and get thrown away. The rest of the list unifies with T, which is the result that we want to produce.
Demo.

Related

Prolog: random permutation

I'm trying to get random permutation with prolog. But the problem is
?- permutation([1,2,3,4],L).
gives always L = [1, 2, 3, 4] as first answer. I could fix this by using the query
?- L1=[1,2,3,4], permutation(L1,L2), dif(L1,L2).
But this gives me always L2 = [1, 2, 4, 3] as first answer.
How can I get a random permutation in SWI Prolog?
Isn't [1,2,3,4] random enough? Looks random to me!
But I know what you mean - you want a permutation which looks more random.
Why not roll your own? Just pick the next element out of an ever-shrinking "input list".
This is a bit laborious. Maybe there are more elegant ways?
look_random_dammit([],[]) :- !.
% note that [PickedElement|PermutedList] APPENDS "PickedElement"
% to list being constructed. Appending or prepending does not
% really make a difference here though:
look_random_dammit(ListRemainder,[PickedElement|PermutedList]) :-
ListRemainder \== [],
length(ListRemainder,Length),
succ(Max,Length),
% We are now leaving logicland and asking an oracle to give
% use a random number. "Buckle your seatbelt Dorothy, 'cause
% Kansas is going bye-bye!"
random_between(0,Max,PickedIndex),
nth0(PickedIndex,ListRemainder,PickedElement),
length(Prefix,PickedIndex),
% Constructing a remainder list is probably slow
append([Prefix,[PickedElement],Suffix],ListRemainder) ,
append(Prefix,Suffix,ListRemainderNext),
look_random_dammit(ListRemainderNext,PermutedList).
And so:
?- look_random_dammit([1,2,3,4],P).
P = [2,3,1,4] ;
false.
?- look_random_dammit([],P).
P = [] ;
false.
?- look_random_dammit([1,1,1,2,2],P).
P = [2,1,1,2,1] ;
false.
If we also retained the information about which elements was picked in equence, we could write a predicate that "reverses the permutation" because no information was lost while creating it.
You can try:
?- random_permutation([1,2,3,4], P).
P = [2, 1, 4, 3].
I am just giving an alternate method.
Using findall to get all possible permutations.
Getting the length of the List containing the permutations.
Using random to generate a random number between 0 and the length. This will be used as an index value.
Using nth1 to give us a permutation on the given index.
! (Cut) is used to give only one value. if you want more values then remove it.
Example:-
perm([H|T],Permutation):-
findall(A,permutation([H|T],A),List),
length(List,Length),
random(1,Length,Random),
nth1(Random,List,Permutation),!.
?- perm([1,2,3,4],Permutation).
Permutation = [1, 4, 3, 2]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 2, 4]
?- perm([1,2,3,4],Permutation).
Permutation = [3, 1, 4, 2]

Prolog: obtain a list with two sublists, containing the odd position elements and the even position elements. How to Improve this code

I would like to ask, if anyone knows how to improve (if it's not optimal) this code.
The idea, is that you have a list of elements, and I want to return a list, with two sublists inside it, the first sublist should contain the elements that are contained in the odd positions of the list, and the second sublist should contain, the elements that are contained in the even positions of the list.
Some examples:
?-evenAndOdd([1,2,3,4,5],[[1,3,5],[2,4]])
True.
?-evenAndOdd([a,b,c,d,e],[[a,c,e],[b,d]]).
True.
The code I have implemented is the next one:
evenAndOdd([],[]).
evenAndOdd([H|R],NL):-
evenAndOddRec([H|R], [[],[]],1,NL).
evenAndOddRec([], [LOdd,LEven],_,[LOdd,LEven]).
evenAndOddRec([H|R],[LOdd,LEven],Pos,NL):-
\+ even(Pos),
!,
NPos is Pos +1,
append(LOdd,[H],NLOdd),
evenAndOddRec(R,[NLOdd,LEven],NPos,NL).
evenAndOddRec([H|R],[LOdd,LEven],Pos,NL):-
NPos is Pos + 1,
append(LEven, [H], NLEven),
evenAndOddRec(R,[LOdd, NLEven],NPos,NL).
even(N):-
N mod 2 =:=0.
One symptom that the code is not optimal is that it will run off into the woods if you ask for an additional solution in the -,+,+ instantiation pattern:
?- evenAndOdd(X, [[1,3,5], [2,4,6]]).
X = [1, 2, 3, 4, 5, 6] ;
<time passes>
This kind of thing is a frequent occurrence when manually trying to match up lists with indexes in Prolog.
Stylistically, I would rather not give back a list containing exactly two lists when I could just have three arguments instead of two; this is, after all, a relationship between three lists, the combined list and the even and odd items.
Additionally, just eyeballing it, I'm not sure why any arithmetic or any cuts are needed here. This is how I would implement it:
evenAndOdd([], [], []).
evenAndOdd([O], [O], []).
evenAndOdd([O,E|Rest], [O|ORest], [E|ERest]) :- evenAndOdd(Rest, ORest, ERest).
This works with many instantiations:
?- evenAndOdd([1,2,3,4,5,6], O, E).
O = [1, 3, 5],
E = [2, 4, 6].
?- evenAndOdd([1,2,3,4,5], O, E).
O = [1, 3, 5],
E = [2, 4] ;
false.
?- evenAndOdd(X, [1,3,5], [2,4]).
X = [1, 2, 3, 4, 5] ;
false.
?- evenAndOdd(X, [1,3,5], [2,4,6]).
X = [1, 2, 3, 4, 5, 6].
?- evenAndOdd(X, [1,3,5], [2,4,6,8]).
false.
?- evenAndOdd([1,2,3,4,5,6], X, [2,4,6,8]).
false.
?- evenAndOdd([1,2,3,4,5,6], X, [2,4,6]).
X = [1, 3, 5].
You can implicitly determine even and odd values upon recursion, by taking two elements at a time (and taking into account when the has an odd number of elements):
evenAndOdd(L, [LOdd, LEven]):-
evenAndOdd(L, LOdd, LEven).
evenAndOdd([], [], []).
evenAndOdd([Odd], [Odd], []).
evenAndOdd([Odd,Even|Tail], [Odd|LOdd], [Even|LEven]):-
evenAndOdd(Tail, LOdd, LEven).

Prolog list of list n number with condition

I'm studying prolog language and i have an issue regarding this problem.
I've already created a program that, given a number N, returns a list with elements between 0 and N:
list2val(N,L):- list2val(0,N,L).
list2val(N,N,[N]).
list2val(C,N,[C|T]):-
C<N,
N1 is C+1,
list2val(N1,N,T).
?- list2val(5,X).
X = [0,1,2,3,4,5]
Now i'm trying to give an extension that, given a list, returns a list of lists in which every list is list2val only if the next number is greater than current number. In this case:
?- newFuction([1,5,2,3,9],L).
L = [[0,1],[0,1,2,],[0,1,2,3]]
My code is this, but somethings is wrong:
array(X):- array(X,_L).
array([],_L).
array([H|[T|Ts]],L1):-
H<T,
list2val(H,L2),
array([T|Ts],[L1|[L2]]).
array([T|Ts],L1).
Maybe could be too much difficult to understand but using a list L = [1,5,2,3,9] i do those steps:
check 1<5 so i create a 1 list2val until 1..in this case [0,1]
check 5<2 i dont create nothing.
check 2<3 i create list2val of 2 ...[0,1,2]
and so on...
I don't want use a standard predicates, by implement with standard terms.
A solution for your problem could be:
list2val(N,L):- list2val(0,N,L).
list2val(N,N,[N]):- !.
list2val(C,N,[C|T]):-
C<N,
N1 is C+1,
list2val(N1,N,T).
simulate([_],[]).
simulate([A,B|T],[H|T1]):-
( A < B ->
list2val(A,H),
simulate([B|T],T1);
simulate([B|T],[H|T1])
).
Using a predicate like simulate/2, you can solve your problem: it compares two numbers of the list and then create a new list in case the condition is satisfied.
?- simulate([1,5,2,3,9],LO).
LO = [[0, 1], [0, 1, 2], [0, 1, 2, 3]]
false

Replace elements of a list with Prolog

how to replace any of the element in the list with prolog?
example:
replace(2,[1,2,3,2,1],5,X)
should have both the solutions:
X = [1,5,3,2,1]
X = [1,2,3,5,1]
You can do it by iterating over the input list:
%replace(_, [], _, []).
replace(Element, [Element|Tail], NElement, [NElement|Tail]).
replace(Element, [CurElement|Tail], NElement, [CurElement|NTail]):-
replace(Element, Tail, NElement, NTail).
Sample input:
?- replace(2,[1,2,3,2,1],5,X).
X = [1, 5, 3, 2, 1] ;
X = [1, 2, 3, 5, 1] ;
If you uncomment the first clause it would also output the solution where the output list remains unchanged.
The first clause (commented) is a base case for iterating over a list. It states that the replaced list of an empty list is the empty itself.
The second clause states that if the head of the list unifies with the Element then the replace list would contain the replaced element and the rest of the list (Tail).
The third clause is the recursive step, it takes the first element and calls recursively with the tail of the list, and the output is the element taken concatenated with the result of the recursive call.

Giving same answer over and over, than listener crashes - Prolog

Warning, I'm quite new to Prolog.
I've written a split predicate in Prolog. It splits a list into two new lists. One that contains items greater than Key, and one that contains items less than or equal to Key. It should only ever return one set of answers. The problem is if I type ; to check for more answers, it keeps giving me the answer I already got and then eventually the listener crashes. I was wondering if you could help me fix this?
Code:
split([],_,[],[]).
split([H|T],Key,Small,Big):-
H=<Key,
removeFirst(Small,H,NewSmall),
split(T,Key,NewSmall,Big).
split([H|T],Key,Small,Big):-
H>Key,
removeFirst(Big,H,NewBig),
split(T,Key,Small,NewBig).
removeFirst([H|T],H,T).
removeFirst(L,Key,Result):-
divide(L,Key,F,E),
X = F,
Y = E,
append(X,Y,Z),
Result = Z.
Output:
?- split([1,2,3,4,5],3,S,B).
S = [1, 2, 3]
B = [4, 5] ;
S = [1, 2, 3]
B = [4, 5] ;
S = [1, 2, 3]
B = [4, 5] ;
Listener crashes on 4th attempt.
I suggest you resolve this algorithm in another way:
Define a recursive predicate (split/4) as you did, checking for each item in the input list, but build the resulting lists on return of recursion (that is, add the current item as the head of the appropriate list on the head of the clause).
It would be something like this:
split([], _, [], []). % Base case
split([Item|Tail], Key, [Item|Small], Big):-
Item =< Key,
split(Tail, Key, Small, Big).
split([Item|Tail], Key, Small, [Item|Big]):-
Item > Key,
split(Tail, Key, Small, Big).

Resources