How can I compare the average of a list with every element in the same list? - functional-programming

fun promedio l = let
fun sl(nil, sum, len) = sum div len
| sl(h::t, sum, len) = sl(t, sum + h, len + 1)
in
sl(l, 0, 0)
end;
This code gives me the average of an list, but now I have to compare every element in that list with the average and say how many elements are greater than the average and how many are lower than the average.
Could you please help me with this last step?

Your promedio function fails on the empty input; promedio [], since it tries to divide by zero.
Here are two alternative ways to write this that takes empty lists into account:
(* Using one traversal *)
fun average xs =
case foldl (fn (x, (sum, count)) => (x + sum, 1 + count)) (0, 0) xs of
(0, 0) => 0
| (x, y) => x div y
(* Using two traversals *)
val sum = foldl op+ 0
fun average [] = 0
| average xs = (sum xs) div (length xs)
You can partition a list using any predicate with List.partition.
In your case, the predicate may be x <= avg.
fun partition_average xs =
let val avg = average xs
in List.partition (fn x => x <= avg) xs end
Notice that if I didn't bind average xs to avg outside the fn x => ...,
(* Don't do this *)
fun partition_average xs =
List.partition (fn x => x <= average xs) xs
then I'd be recomputing average xs for each element of xs.
A demo:
- partition_average [1,2,3,4,5]; (* avg being 3 *)
> val it = ([1, 2, 3], [4, 5]) : int list * int list
- partition_average [1,2,3,9]; (* avg being 3(.75) *)
> val it = ([1, 2, 3], [9]) : int list * int list

Related

Applying a function n times

I am trying to apply a function to a value n times.
Currently, I have
let rec n_times (f, n, v) =
if n > 0 then
n_times f n-1 (f v)
else
v
For some reason I keep getting an error that says
This expression has type 'a but an expression was expected of type 'a * int * 'b
The type variable 'a occurs inside 'a * int * 'b
I saw a few posts that address the same problem I am working on but none of them gets the same error.
In the first line of your code: you say "I declare a function called n_times that take a triplet (f, n, v) so one argument" then at the call site (third line) you give 3 arguments.
To fix this: write let rec n_times f n v = on line 1 or n_times (f, n-1, (f v)) on line 3.
You have defined the function to take a 3-tuple of values. So when you call it recursively you need to supply a 3-tuple:
n_times (f, n - 1, f v)
There are at least two problems, it would help to know what the purpose is other than recursion.
To get this to run you have to change your third line. n_times is defined with three inputs so it needs to be called with three. Also the function is defined to take a general, integer, and general input and output a general type.
You could remove (f v) and input just v every loop,
# let rec n_times (f, n, v) =
if n > 0 then
n_times (f , n-1 , v)
else
v;;
val n_times : 'a * int * 'b -> 'b = <fun>
# n_times(2,3,4);;
- : int = 4
This will however always return just v at the end.
You could also replace (f v) with a list and preapped it each loop,
# let rec n_times (f, n, v) =
if n > 0 then
n_times (f , n-1 , f::v)
else
v;;
val n_times : 'a * int * 'a list -> 'a list = <fun>
# n_times(2,3,[4]);;
- : int list = [2; 2; 2; 4]
# n_times(2,5,[4]);;
- : int list = [2; 2; 2; 2; 2; 4]
This allows the list to grow with each loop.
There seems to be a misunderstanding in how OCaml functions with multiple arguments are defined. You should replace
let rec n_times (f, n, v) =
with:
let rec n_times f n v =

Finding the mode of an int list in SML and where it occurs without library functions

I'm trying to find the mode or value that occurs most frequently. I want a function like :
mode:' 'a list -> (''a * int) list
and it returns the mode and where it occurs, unless there is a tie then return all occurrences so something like:
mode([1,1,2,3,5,8]) ===> [(1,2)]
mode([1,3,5,2,3,5]) ===> [(3,2),(5,2)]
mode([true,false,true,true]) ====>[(true,3)]
I'm trying to do this without library functions in SML.
so far I got:
fun mode(L)=
if null L then nil
else if hd L= hd (tl L) then 1+mode(hd(tl L))
else mode(tl L);
I know this isn't right I guess I am curious on how you both keep the indices of where the mode occurs and what the mode is and return them as tuples in a list.
You're trying to solve an exercise in many parts with several easier exercises before it. Judging by your current progress, have you considered solving some very similar exercises that build up to the final goal? This is generally good advice when solving programming problems: Reduce your current problem to simpler problems and solve those.
I'd try and solve this problem first
Build a histogram : ''a list -> (''a * int) list over the elements of a list:
fun histogram [] = ...
| histogram (x::xs) = ...
Do this by inserting each x with its count into a histogram.
fun insert (x, []) = ...
| insert (x, (y, count) :: hist) = ...
And write some tests that you can execute once in a while.
Find the mode : ''a list -> ''a of a list:
fun mode xs = ... (histogram xs)
Do this by finding the element in the histogram with the biggest count:
fun findMax [] = ... (* what if the list/histogram is empty? *)
| findMax [(x, count)] = ...
| findMax ((x, count) :: (y, count) :: hist) = ...
and eventually try and solve this problem
When you have a good grasp of representing and navigating regular histograms recursively, you could create an annotated histogram : (''a * int * int list) list that doesn't just contain the frequency of each element, but also their positions in the input list:
fun histogram_helper ([], _) = ...
| histogram_helper (x::xs, i) = ... histogram_helper (xs, i+1) ...
Do this by inserting each x with its count and position i along with previously found positions is into a histogram:
fun insert (x, i, []) = ...
| insert (x, i, (y, count, is) :: hist) = ...
Find the (possibly multiple) mode : ''a list -> (''a * int list) list of a list:
fun mode xs = ... (histogram xs)
Do this by finding the (possibly multiple) element(s) in the histogram with the biggest count:
fun findMax ([], countMax, tmpModes) = ...
| findMax ((x, count, is) :: hist, countMax, tmpModes) = ...
with countMax : int being the frequency repeated in tmpModes : (''a * int * int list) list. Here countMax and tmpModes are accumulating result parameters. Do this by determining whether (x, count, is) should be thrown away in favor of all tmpModes, or it should be added to tmpModes, or it should be chosen in favor of all tmpNodes
I am curious on how you both keep the indices of where the mode occurs and what the mode is and return them as tuples in a list.
Yes, this is not trivial. Using my suggested division into sub-problems, answering this depends on whether we are in the histogram function or the findMax function:
In histogram you can store the indices as part of the tuple that contains the element and the frequency. In findMax, since you're potentially collecting multiple results, you need to keep track of both which frequency is the highest (countMax) and what the temporary modes of choice are (tmpModes); subject to replacement or addition in a later recursive call.
So to answer your question: In an accumulating parameter.
and a little feedback to your code snippet
fun mode(L)=
if null L then nil
else if hd L= hd (tl L) then 1+mode(hd(tl L))
else mode(tl L);
Use pattern matching instead of null, hd and tl:
fun count_4s [] = 0
| count_4s (x::xs) = (if x = 4 then 1 else 0) + count_4s xs
fun count_ns ([], _) = 0
| count_ns (x::xs, n) = (if x = n then 1 else 0) + count_ns (xs, n)
fun count_12 ([], ones, twos) = (ones, twos)
| count_12 (x::xs, ones, twos) =
if x = 1 then count_12 (xs, ones+1, twos) else
if x = 2 then count_12 (xs, ones, twos+1) else
count_12 (xs, ones, twos)
fun count_abc ([], result) = result
| count_abc (x::xs, ((a, ca), (b, cb), (c, cc))) =
count_abc (xs, if x = a then ((a, ca+1), (b, cb), (c, cc)) else
if x = b then ((a, ca), (b, cb+1), (c, cc)) else
if x = c then ((a, ca), (b, cb), (c, cc+1)) else
((a, ca), (b, cb), (c, cc)))
Building a histogram is sort of an extension to this where instead of a fixed value like 4, or a fixed amount of them like ones and twos, you have a whole list of them, and you have to dynamically look for the one you've got, x, and determine if it needs to be added to the histogram or incremented in the histogram.
The best way would be to do that in a helper function, so for example, if count_abc were made with a helper function,
fun insert_abc (x, ((a, ca), (b, cb), (c, cc))) =
if x = a then ((a, ca+1), (b, cb), (c, cc)) else
if x = b then ((a, ca), (b, cb+1), (c, cc)) else
if x = c then ((a, ca), (b, cb), (c, cc+1)) else
((a, ca), (b, cb), (c, cc)))
fun count_abc ([], result) = result
| count_abc (x::xs, result) =
count_abc (xs, insert (x, result))
only instead of the histogram representation
(''a * int) * (''a * int) * (''a * int)
you want
(''a * int) list
and insert should be recursive rather than how insert_abc is repetitive.

