-
Some more recursion examples →
Continuing with our previous post on recursions, let’s play with a couple of more simple examples to get ourselves familiar. This is just to start thinking in terms of recursive functions for the problems we try to solve. This kind of thinking will become more useful when we learn about tail recursion in one of the future posts.
Let’s write a small function, call it
find
, to find if a given element exists in a list. i.e., we are provided with an input listlst
of integers and an integerx
and the function would returntrue
ifx
exists as one of the elements oflst
andfalse
otherwise.As before, we think of the base case and the recursive step. We recursively call the function on a sub-list of the input list, till the problem reduces to the base case - the empty list.
Let’s try another simple examples - to find the minimum integer in the given list of integers. We will call the function
find_min
and it takes an input listlst
.Let’s test it out:
Let’s now move away from having lists as input, and work on an example that produces an output list. This is a very familiar introductory CS example - converting an input decimal number to it’s base-2 (
binary
) representation. Humans naturally count in base-10 (also calleddecimal
) number system, probably because most of us were born with 10 fingers. Computers, to be technically correct I should say digital circuits, work on base-2 number system - they know0
and1
. Just like how we count 0 .. 9 and then start counting 10 .. 19, followed by 20 .. 29, etc., digital circuits count 0, 1 followed by 10, 11 and then follow that by 100, 101, and 110, 111, etc. You see the pattern. Probably, it is more apparent if I write it one after the other:base-2 base-10 0 0 1 1 10 <-- restart 2 11 3 100 <-- restart 4 101 5 110 6 111 7 1000 <-- restart 8 1001 9 1010 10 <-- restart 1011 11 1100 12 1101 13 1110 14 1111 15
The usual way we compute the binary representation of a decimal number is to repeatedly divide it and collect the remainders. For example, if we want to compute the binary equivalent of decimal 7:
2 |_ 7 _ ^ 2 |_ 3 _ - (1) | 2 |_ 1 _ - (1) | ---------->
111 is the binary equivalent of decimal 7. Here, 3, 1 are quotients (
n/2
- n being the input number initally and then the quotient) and the ones on the right within parantheses are the remainders (n mod 2
).Let’s work out one more example - the binary equivalent of 13:
2 |_ 13 _ ^ 2 |_ 6 _ - (1) | 2 |_ 3 _ - (0) | 2 |_ 1 _ - (1) | -------->
If you observe carefully, what we are doing essentially is repeatedly dividing the input number
n
by the base we want to convert our number to - in this case base-2, and collect the remainders. Dividing a number is the expressionn/2
for algorithmic purposes and the remainder is the expressionn mod 2
. What we are going to do is to repeatedly (think “recursively”) dividen
and collect the remainder in a list which we would eventually return as the output result.@
is the OCaml syntax for list concatenation: for examplelst1 @ lst2
will concatenatelst1
andlst2
. Note the base case for our computation.Let’s check if what we worked out for 7 and 13 are consistent with what this program computes:
I guess it became a longer post than what I intended it to be, but I hope you are getting a better hang of thinking recursively. We will see more examples in future posts - feel motivated to play around with some examples in the mean time!!
-
Let's play with some simple recursion →
Recursion has been one of my favourite concepts for a very long time much like my fascination for mathematical induction. The subtle differences between the two would be a topic for a separate post.
Let’s do some simple recursive functions just to illustrate the beauty. I chose OCaml for this post as it is one of my favourite programming languages. Somehow, I feel that many algorithms when coded in OCaml look very intuitive and understandable than in other imperative programming languages. We will look at some algorithms in both OCaml and C in a later post and leave it to the reader to decide as to which one looks more intuitive.
OCaml is a very nice functional programming language and it offers
list
as a primitive data type. For example, if we want a list of five integers, this is how we do it in OCaml:We would usually think of the list data type itself to be a recursive definition. i.e., a list is made of either an empty list or a list composed of a
head
element andtail
where tail itself is a list (possibly empty list). For example, in the listl1
above,1
constitutes the head element and the tail corresponds to the list2;3;4;5
.Now, let’s write a recursive function to count the number of elements in the list.
- Let’s think of the base case: when the list is empty - in which case we just return
0
as the result. - And let’s build our thought process this way - what if the list has just one element? This would correspond to a list where there is a single head element and an empty list as the tail. i.e., we count the single head element and the empty list (the tail) we know contributes
0
to our result (the base case we just saw in 1.). - Now, when the list has 2 elements, we think of it as having a head element and a tail list that consists of a single element. Now, we count the head element and apply the same function (our counting) to count the number of elements in the tail list (which now corresponds to the case we saw in 2.).
Essentially what we are doing is:
- If the list is empty, return 0 as the result
- If the list is not empty, count the head element (1) and call the function (recursively) to count the number of elements in the tail
Now, let’s write the above two steps in the following program which we call
lst_len
(for list length), that takes a single input parameterlst
:Recursive functions in OCaml are defined with
rec
keyword. Let’s use this function to count the number of elements in our listl1
:Let’s use the same thought process to write a recursive function
lst_sum
to sum up (add) the elements of the list.And let’s use this function to sum up the elements in our list
l1
:Isn’t this intuitive and elegant way of programming? We’ll talk more about simple programs that can be written in an intuitive way and try to develop our understanding of the concepts in a clear way.
Thanks for your interest and keep checking out this space for more.
- Let’s think of the base case: when the list is empty - in which case we just return
-
My First Post →
This is my first post. I will keep this a very short one - nothing interesting to read and learn. The internet is a wonderful place. I learnt a lot by browsing interesting blogs, tutorials, asking questions on the various sites, twitter, etc. and it imperative that I give back to the community that helps me learn continuously. I am hoping to be regular with this effort at learning by teaching the many subjects and topics that interest me. Let’s see how much I can keep up and how much I can learn.