How can I build a list recursively? ML - list

I have to write a recursive function that takes a list of three elements, and returns another list created using those three elements. For example I might have a list like [a,b,c], and a function needs to multiple a by b c times. So [2,3,5] would create a list like [2,6,18,54,162,486]
I understand the hd, tl, #, and :: list operators, but I don't understand the logic of building the list.
If I multiply hd([2,3,5])* hd(tl([2,3,5)) I'll get six. But where do I attach that? I would need new logic on every call to go deeper in the list multiplying the last element by 3.

The point is, your recursive function should return the list, and the call which satisfies the stopping requirement should return empty list (or some starting list).
In this case, the function appends (a * b) to the start of list of the next values. The decreasing c provides a counter, while intermediate result (a * b) serves as a base for calculations further down the line. So here the list grows backwards, from the greatest values at the tail to the smallest at the head.

Related

How can I get multiple nth elements in a list?

I want to know how I can get multiple elements in a list in one function
for example if I wanted to get elements 1 2 3 and 4 from list a, I would have to type a!!0 ++ a!!1 ++ a!!2 ++ a!!3. This takes up a lot of space especially if the list name is more than one character. so I'm wondering if I can do something like a!![0,1,2,3] instead and get all of those elements in a much shorter way. Thank you.
You can work with a mapping where you lookup all items for a list, so:
map (a !!) [0,1,2,3]
If you are however interested in the first four items, you can work with take :: Int -> [a] -> [a]:
take 4 a
especially since looking up by an index (with (!!)) is not a common operation in Haskell: this is unsafe since it is not guaranteed that the index is in bounds. Most list processing is done with functions like take, drop, sum, foldr, etc.

How to make predicate repeat N number of times in Prolog?

I have a number of lists containing letters and I have written a predicate that checks whether or not there are duplicates present in one of these given lists:
noDuplicates([]).
noDuplicates([H|T]):-
not(member(H, T)),
noDuplicates(T).
I have 10 lists and I want to know if there are no duplicates in any of them, so I made them into sublists of one big list, something like:
[[A,B,C], [C,A,D], [E,F,G]...]]
(So there can be duplicates in the big list, but not the individual sublists).
I get that I have to do the duplicates test 10 times; once for every sublist, but how do I write this in Prolog? I could probably write it down 10 times, but my guess is I can use recursion to make prolog repeat itself until all sublists have been checked.
So basically: I want this predicate to repeat itself N times, until N is 10. I'm really struggling with it though. Does anyone have any idea on what to do?
Let us generalize the question as follows:
You have a predicate p/1 that expresses what you want for a single list.
Thus, to lift this definition to a list of such lists, you can define a predicates ps/1 as follows:
ps([]).
ps([L|Ls]) :-
p(L),
ps(Ls).
Every time you see this pattern, you can use maplist/2. That is, the above is equivalent to:
ps(Ls) :- maplist(p, Ls).
The goal maplist(p, Ls) is true iff p holds for each element L of Ls.
Note that it will limit your understanding of Prolog if you think in terms of "looping" and "repeating". These are imperative notions and only make sense when the list is already fully instantiated. However, from Prolog, we expect more than that: We expect a full-fledged relation to also generate lists for which the relation holds. And in such cases, there is nothing to "repeat" yet: We start from nothing, and ask Prolog what solutions there are in general.
Thus, think in terms of describing when the relation ps/1 holds for lists of lists:
It holds for the empty list [].
It holds for the list [L|Ls] if our initial predicate (p/1) holds for L, and ps/1 holds for the remaining list Ls.
This declarative reading is applicable in all directions, no matter how many list elements are already instantiated, if any. It works for 10 lists just as well as for zero and 50.

Prolog summing first indices of lists

