Prolog - Twice List - list

I am practicing prolog and all and this one is killing me. Trying to do this:
twice([1,2,3],X).
the output I want is
X = [1,1,2,2,3,3].
Here's my latest attempt:
twice([HD|TL],[HD2|TL2]):-
twice(TL,[HD,HD2|TL2]).
twice([],[HD|TL]).
//New
twice([],[]).
twice([A|B],Out):- twice([A|B],[A,A|Rest],
twice(B,Rest).

Start with the base case,
twice([],
"twice of nothing is" ... nothing, right?
[]).
Now, what if there is something there?
twice([A|B],
then what? do we want the result to start from A? You bet,
[A,
what next goes there?
...
(fill it in, please). Then, there's the rest:
| Rest] ):-
so, we continue. The Rest is taken from B:
twice(B, ...).
fill this in too, please.

Let's look at a simpler task first, a predicate where every element in input is not get to the output twice, but only once (input and output are the same, basically).
onlyonce([], []).
onlyonce([Head | Tail], [Head | NewTail]) :-
onlyonce(Tail, NewTail).
The first clause is obvious.
The second clause means:
the first argument (input) is a non-empty list. Name first element of that list "Head", name the rest elements of that list "Tail"
the second argument is a non-empty list. The first element of that list is the same as in the first argument list "Head" (i.e. the first element of the input list copied once). Name the rest elements of the list "NewTail"
"NewTail" can be obtained from "Tail" (and vice versa) using "onlyonce" predicate.
If you understand how "onlyonce" works, it's very easy to change it to "twice".

Try this:
twice([], []).
twice([A|B], [A,A|Rest]) :- twice(B, Rest).

Related

Reverse every second list of lists in Prolog

I have a list containing lists and I want to reverse every second list in it. I tried something but if I have odd number of elements in the list the last list element is lost... So the best solution would be to put the odd lists first and the even lists second till every second list is reversed.
I can't use any libraries. I need to do it recursively or split them and append them again. The best thing I made so far was to reverse only the first even list and append the first odd and even list in a new list.
I tried to do this:
reverselist(List, [List]).
reverselist([X,Y|Rest], [SnakeList|Rest2]):-
append(X, [], Odd),
reverse(Y, EvenList),
append(Odd, EvenList, SnakeList),
reverselist(Rest, Rest2).
And this:
reverselist(List1, List2).
reverselist([H|Ts], [Odd|R]):-
not(0 is H mod 2),
append(H, [], Odd),
reverselist(Ts, R).
reverselist([H|Ts], [Even|R]):-
0 is H mod 2,
reverse(H, Even),
reverselist(Ts, R).
Sample query:
?- reverselist([[a,b,c],[d,a,b],[c,d,o],[b,c,d],[e,e,d]], List).
I want the result to be:
List = [ [a,b,c],[b,a,d],[c,d,o],[d,c,b],[e,e,d] ].
You can also write mutual recursion:
reverselist([],[]).
reverselist([H|T],[H|T1]):-reverselist2(T,T1).
reverselist2([],[]).
reverselist2([H|T],[H1|T1]):-reverse(H,H1), reverselist(T,T1).
You were pretty close with your first variant.
Instead of your
reverselist(List, [List]).
reverselist([X,Y|Rest], [SnakeList|Rest2]):-
append(X, [], Odd),
reverse(Y, EvenList),
append(Odd, EvenList, SnakeList),
reverselist(Rest, Rest2).
just tweak it as
reverselist([], []). % additional clause
reverselist([List], [List]).
reverselist([X,Y|Rest], [X,EvenList|Rest2]):-
reverse( Y, EvenList),
reverselist( Rest, Rest2).
All three clauses are mutually exclusive and together they are exhaustive, i.e. they cover every possibility.
I believe this definition to be the most immediate and close representation of your problem. In Prolog, to formulate the problem means to have the solution for it.
We need to create another predicate with one more argument to keep track of odd or even position:
reverselist(InList,OutList):- reverselist(InList,OutList, 0).
reverselist([],[],_). %base case
%case of even position
reverselist([H|T],[H|T1], 0):- reverselist(T,T1,1).
%case of odd position
reverselist([H|T],[H1|T1], 1):- reverse(H1,H), reverselist(T,T1,0).

Best way to remove the first elements from each list in a list of lists in Prolog?

I am trying to remove the first element of every list in a list of lists.
For example, to list [[1,2],[3,4]], I should return [[2],[4]].
In most situations, this code below will work fine:
remove_firstElem([],[]).
remove_firstElem([[_H|T]|Ls],[T|L]) :-
remove_firstElem(Ls,L).
But for lists like [[1],[2]], I would like it to return [] rather than [[],[]].
What I tried so far looks like:
remove_firstElem([_H|Ls],L) :-
length(_H,1),
remove_firstElem(Ls,L).
But it returns [ ],[[ ]],[[ ]],[[ ],[ ]] and I really don't know what's wrong with it.
Can anyone help me to fix it? Thanks for any help!
If I understand it correctly, you want to pop the head of the list, but in case the list contains only one element (or none at all), that list should be removed.
We can check if the sublist contains at least two elements with the pattern:
pop_lists([[_,H2|T]|TA],[[H2|T]|TB]) :-
pop_lists(TA,TB).
so here we have a pattern [_,H2|T] for the first list. The _ binds with the first element, H2 with the second element, and the remaining elements with the tail.
Lists that can not unify with that pattern are the empty list, or a list with one element. So in that case we simply ignore them:
pop_lists([[]|TA],TB) :-
pop_lists(TA,TB).
pop_lists([[_]|TA],TB) :-
pop_lists(TA,TB).
In case we reach the end of the list, of course we unify the filter with the empty list as well:
pop_list([],[]).
we better put this clause on the first line to make our predicate more multidirectional. So in full, we have the following solution:
pop_list([],[]).
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :-
pop_list(TA,TB).
pop_list([[]|TA],TB) :-
pop_list(TA,TB).
pop_list([[_]|TA],TB) :-
pop_list(TA,TB).
We can further reorder the statements, such that the amount of backtracking is less:
pop_list([],[]).
pop_list([[]|TA],TB) :-
pop_list(TA,TB).
pop_list([[_]|TA],TB) :-
pop_list(TA,TB).
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :-
pop_list(TA,TB).
Easier way:
list_tail([_|Es], Es).
maplist(list_tail, Input, Output).

Get "real" prefixes/suffixes/infixes in Prolog

the Prolog notation of prefix/suffix is a quite easy one:
It pretty much puts all the work on append.
For those who don't know:
prefix(P,L):-append(P,_,L).
suffix(S,L):-append(_,S,L).
Now this means, that the result for prefix(X,[a,b,c,d]).
will be: X=[];X=[a];X=[a,b];X=[a,b,c];X=[a,b,c,d]
Here is my problem with this: I want a "real" prefix. Hence, a prefix cannot be empty, nor can the part following it be empty.
So the result to the query prefix(X,[a,b,c,d]). should be
X=[a];X=[a,b];X=[a,b,c]
and that's it.
Unfortunately, the real beaty of the standard-built in prefix predicate is, that it can use the termination of append, which is append([],Y,Y).
So it is pretty easy to know when to stop, picking the list apart one by one till the list is empty.
My termination means: Stop if there is exactly one element left in your list.
How do I do this?
My naive result would be:
prefix(P,L):-
length(P,1),append(P,E,L),E/=[].
This feels wrong though. I'm at work so I haven't checked if this actually works, but it should:
Is there any more convenient way to do this?
Same goes for suffix, which will be even harder since you do not have a way to adress the Tail as specific as the Head, I guess I'd just reverse the whole thing and then call prefix on it.
Infix will just be a combination of two.
I hope it is clear what I mean. Thanks for your input!
tl;dr: How to write a predicate prefix/2 which only filters real prefixes, so the prefix itself can not be empty, nor can the list followed by it be empty.
For the real prefix, you can try to do it like this:
list_prefix(List, [H|T]) :-
append([H|T], [_|_], List).
This just says that the first argument must have at least one element, and the rest of the list must have at least one element.
And following the suggestion by #false to make it more explicit:
list_real_prefix(List, Prefix) :-
Prefix = [_|_],
Rest = [_|_],
append(Prefix, Rest, List).
The "real" suffix will be exactly the same:
list_real_suffix(List, Suffix) :-
Front = [_|_],
Suffix = [_|_],
append(Front, Suffix, List).
You can also use a DCG for this, which is descriptive:
list_prefix(P) --> non_empty_seq(P), non_empty_seq(_).
non_empty_seq([X]) --> [X].
non_empty_seq([X|Xs]) --> [X], non_empty_seq(Xs).
| ?- phrase(list_pref(P), [a,b,c,d]).
P = [a] ? a
P = [a,b]
P = [a,b,c]
no
| ?-
You can define the suffix similarly:
list_suffix(S) --> non_empty_seq(_), non_empty_seq(S).

Increment list items by a certain value in prolog

I'm trying to write a predicate that increments a list item by a certain value. I wrote this one but it's not giving me the correct result:
%--Increments every single list item by a certain Value.
incList([],[],_).
incList([X | List], [X2 | List2],Value) :-
incList(List,List2),
X2 is X + Value.
It only increments the first one. Any solutions on how to solve this without changing the structure of the predicate? Thank you.
As joel76 mentioned I have a typo on line2 of second predicate. It should be incList(List,List2,Value) not incList(List,List2).

how to remove the first element in list

I need to remove the first element from a list (the head). How do I do it?
Maybe something like:
removehead([_|Tail], Tail).
Test:
prolog> removehead([1,2,3,4], R).
[2,3,4]
R is unbound here, and is used for binding it the result.