Prolog: assign the tail of a list to a variable? - list

I have some prolog code below, which takes a list of integers, and returns me the Max element of said list. My issue is that I'm not quite sure how theList = [H|_] portion of the code works.
I understand that H gets assigned the head value of the list, but the variable List below is what? How does prologue know to take the tail and assign it to List when given the following snippet of code List = [H|_]
To me List could either be H or it could be _ (the tail)... but logically it has to be _ (the tail) or the function below would not work.
max(List,Max) :-
List = [H|_],
accMax(List,H,Max).
Example of code : http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse21

Related

Return a list of the odd indices using List.map

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.

OCaml count consecutive elements in a list

I'm writing OCaml code that reads in a list and removes any char 'i's that appear at the beginning of the list. For instance, the list removeI['i';'i';'a';'c';'i'] should return -: int * char list = ['a';'c';'i'], because there are 2 'i's at the beginning of the list. I believe I know how to implement this properly; however, I want to return a tuple that includes the number of removed 'i's as well as the new list with the 'i's removed. I know that may sound confusing, but an example would be removeI['i';'i';'a';'c';'i'] -: int * char list = (2,['a';'c';'i']) There are 2 'i's removed and the new list with the removed 'i's.
So far, I have the following function:
let rec removeI list = match list with
| [] -> []
| x::[] -> x::[]
| x::y::t1 -> if x='i' then removeI (y::t1)
else list;;
This returns the list with the first 'i's removed, but I keep getting errors when I try to include the number of removed 'i's as part of a tuple. Could anyone push me in the right direction? Thanks!
Your recursive call will return the same type as the function overall. So if you change the function to reuturn (count, list), then the recursive call will return that also.
Generally you want to gather up the returned values and calculate a new value from them.
Right now you have just this:
removeI (y :: t1)
But you need something more like this:
let (count, list) = removeI (y :: t1) in
(* Newly calculated count and list *)
Note that your base cases also have to return a count and a list.
As a side comment, I don't actually understand your second base case. You don't want to remove an 'i' if it's the only thing in the list? That doesn't seem particularly consistent.

Understanding Prolog's empty lists