I'm new to Prolog, trying to sum up only the first elements of each list.
takeFirst([[1,2,3],[4,5,6],[7,8,9]],R). --> R=1+4+7=12
It keeps outputting false and I don't understand what I'm missing here.
takeFirst([HF|_],[],HF):-!.
takeFirst([H|L1],R):- H=[_|_], L1=[_|_],!,takeFirst(H,L1,NN), R is NN.
takeFirst([HF|_],[K|L2],HF):- takeFirst(K,L2,NN), HF is HF+NN.
does anyone see what is wrong here?
Well your code is rather chaotic: you define a takeFirst/3 first (that probably should be the base case?). Next you define two recursive cases, but you somehow pass the head the list in the recursive call, etc.
Actually the problem is easy to solve. You first better redirect your takeFirst/2 to a takeFirst/3` with an accumulator:
takeFirst(L,R) :-
takeFirst(L,0,R).
Next we consider a base case: we reached the end of the list:
takeFirst([],R,R).
In this case we reached the end, and so the value of the accumulator, the variable we pass that keeps track of the sum thus far, is returned as the result.
In the recursive case, we are given a list [H|T] and we are interested in the head of the head HH so [[HH|_]|T]. In that case we add HH to the accumulator and do a recursive call with T:
takeFirst([[HH|_]|T],Ra,R) :-
Rb is Ra+HH,
takeFirst(T,Rb,R).
So putting it together we get:
takeFirst(L,R) :-
takeFirst(L,0,R).
takeFirst([],R,R).
takeFirst([[HH|_]|T],Ra,R) :-
Rb is Ra+HH,
takeFirst(T,Rb,R).
Something that was not very clear in your question is what should be done if there is an empty list in your list, like [[1,2,3],[],[7,8,9]]. The above predicate will fail: it expects that all lists have at least one element. In case you simply want to ignore these lists, you can alter your code into:
takeFirst2(L,R) :-
takeFirst2(L,0,R).
takeFirst2([],R,R).
takeFirst2([[]|T],Ra,R) :-
takeFirst2(T,Ra,R).
takeFirst2([[HH|_]|T],Ra,R) :-
Rb is Ra+HH,
takeFirst2(T,Rb,R).
So we add a case where the list follows the pattern [[]|T], in which case we simply perform a recursive call with the tail T.
Based on the given above predicates, constructing a list of heads is not hard as well:
heads([],[])
heads([[HH|_]|TA],[HH|TB]) :-
heads(TA,TB).

OCAML - Is element in the list?

let's say we have a list of elements:
[(a,b); (c,d); (e,f)]
What function would check if element (lets say A, where A=(x,y)) is in the list or not?
Use List.mem to do the search for a match.
let a = (3,4)
List.mem a [(1,2); (3,4); (5,6)]
You can also use List.memq if you want to check if the two items both reference the same entity in memory.
Here's a hint on how to write this yourself. The natural way to to process a list is to initially look at the first element, then check the remainder of the list recursively until you have an empty list. For this problem, you could state the algorithm in English as follows:
If the list is empty then the item is not in the list,
else if the first list element equals the item then it is in,
else it is the answer to (Is the item in the remainder of the list?)
Now you just need to translate this into OCaml code (using a recursive function).
In general, if you can describe what you want to do in terms of smaller or simpler parts of the problem, then writing the recursive code is straightforward (although you have to be careful the base cases are correct). When using a list or tree-structured data the way to decompose the problem is usually obvious.

Define new list and recursively add items in the list by appending in Prolog

I am trying to do some operation on the given list items and trying to declare a new list and add items to it that satisfy a certain condition. I have to call this function recursively. So, first time the list is null and i want to insert an item in it. Second time , it will have one element and adding another element makes two elements. Third time two elements are there, and add one more element and so on.
Please help me how to declare list in prolog and addr elements to it by appending in recursive function calls.
There is no need to declare terms in Prolog; they exist once you write them down. So if you write [], it is the empty list. The things you mention are relations between two lists: One list, call it List0, and another list, call it List, which is List0 with additional elements. So you have a relation like
list0_list(List0, List) :-
....
which holds if List is List0 with the elements you want. You only have to describe when this relation holds, and you do this by stating the necessary conditions in the rule's body.