comparing length of sublists in a list F# - f#

I'm new to F#, and currently working on a problem where I'm trying to compare the length of sublists inside a list, and returning a boolean.
The program is also supposed to return "false" in case any of the sublists are empty. However as I've been progressing I haven't been able to solve my current problem, even though I somehow see what is wrong (this linked to my experience in the F# language thus far). Hopefully someone can lend me a hand, so I can quickly move on to my next project.
My program so far is as follows:
let projectOne (initList: int list list) =
let mutable lst = initList.[0].Length
let mutable lst1 = ""
let n = initList.Length
for i=1 to n-1 do
if lst = 0 || initList.[i].Length = 0 then
lst1 <- "false"
elif lst <> initList.[i].Length then
lst1 <- "false"
elif
lst = initList.[i].Length then
lst1 <- "true"
lst1
printfn "The sublists are of same lenght: %A" (projectOne [[1;2;3;4];[4;5;6];[6;7;8;9];[5;6;7;8]])
The way I see it is, that right now I am comparing [0] with [i] incrementing with each iteration in my loop, this causes a problem as for the print example, I end my iterations by comparing [0] with [3] and since the 2 sublists are of equal size my function returns "true" which is obviously wrong, since [1] is of length shorter than the rest, hence the result should be "false".
I've tried to solve this by mutating the value of lst, for each iteration, but this again causes a problem if for instance [2] and [3] are same length but [0] and [1] are not, and again it returns "true" even though the output should be "false". (like [[1;2;3];[3;4;5];[6;7];[8;9]])
I can't seem to wrap my head around what I've missed. Since I cant break a loop in F# (at least not in a traditional way like Python), I need to run all my iterations, but I want each iteration to compare with the average of all the previous sublists length (if that makes sense).
What am I missing? :-) I have though of using af List.fold operator to solve the problem, but not sure how I am going to implement this, with the fact that the program also need to check for empty lists.
I can say however I am trying to solve the problem using the metod appropriate to my level og experience thus far. I am sure that several very compact solutions using the pipeline operator |> are available, but I am not yet capable of utilizing these solutions, so I am looking for a simpler perhabs beginners solution.
Thanks in advance.

A more functional way to think about this would be
If all the sublists are empty, they are all the same length
Otherwise, if any of the sublists are empty, they are not of the same length
Otherwise, the lists are all the same length if their tails are all the same length
For example:
let rec projectOne initList =
if List.forall List.isEmpty initList then
true
else if List.exists List.isEmpty initList then
false
else
projectOne (List.map List.tail initList)

Here is another take:
let projectOne lst =
match lst with
| h::t -> t |> List.forall(fun (l:_ list) -> l.Length = h.Length)
| _ -> true

A simple fix of your code could be:
let projectOne (initList: int list list) =
let length = initList.[0].Length
let mutable result = length <> 0
let n = initList.Length
for i=1 to n-1 do
result <- result && initList.[i].Length = length
result
It still operates on a mutable variable which is undesirable in functional programming and it is inefficient in that it searches all lists even if a wrong length has been found.
Another - more functional - solution could be:
let haveEqualLength lists =
let length = lists |> List.head |> List.length
length <> 0 && lists |> List.tail |> List.tryFind (fun l -> l.Length <> length) = None

Related

Compare values in a list