How to create a function that encodes run-length using fold_right?

I created a function and helper function that find the number of repeating elements in a list, and what those elements.
let rec _encode l x =
match l with
| [] -> 0
| head::rest -> (if head = x then 1 else 0) + encode rest x
let encode l x = ((_encode l x), x)
In this case, I have to specify what that element is for it to search.
So this is a two part question. 1) How do I do it to return a list of tuples, with format (int * 'a) list, where int is the # of rep, and 'a is the element that is repeating.
2) How would I implement this using fold_right?
I was thinking something along the lines of:
let encode (l : 'a list) : (int * 'a) list = fold_right (fun (x,hd) lst ->
match x with
| [] -> 0
| hd :: rest -> if hd x then (x+1, hd) else (x, hd)) l []
Your attempt looks very confused:
It doesn't use lst, hd (the first one), or rest.
x is used as a list (match x with []) and a number (x+1).
The elements of x (list) are functions that return bools?? (... hd::rest -> ... if hd x)
The function sometimes returns a number (0) and sometimes a tuple ((x, hd)).
Here's how I'd do it:
let encode l =
let f x = function
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
let f x z = match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
fold_right (fun x z ->
match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
) l []

F# lazy recursion

I am have some problems with recursion in Lazy Computations. I need calculation the square root by Newton Raphson method. I do not know how to apply a lazy evaluation. This is my code:
let next x z = ((x + z / x) / 2.);
let rec iterate f x =
List.Cons(x, (iterate f (f x)));
let rec within eps list =
let a = float (List.head list);
let b = float (List.head (List.tail list));
let rest = (List.tail (List.tail (list)));
if (abs(a - b) <= eps * abs(b))
then b
else within eps (List.tail (list));
let lazySqrt a0 eps z =
within eps (iterate (next z) a0);
let result2 = lazySqrt 10. Eps fvalue;
printfn "lazy approach";
printfn "result: %f" result2;
Of course, stack overflow exception.
You're using F# lists which has eager evaluation. In your example, you need lazy evaluation and decomposing lists, so F# PowerPack's LazyList is appropriate to use:
let next z x = (x + z / x) / 2.
let rec iterate f x =
LazyList.consDelayed x (fun () -> iterate f (f x))
let rec within eps list =
match list with
| LazyList.Cons(a, LazyList.Cons(b, rest)) when abs(a - b) <= eps * abs(b) -> b
| LazyList.Cons(a, res) -> within eps res
| LazyList.Nil -> failwith "Unexpected pattern"
let lazySqrt a0 eps z =
within eps (iterate (next z) a0)
let result2 = lazySqrt 10. Eps fvalue
printfn "lazy approach"
printfn "result: %f" result2
Notice that I use pattern matching which is more idiomatic than head and tail.
If you don't mind a slightly different approach, Seq.unfold is natural here:
let next z x = (x + z / x) / 2.
let lazySqrt a0 eps z =
a0
|> Seq.unfold (fun a ->
let b = next z a
if abs(a - b) <= eps * abs(b) then None else Some(a, b))
|> Seq.fold (fun _ x -> x) a0
If you need lazy computations, then you have to use appropriate tools. List is not lazy, it is computed to the end. Your iterate function never ends, so the entire code stack overflows in this function.
You may use Seq here.
Note: Seq.skip almost inevitably leads you to an O(N^2) complexity.
let next N x = ((x + N / x) / 2.);
let rec iterate f x = seq {
yield x
yield! iterate f (f x)
}
let rec within eps list =
let a = Seq.head list
let b = list |> Seq.skip 1 |> Seq.head
if (abs(a - b) <= eps * abs(b))
then b
else list |> Seq.skip 1 |> within eps
let lazySqrt a0 eps z =
within eps (iterate (next z) a0);
let result2 = lazySqrt 10. 0.0001 42.;
printfn "lazy approach";
printfn "result: %f" result2;
// 6.4807406986501
Yet another approach is to use LazyList from F# PowerPack. The code is available in this article. Copying it to my answer for sake of integrity:
open Microsoft.FSharp.Collections.LazyList
let next N (x:float) = (x + N/x) / 2.0
let rec repeat f a =
LazyList.consDelayed a (fun() -> repeat f (f a))
let rec within (eps : float) = function
| LazyList.Cons(a, LazyList.Cons(b, rest)) when (abs (a - b)) <= eps -> b
| x -> within eps (LazyList.tail x)
let newton_square a0 eps N = within eps (repeat (next N) a0)
printfn "%A" (newton_square 16.0 0.001 16.0)
Some minor notes:
Your next function is wrong;
The meaning of eps is relative accuracy while in most academic books I've seen an absolute accuracy. The difference between the two is whether or not it's measured against b, here: <= eps * abs(b). The code from FPish treats eps as an absolute accuracy.