I am reading Bratko's Prolog: Programming for Artificial Intelligence. The easiest way for me to understand lists is visualising them as binary trees, which goes well. However, I am confused about the empty list []. It seems to me that it has two meanings.
When part of a list or enumeration, it is seen as an actual (empty) list element (because somewhere in the tree it is part of some Head), e.g. [a, []]
When it is the only item inside a Tail, it isn’t an element it literally is nothing, e.g. [a|[]]
My issue is that I do not see the logic behind 2. Why is it required for lists to have this possible ‘nothingness’ as a final tail? Simply because the trees have to be binary? Or is there another reason? (In other words, why is [] counted as an element in 1. but it isn't when it is in a Tail in 2?) Also, are there cases where the final (rightmost, deepest) final node of a tree is not ‘nothing’?
In other words, why is [] counted as an element in 1. but it isn't when it is in a Tail in 2?
Those are two different things. Lists in Prolog are (degenerate) binary trees, but also very much like a singly linked list in a language that has pointers, say C.
In C, you would have a struct with two members: the value, and a pointer to the next list element. Importantly, when the pointer to next points to a sentinel, this is the end of the list.
In Prolog, you have a functor with arity 2: ./2 that holds the value in the first argument, and the rest of the list in the second:
.(a, Rest)
The sentinel for a list in Prolog is the special []. This is not a list, it is the empty list! Traditionally, it is an atom, or a functor with arity 0, if you wish.
In your question:
[a, []] is actually .(a, .([], []))
[a|[]] is actually .(a, [])
which is why:
?- length([a,[]], N).
N = 2.
This is now a list with two elements, the first element is a, the second element is the empty list [].
?- [a|[]] = [a].
true.
This is a list with a single element, a. The [] at the tail just closes the list.
Question: what kind of list is .([], [])?
Also, are there cases where the final (rightmost, deepest) final node of a tree is not ‘nothing’?
Yes, you can leave a free variable there; then, you have a "hole" at the end of the list that you can fill later. Like this:
?- A = [a, a|Tail], % partial list with two 'a's and the Tail
B = [b,b], % proper list
Tail = B. % the tail of A is now B
A = [a, a, b, b], % we appended A and B without traversing A
Tail = B, B = [b, b].
You can also make circular lists, for example, a list with infinitely many x in it would be:
?- Xs = [x|Xs].
Xs = [x|Xs].
Is this useful? I don't know for sure. You could for example get a list that repeats a, b, c with a length of 7 like this:
?- ABCs = [a,b,c|ABCs], % a list that repeats "a, b, c" forever
length(L, 7), % a proper list of length 7
append(L, _, ABCs). % L is the first 7 elements of ABCs
ABCs = [a, b, c|ABCs],
L = [a, b, c, a, b, c, a].
In R at least many functions "recycle" shorter vectors, so this might be a valid use case.
See this answer for a discussion on difference lists, which is what A and Rest from the last example are usually called.
See this answer for implementation of a queue using difference lists.
Your confusion comes from the fact that lists are printed (and read) according to a special human-friendly format. Thus:
[a, b, c, d]
... is syntactic sugar for .(a, .(b, .(c, .(d, [])))).
The . predicate represents two values: the item stored in a list and a sublist. When [] is present in the data argument, it is printed as data.
In other words, this:
[[], []]
... is syntactic sugar for .([], .([], [])).
The last [] is not printed because in that context it does not need to. It is only used to mark the end of current list. Other [] are lists stored in the main list.
I understand that but I don't quite get why there is such a need for that final empty list.
The final empty list is a convention. It could be written empty or nil (like Lisp), but in Prolog this is denoted by the [] atom.
Note that in prolog, you can leave the sublist part uninstantiated, like in:
[a | T]
which is the same as:
.(a, T)
Those are known as difference lists.
Your understanding of 1. and 2. is correct -- where by "nothing" you mean, element-wise. Yes, an empty list has nothing (i.e. no elements) inside it.
The logic behind having a special sentinel value SENTINEL = [] to mark the end of a cons-cells chain, as in [1,2,3] = [1,2|[3]] = [1,2,3|SENTINEL] = .(1,.(2,.(3,SENTINEL))), as opposed to some ad-hoc encoding, like .(1,.(2,3)) = [1,2|3], is types consistency. We want the first field of a cons cell (or, in Prolog, the first argument of a . functored term) to always be treated as "a list's element", and the second -- as "a list". That's why [] in [1, []] counts as a list's element (as it appears as a 1st argument of a .-functored compound term), while the [] in [1 | []] does not (as it appears as a 2nd argument of such term).
Yes, the trees have to be binary -- i.e. the functor . as used to encode lists is binary -- and so what should we put there in the final node's tail field, that would signal to us that it is in fact the final node of the chain? It must be something, consistent and easily testable. And it must also represent the empty list, []. So it's only logical to use the representation of an empty list to represent the empty tail of a list.
And yes, having a non-[] final "tail" is perfectly valid, like in [1,2|3], which is a perfectly valid Prolog term -- it just isn't a representation of a list {1 2 3}, as understood by the rest of Prolog's built-ins.

How does this ocaml recursive function work?

I'm pretty new to ocaml and I'm having a hard time with this func
I know what it does but not HOW! With a given list, it returns the minimum value of the list and the rest of the list as a pair.
sepmin [2;1;3;4] == (1,[2;3;4])
val sepmin : 'a list -> 'a * 'a list
# let rec sepmin = function
[h] -> h, []
|h::t -> let h1, t1 = sepmin t in
min h h1, (max h h1)::t1;;
Could you guys help me out with the recursive part t.t
First, it is applied to the list's tail recursively. Say, it returns h1 and t1 that are the minimum of the tail and all the other elements of the tail. Next, this element, h, is compared against h1. If it is less than h1, then the pair (h, h1::t1) returned; otherwise the pair (h1, h::t1) is returned. Since the function is called recursively, then probably one of these pairs is returned to the previous recursion point (and its first element is again compared against that point's list head). As far as I can see, the function does not care much about the original order of the elements, i.e. for the list [1; 4; 2; 5; 6] it should return (1, [2; 4; 5; 6]), 2 and 4 are reordered in the result.
A good way to think about recursion is to take it in two pieces. First, what does the function do when the input is trivial? Second (this is the tricky part), assuming the function works for small inputs, how does it transform a bigger intput into a smaller one and use the answer for the smaller case to calculate the correct result for the bigger case.
The trivial case for this function is a list of one element. The answer is obvious in that case.
For a longer list, you can use your recursive power to get the correct answer for the tail of the list (which is a shorter list, hence the recursion will work by assumption). Once you know the answer for the tail of the list, you can construct the correct answer for the full list: the max of the head of the list and the answer for the tail is the overall maximum. You need to add the smaller of these two values back to the list.

Cons Operator "|" In Erlang

While reading the LearnYouSomeErlang and I found that cons operator is used to get the first element of list. I was a bit confused as to how that works because earlier in the book he mentions that cons operator is used to add elements to the list.
This function returns the first element of a List.
head([H|_]) -> H.
Found in this page http://learnyousomeerlang.com/syntax-in-functions.
Can someone explain how this works in returning the first element of a list.
The cons operator can be used to pattern match a list. So a list can be pattern matched to [H|T] which deconstructs the list and H is the first element of the list and the T is the remaining items of the list.
So, the cons operator is both used for pattern matching and also to construct lists. E.g of construction is X = [1|[2,3]].
I'm not sure if this will be useful, but...
A cons cell describes a pair of which the first element is a term of some sort and the second is a pointer to another cons cell (or null if at the end of a list). So, if you will let me use '->' as a pointer symbol, a simple cons cell representing a list of one element could be,
[1, -> null] = the list [1].
[2, -> [1,-> null]] = the list [2,1], etc.
A list can be thought of as a linked list of cons cells where the 2nd element of the Cons cell is the pointer to the next link.
A Cons operator creates a new list by creating a Cons cell of which the first element is a new list element and the second element is a pointer to the first Cons cell of the original list. The first element is the Head, and the second element (the Tail) is a pointer to next Cons cell in the 'chain'. In Erlang, the above can be written as
[2|[1|[]]]
which is the list [2,1]. As a short-hand, [1|[]] is written as [1], so
[2|[1|[]]] = [2|[1]]=[2,1]
Now, if my list were [1,2,3], I could represent it as its head Cons-ed with its Tail as in,
[1|[2,3]
So, because Erlang is awesome, this pattern is available to match on as in: "I have a list, [1,2,3] which can be described as a Cons-ed Hd and a Tail (a pointer to the Hd of the rest of the list). So
[Hd|Tail] = [1,2,3]
gives
Hd = 1
and
Tail = [2,->[3,->null]] = [2|[3|[]]] = [2|[3]] = [2,3].