Trying to conceptualize how I would compare several values in a list to find the largest value, without using mutable variables.
For example in an imperative language I could simply store a max variable that gets updated every time the iteration finds a larger value in the list. Like such:
max = 0;
for i in list
if i > max
max = i
Now, in functional programming if i had a list, for example [1; 2; 3]
How would I get around the issue of using a max variable?
The easy answer would be to use let maxValue = List.max theList.
If you were wanting to 'roll your own' without using an explicitly mutable variable, the obvious way is to use a recursive function. Personally, I would define it like so:
let listMax theList =
let rec maxHelper remainingList maxSoFar =
match remainingList with
| [] -> maxSoFar
| h :: t ->
if h > maxSoFar then
maxHelper t h
else
maxHelper t maxSoFar
maxHelper theList (List.head theList)
Note that this implementation as presented would throw an exception with an empty input list (also, I haven't actually tested this, so there might be a slight error in there). The reason I have done it this way is that it uses tail recursion, which should mean it's roughly as efficient as a mutable solution, but keeps the complexity of the exposed function signature to the bare minimum.
Alternatively, this could also be done fairly easily with a List.fold call. E.g.
List.fold (fun (nextElem, maxSoFar) ->
if nextElem > maxSoFar then nextElem else maxSoFar) (List.head theList) theList
Same proviso about not having tested it applies to this too.
In both of the presented cases, this could be made more generic to apply to any binary operation that returns a boolean, by using another parameter that is a function which carries out said operation. E.g.
List.fold (fun (nextElem, maxSoFar) ->
if comparatorFunction nextElem maxSoFar then nextElem else maxSoFar)
(List.head theList) theList

How do I print out the entire Fibonacci sequence up to a user inputted value in F#?

So I have a program that, currently, finds the fibonacci equivalent of a user inputted value, e.g. 6 would be 5 (or 13 depending on whether or not you start with a 0). Personally I prefer the sequence starting with 0.
open System
let rec fib (n1 : bigint) (n2 : bigint) c =
if c = 1 then
n2
else
fib n2 (n1+n2) (c-1);;
let GetFib n =
(fib 1I 1I n);;
let input = Console.ReadLine()
Console.WriteLine(GetFib (Int32.Parse input))
The problem is that ALL it does is find the equivalent number in the sequence. I am trying to get it to print out all the values up to that user inputted value, e.g. 6 would print out 0,1,1,2,3,5. If anyone could help me figure out how to print out the whole sequence, that would be very helpful. Also if anyone can look at my code and tell me how to make it start at 0 when printing out the whole sequence, that would also be very much appreciated.
Thank you in advance for any help.
Take a look at the link s952163 gave you in the comments - that shows ways of generating a fibonnaci sequence using Seq expressions and also explains why these are useful.
The following will print a sequence up until the specified sequence number:
let fibsTo n = Seq.unfold (fun (m,n) -> Some (m, (n,n+m))) (0I,1I)
|>Seq.takeWhile (fun x -> x <= n)
let input = Console.ReadLine()
(fibsTo (Numerics.BigInteger.Parse input))|>Seq.iter(printfn "%A")
Note the use of printfn rather than console.writeline, the former is more idiomatic.
Also, you may want to consider handling negative inputs here as these will throw an error.

Avoid mutation in this example in F#

Coming from an OO background, I am having trouble wrapping my head around how to solve simple issues with FP when trying to avoid mutation.
let mutable run = true
let player1List = ["he"; "ho"; "ha"]
let addValue lst value =
value :: lst
while run do
let input = Console.ReadLine()
addValue player1List input |> printfn "%A"
if player1List.Length > 5 then
run <- false
printfn "all done" // daz never gunna happen
I know it is ok to use mutation in certain cases, but I am trying to train myself to avoid mutation as the default. With that said, can someone please show me an example of the above w/o using mutation in F#?
The final result should be that player1List continues to grow until the length of items are 6, then exit and print 'all done'
The easiest way is to use recursion
open System
let rec makelist l =
match l |> List.length with
|6 -> printfn "all done"; l
| _ -> makelist ((Console.ReadLine())::l)
makelist []
I also removed some the addValue function as it is far more idiomatic to just use :: in typical F# code.
Your original code also has a common problem for new F# coders that you use run = false when you wanted run <- false. In F#, = is always for comparison. The compiler does actually warn about this.
As others already explained, you can rewrite imperative loops using recursion. This is useful because it is an approach that always works and is quite fundamental to functional programming.
Alternatively, F# provides a rich set of library functions for working with collections, which can actually nicely express the logic that you need. So, you could write something like:
let player1List = ["he"; "ho"; "ha"]
let player2List = Seq.initInfinite (fun _ -> Console.ReadLine())
let listOf6 = Seq.append player1List list2 |> Seq.take 6 |> List.ofSeq
The idea here is that you create an infinite lazy sequence that reads inputs from the console, append it at the end of your initial player1List and then take first 6 elements.
Depending on what your actual logic is, you might do this a bit differently, but the nice thing is that this is probably closer to the logic that you want to implement...
In F#, we use recursion to do loop. However, if you know how many times you need to iterate, you could use F# List.fold like this to hide the recursion implementation.
[1..6] |> List.fold (fun acc _ -> Console.ReadLine()::acc) []
I would remove the pipe from match for readability but use it in the last expression to avoid extra brackets:
open System
let rec makelist l =
match List.length l with
| 6 -> printfn "all done"; l
| _ -> Console.ReadLine()::l |> makelist
makelist []

F# Cumulative Product of an array

Using F#, I would like to calculate the cumulative product of an Array without any loop. A first idea will be to use Array.fold and Array.map but I don't see how I can use them. What do you suggest? or peharps using a recursive function? Many thanks in advance for your help.
If you need the product of all elements, you can use fold indeed:
> let a = [|1;2;3;4;5|];
> a |> Array.fold (*) 1;;
val it : int = 120
If you need the intermediate (cumulative) results, you can use scan. Scan takes each element in the array and applies a function (product in this case) to the element, and the previous cumulative result. Starting with a value of 1 for the accumulator, we get:
> a |> Array.scan (*) 1;;
val it : int [] = [|1; 1; 2; 6; 24; 120|]
You can use Array.scan:
let products = arr |> Array.scan (*) 1;;
Others already gave nice answers, just a general remark. Your statement "or perhaps a recursive function" is usually unnecessary. About 95% of the time, you can use a fold instead. Where recursive functions are the way to go, is if you need a non-standard iteration order.
Apart from that think in terms of not how to do the whole operation at once, i.e. how to process a list of numbers in your case, but just think how to do it for one item.
From that you get that you e.g. need to multiply the item with the accumulator. So in this case your no longer needs to be recursive, because with fold you abstracted over the iteration itself.
If you want to use tail recursive function to do the job. You might want to try sth similar:
let l = [1;2;3;4;5]
let product lst =
let rec pTR acc = function
| [] -> acc
| h::t -> pTR (h * acc) t
pTR 1 lst
product l

Comparing values in loop inside function

I want to make a function that takes an integer list as argument and compares every value and returns the largest value. In C# I would simply iterate through every value in the list, save the largest to a variable and return it, I'm hoping F# works similarly but the syntax is kinda iffy for me, here's what my code looks like. Also max2 is a function that compares 2 values and returns the largest.
let max_list list =
let a = 0 : int
match list with
| head :: tail -> (for i in list do a = max2 i a) a
| [] -> failwith "sry";;
You could use mutable variable and write the code using for loop, just like in C#. However, if you're doing this to learn F# and functional concepts, then it's good idea to use recursion.
In this case, recursive function is a bit longer, but it demonstrates the key concepts including pattern matching - so learning the tricks is something that will be useful when writing more complicated F# code.
The key idea is to write a function that takes the largest value found so far and calls itself recursively until it reaches the end of the list.
let max_list list =
// Inner recursive function that takes the largest value found so far
// and a list to be processed (if it is empty, it returns 'maxSoFar')
let rec loop maxSoFar list =
match list with
// If the head value is greater than what we found so far, use it as new greater
| head::tail when head > maxSoFar -> loop head tail
// If the head is smaller, use the previous maxSoFar value
| _::tail -> loop maxSoFar tail
// At the end, just return the largest value found so far
| [] -> maxSoFar
// Start with head as the greatest and tail as the rest to be processed
// (fails for empty list - but you could match here to give better error)
loop (List.head list) (List.tail list)
As a final note, this will be slow because it uses generic comparison (via an interface). You can make the function faster using let inline max_list list = (...). That way, the code will use native comparison instruction when used with primitive types like int (this is really a special case - the problem only really happens with generic comparison)
Also know that you can write a nice one-liner using reduce:
let max_list list = List.reduce (fun max x -> if x > max then x else max)
If your intention is to be able to find the maximum value of items in a list where the value of the items is found by the function max2 then this approach works:
let findMax list =
list
|> List.map (fun i -> i, max2 i)
|> List.maxBy snd
|> fst

Resources