I'm very new to prolog. I have a size of list predicate. I'm trying to make another predicate that takes two arguments (an int, and a list) and it calls the size of list predicate on the passed in list and returns true if the list size matches the int passed in.
This is what I have so far.
size([],0).
size([H|T],N) :- size(T,N1), N is N1+1.
isEqual[X,Y] :- X/size[Y,N]. %X is an int representing expected length of list, Y is the list
Advice is welcomed.
Related
Let's assume we have alphabet {x,y} and I want to create a function, which returns true or false, whether the input list contains 2x symbol x after each other.
For example two([x,x,y]). returns true, while two([x,y,x]). returns false.
This is my function that I have so far:
two([Xs]) :- two(Xs, 0).
two([y|Xs], S) :- two(Xs, S).
two([x|Xs], S) :- oneX(Xs, S).
two([], S) :- S=1.
oneX([x|Xs], S) :- S1 is 1, two(Xs, M1).
oneX([y|Xs], S) :- two(Xs, S).
I use parameter S to determine, whether there were 2x x already (if so, parameter is 1, 0 else). This function however doesn't work as intended and always return false. Can you see what am I doing wrong?
You can use unification here and thus check if you can unify the first two items of the list with X, if not, you recurse on the list:
two([x, x|_]).
two([_|T]) :-
two(T).
The first clause thus checks if the first two items of the list are two consecutive xs. The second clause recurses on the tail of the list to look for another match by moving one step to the right of the list.
If I have a list [1;2;3;4;5;6] and I want to return a list of the odd indices [2;4;6], could I do this with List.map and some function? I'm having difficulty figuring this out.
What List.map does is return a function (call it f say) of each of the elements of the list. For each element x of the input list, it returns f x in the resulting list. Hence, the returned list is always the same length as the one it is passed.
Since you want a shorter list, you can't use List.map.
As #UnholySheep says, you could use List.filteri. It's specifically intended for returning only some of the elements of the list based on their position in the list.
In OCaml, suppose I have a string list as follows:
let ls : string list = ["A"; "A"; "B"; "B"; "A"; "Y"; "Y"; "Y"] ;;
I'm having trouble writing a function that calculates how many times an element occurs consecutively and also pairs up that element with its frequency. For instance, given the above list as input, the function should return [("A", 2); ("B", 2), ("A", 1), ("Y", 3)].
I've tried looking for some hints elsewhere but almost all other similar operations are done using int lists, where it is easy to simply add numbers up. But here, we cannot add strings.
My intuition was to use something like fold_left in some similar fashion as below:
let lis : int list = [1;2;3;4;5]
let count (lis : int list) = List.fold_left (fun x y -> x + y) (0) (lis)
which is essentially summing all the elements cumulatively from left to right. But, in my case, I don't want to cumulatively sum all the elements, I just need to count how many times an element occurs consecutively. Some advice would be appreciated!
This is obviously a homework assignment, so I will just give a couple of hints.
When you get your code working, it won't be adding strings (or any other type) together. It will be adding ints together. So you might want to look back at those examples on the net again :-)
You can definitely use fold_left to get an answer. First, note that the resultl is a list of pairs. The first element of each pair can be any type, depending on the type of the original list. The second element in each pair is an int. So you have a basic type that you're working with: ('a * int) list.
Imagine that you have a way to "increment" such a list:
let increment (list: ('a * int) list) value =
(* This is one way to think of your problem *)
This function looks for the pair in the list whose first element is equal to value. If it finds it, it returns a new list where the associated int is one larger than before. If it doesn't find it, it returns a new list with an extra element (value, 1).
This is the basic operation you want to fold over your list, rather than the + operation of your example code.
let concat (l : string list) : string = fold_right (fun a x -> a ^ x) l ""
so to go through it, I see that
let concat takes a list with strings, and returns a string.
fold right takes 3 parameters,
1 the first being a function that concatenates two strings, it takes a and x, and then concatenates them using ^.
2 the second argument is the list,
3 and finally the third is the accumulator that gets each pass added to it.
BUT, how does the func a x know that a is the first element of the list, and x is the second.
And when it passes through again, how does it know that a is the third element of the list, and x is the fourth, and so forth?
The accumulator is the first argument, a, to the fold function, and x is set to each element of the list in turn as the fold walks over it.
The return value of the fold function is the new value of the accumulator.
The initial value of the accumulator is the empty string, so the result of the first concatenation, which becomes the new accumulator, is the same value as the first element of the list.
Then the next element is concatenated to that, and so on until the end of the list is reached, at which point the fold returns final value of the accumulator, the fully concatenated string.
I'm having a little trouble understanding list recursion and modification in Prolog. I'm trying to take a list of lists, then with each list, multiply each element in the list by the last element.
Here's a snippet of my code:
/*Find the last element of a list*/
lastelement(X,[X]).
lastelement(X,[_|L]) :- lastelement(X,L).
/*Multiply two lists together*/
multiplication(M1,M2,M1*M2).
/*Take a list, find the last element and multiply every part of that list by that element*/
/*Attach modified list to X*/
modifyL([],X) :- X is [].
modifyL([First|Tset],X) :- lastelement(Y,First),
multiplication(Y,First,MFirst),
modifyL([Tset],X),
append(X,MFirst,X).
When I try any list of lists, however, all I get is false. Can someone give me any pointers
on list recursion that could help further understand this problem?
modifyL([],X) :- X is [].
This doesn't do what you think, is is used to get the result of an arithmetic evaluation.
you can write
modifyL([],X) :- X = [].
or simply
modifyL([],[]).
When you work with a list, and you repeat the same process to each element of this list you can use maplist which is exactly design for that.
the template is maplist(Goal, L1 L2).
modify(L1, L2) :-
maplist(multiply_one_list,L1, L2).
multiply_one_list works with a list, you it can be written like that :
multiply_one_list(L_in, L_out) :-
% getting last argument
reverse(L_in, [Last | _]),
% multiply each element of the list by
% the last element, one more maplist !
maplist(multiply_one_element(Last), L_in, L_out).
multiply_one_element(Last, In, Out) :-
Out is In * Last.