How to do an addition on a list with a condition?

I have a university course about functional programming, where I use SML. As a preparation for the exam, I am working on some of the older exam sets without solutions.
One of the only questions I really have problems with is the following question using foldl:
Consider the program skeleton: fun
addGt k xs = List.foldl (...) ... xs;
Fill in the two missing pieces
(represented by the dots ...), so that
addGt k xs is the sum of those
elements in xs, which are greater than
k. For example, addGt 4 [1, 5, 2, 7,
4, 8] = 5 + 7 + 8 = 20
I am sure this is really easy, but I have a very hard time understanding the foldl and foldr functions.
What I have now is the following (which seems to be very wrong if you ask my compiler!):
fun addGt(k,xs) = List.foldl ( fn x => if x > k then op+ else 0) 0 xs;
I would really appreciate some help with this question, and maybe a very short comment which would cast some light on the foldl and foldr functions!
A solution that I just though of is the following:
fun addGt(k, xs) = List.foldl (fn (x, y) => if x >= 5 then x + y else y) 0 xs;
But let me explain. First of all check the type of the List.foldl function, it's:
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
So List.foldl is a curried function that takes as first parameter another function of type ('a * 'b -> 'b). You used (fn x => if x > k then op+ else 0) which has type int -> int. You should instead provide List.foldl with a function that takes a tuple of type int * int and returns an int, so something like this: (fn (x, y) => do stuff). That's why your code didn't compile, you passed a wrong type of function in foldl.
Now you can think of foldl this way:
foldl f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_n, f(x_(n - 1), ..., f(x2, f(x1, b)) ...)) where f is a function of type ('a * 'b -> 'b), b is something of type 'b and the list [x_1, x_2, ..., x_(n - 1), x_n] is of type 'a list.
And similar for foldr you can think it in this way:
foldr f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_1, f(x_2, ..., f(x_(n - 1), f(x_ n, b))
If you call foldl f s ls on a list, ls = [x1, x2, ..., xn], then you get the result:
f(xn, ... f(x2, f(x1, s)))
That is, it starts by finding
a1 = f(x1, s)
Then
a2 = f(x2, a1)
and so on, until it's through the list.
When it's done, it returns an.
You can think of the a-values as being a sort of accumulator, that is, ai is the result as it would be if the list was only [x1, x2, ..., xi] (or rather, the first i elements of the list).
Your function will usually have the form:
fn (x, a) => ...
What you then need to do is think: Okay, if I have the next element in the list, x(i+1), and the value ai, which is the result for the list [x1, x2, ..., xi], what do I need to do to find the value a(i+1), which is the result for the list [x1, x2, ..., xi, x(i+1)].
s can be thought of as the value given to the empty list.
foldr works the same way, only you start from the back of the list instead of from the front.

Resources