Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find maximum, minimum and average in F#

I want to find maximum, minimum and average in an array without .NET in F#. I used this code but it is not working:

let mutable max = 0
let arrX = [|9; 11; 3; 4; 5; 6; 7; 8|]

for i in 0 .. arrX.Length - 2 do
  if (arrX.[i]) < (arrX.[i+1]) then 
       max <- arrX.[i]
       printfn "%i" max
like image 740
Massoud Avatar asked Dec 11 '11 08:12

Massoud


2 Answers

While the answers already posted are perfectly valid as to why your posted code doesn't work, I would argue that using a loop and a mutable variable isn't very ... functional. So I thought I would post a more F# - idiomatic way of solving it.

You state you "can't use .NET". I am guessing you mean you can't use any of the built-in functions or .NET libraries. Of course, that also means that you can implement them yourself using F# primitives.

One common function in the functional world is fold, which simply applies a function to all elements of a sequence, while keeping the return of that function in an accumulator. The built-in version is Seq.fold, but since we can't use that, we'll define one ourselves:

let rec fold accFn arr acc = 
    match arr with
    | [||] -> acc
    | _ -> fold accFn arr.[1..] (accFn arr.[0] acc)

This is a recursive function which applies the accFn function to each element, and then calling itself with the remainder of the array. When it gets passed an empty array, recursion terminates.

When we have that, let's define some simple functions to pass into fold:

let min x y =
    if x < y then x 
    else y

let max x y = 
    if x > y then x
    else y

let sum x y = 
    x + y

Once we have that, the solution to the stated problem is simple:

let arrX= [|9; 11; 3; 4; 5; 6; 7; 8|]
let head = arrX.[0]
let avg = (fold sum arrX 0) / arrX.Length
let minValue = fold min arrX head
let maxValue = fold max arrX head
like image 154
driis Avatar answered Oct 05 '22 22:10

driis


I fixed your code for max

let mutable max = 0
let arrX= [|9; 11; 3; 4; 5; 6; 7; 8|]

for i in 0 .. arrX.Length - 1 do
  if max < (arrX.[i]) then 
       max <- arrX.[i]
       printfn "%i" max

To find max, min and avg, using your approach:

let mutable max = System.Int32.MinValue
let mutable min = System.Int32.MaxValue
let mutable sum = 0
let arrX= [|9; 11; 3; 4; 5; 6; 7; 8|]

for i in 0 .. arrX.Length - 1 do
  if max < (arrX.[i]) then 
       max <- arrX.[i]
       printfn "max %i" max
  if min > (arrX.[i]) then 
       min <- arrX.[i]
       printfn "min %i" min
  sum <- sum + arrX.[i]
printfn "-> max is %i" max
printfn "-> min is %i" min
printfn "-> avg is %f" (float sum / float arrX.Length)

But note you can do just:

let max = Seq.max arrX
let min = Seq.min arrX
let avg = Seq.averageBy float arrX
like image 33
Gus Avatar answered Oct 05 '22 21:10

Gus