F# - how to write nested loops in a recursive way? - f#

Given the following C# code:
var product = new List<int>();
for (int n1 = 100; n1 < 1000; n1++)
{
for (int n2 = 100; n2 < 1000; n2++)
{
product.Add(n1 * n2);
}
}
What would be the equivalent F# code written in a functional style?

I would just write it that way with the for-loops. Even a Haskell programmer would probably express this with a list comprehension, in which case you could write e.g.
let productsList =
[for x in 2..4 do
for y in 2..4 do
yield x*y]
in F#.

the solution that Brian suggests is definitely the best option (in F#). Sequence expressions give you an easier way to express what you mean, so why not use them?
Anyway, if you're doing this just as an excercise, then you can rewrite the nested loop as single recursive function and the outer loop as second (as Imagist suggests):
let product =
let rec outer(n1) =
let rec nested(n2) =
if n2 > 4 then [] else (n1 * n2)::(nested(n2 + 1))
if n1 > 4 then [] else nested(2) # outer(n1 + 1)
outer(2)
I'm using :: in the nested function to append elements to the beginning and # to concatenate lists generated by individual nested function calls. The use of # isn't very efficient and the code also isn't tail-recursive, so better version using accumulator parameter would look like this:
let product =
let rec outer n1 acc =
let rec nested n2 acc =
if n2 > 4 then acc else nested (n2 + 1) ((n1 * n2)::acc)
if n1 > 4 then acc else outer (n1 + 1) (nested 2 acc)
outer 2 [] |> List.rev
Hope this helps!

Related

F# Array.tryFindIndex start search from an index

I wonder if there's a cheap(performance wise) option to search an index of array element which meets certain criteria starting from an index?
Array.tryFindIndex method doesn't have an argument startIndex. I could do Array.skip(n) and then search there but it seems expensive to create an array just for search. How do I do this?
I looked List also doesn't have that argument.
Do I have to use while ... do? Is there a nicer way?
The base libraries try to provide functions for your convenience but they cannot possibly anticipate all use cases. Nothing wrong with writing your own if need be:
module Array =
let tryFindIndexFrom i p (a : _ []) =
let rec loop k =
if k >= a.Length then None
elif p a.[k] then Some k
else loop (k + 1)
if i < 0 then None else loop i
EDIT: p is the predicate testing the array elements. tryFindIndexFrom has the same signature as tryFindIndex but with the starting index added as first parameter.
EDIT 2: Added test for k < 0 for fool-proof usage.
EDIT 3: Moved test for k < 0 out of the loop as it needs to be checked only once.
Here's a way to do it using a lazy sequence of array indexes:
let input = [| 'a' .. 'z' |]
seq { 4 .. input.Length - 1 }
|> Seq.tryFind (fun i -> input |> Array.tryItem i = Some 'x')
I'll leave it to you to generalise this into a helper function if you think that's necessary.
The nice thing about the current form is that it's quite flexible. You can change the maximum index easily, or search backwards, e.g. seq { input.Length - 1 .. -1 .. 4 }.
Follow your instinct. Considering Array.skip but noting the obvious waste of allocating a second array, you can take it one step further and generalize to the lazily evaluated Seq.skip, compose it with the standard Seq.tryFindIndex function and add the offset, if applicable.
let tryFindIndexMin n p =
Seq.skip n
>> Seq.tryFindIndex p
>> Option.map ((+) n)
// val tryFindIndexMin : n:int -> p:('a -> bool) -> (seq<'a> -> int option)
[ for i in 0..3 ->
[|"a"; "b"; "a"; "b"|]
|> tryFindIndexMin i ((=) "a") ]
// val it : int option list = [Some 0; Some 2; Some 2; null]

Functional digits reversion

In C, I would solve the problem with a loop. To represent the idea, something like:
void foo(int x){
while(x > 0){
printf("%d", x % 10);
x /= 10;
}
}
With F#, I am unable to make the function return the single values. I tried:
let reverse =
let aux =
fun x ->
x % 10
let rec aux2 =
fun x ->
if x = 0 then 0
else aux2(aux(x / 10))
aux2 n
but it returns always the base case 0.
I cannot get my mind beyond this approach, where the recursion results are maintained with an operation, and cannot be reported (according to may comprehension) individually:
let reverse2 =
let rec aux =
fun x ->
if x = 0 then 0
else (x % 10) + aux (x / 10) // The operation returning the result
aux n
This is a simple exercise I am doing in order to "functionalize" my mind. Hence, I am looking for an approach to this problem not involving library functions.
A for loop that changes the value of mutable variables can be rewritten as a recursive function. You can think of the mutable variables as implicit parameters to the function. So if we have a mutable variable x, we need to instead pass the new state of x explicitly as a function parameter. The closest equivalent to your C function as a recursive F# function is this:
let rec foo x =
if x > 0 then
printf "%d" (x % 10)
foo (x / 10)
This in itself isn't particularly functional because it returns unit and only has side effects. You can collect the result of each loop using another parameter. This is often called an accumulator:
let foo x =
let rec loop x acc =
if x > 0 then
loop (x / 10) (x % 10 :: acc)
else acc
loop x [] |> List.rev
foo 100 // [0; 0; 1]
I made an inner loop function that is actually the recursive one. The outer foo function starts off the inner loop with [] as the accumulator. Items are added to the start of the list during each iteration and the accumulator list is reversed at the end.
You can use another type as the accumulator, e.g. a string, and append to the string instead of adding items to the list.

Assignment: this expression was expected to have the type unit

I'm writing some thing really easy, a program that finds all factors of an int. Here is what I have
let factor n=
let ls=[]
for i=1 to n do
if i % n =0 then ls = i::ls
l
If I do this then it pops an error This expression was expected to have the type unit. But I tried to put an expression that prints something after if..then.., which is suppose to return type unit, but it still gives the same error. I am lost about this. Can someone help please? Thanks
You are trying to make ls into a mutable variable nd assign it with =. While this is possible, by using mutable (1) or ref (2) along with <- or := assignment operators, this is generally discouraged in the functional world.
A possibly more idiomatic implementation of the naive algorithm could be:
let factor n =
let rec factorLoop curr divs =
if curr > n then divs
else
if n % curr = 0
then factorLoop (curr+1) (curr::divs)
else factorLoop (curr+1) divs
factorLoop 1 [] |> List.rev
> factor 12;;
val it : int list = [1; 2; 3; 4; 6; 12]
Here the main function defines an inner factorLoop function that is recursive. Recursion is the way we can avoid many uses of mutable variables in functional languages. The recursive inner function threads along a curr variable that is the current divisor to be tested and a list divs of currently found divisors. The result includes 1 and n. This can be altered respectively by changing the initial value of curr and the terminating condition in the first line of factorLoop.
It is worth noting that it can all be shrunk down to one line by making use of the F# library:
let factor n =
[1..n] |> List.filter (fun x -> n % x = 0)
Here we build a list of values 1..n and feed them to List.filter which applies the given predicate (at the end of the line) to select only divisors on n. If n is large, however, the temp list will grow very large. We can use a lazily evaluated sequence instead, which won't blow the memory usage:
let factor n =
{1..n} |> Seq.filter (fun x -> n % x = 0) |> Seq.toList
Here we filter on a 'lazy' sequence and only convert the (much smaller) sequence of results to a list at the end:
> factor 10000000;;
val it : int list =
[1; 2; 4; 5; 8; 10; 16; 20; 25; 32; ... etc
= is comparison, not assignment. You want either
let factor n =
let mutable ls = []
for i = 1 to n do
if n % i = 0 then ls <- i::ls
ls
or
let factor n =
let ls = ref []
for i = 1 to n do
if n % i = 0 then ls := i::(!ls)
!ls
Note, however, that both of these solutions are highly unidiomatic, as there are equally easy immutable solutions to this problem.

F# solution for Store Credit

I want to solve this excercise: http://code.google.com/codejam/contest/351101/dashboard#s=p0 using F#.
I am new to functional programming and F# but I like the concept and the language a lot. And I love the codejam excercise too it looks so easy but real life. Could somebody point me out a solution?
At the moment I have written this code which is just plain imperative and looks ugly from the functional perspective:
(*
C - Credit
L - Items
I - List of Integer, wher P is single integer
How does the data look like inside file
N
[...
* Money
* Items in store
...]
*)
let lines = System.IO.File.ReadAllLines("../../../../data/A-small-practice.in")
let CBounds c = c >= 5 && c <= 1000
let PBounds p = p >= 1 && p <= 1000
let entries = int(lines.[0]) - 1
let mutable index = 1 (* First index is how many entries*)
let mutable case = 1
for i = 0 to entries do
let index = (i*3) + 1
let C = int(lines.[index])
let L = int(lines.[index+1])
let I = lines.[index+2]
let items = I.Split([|' '|]) |> Array.map int
// C must be the sum of some items
// Ugly imperative way which contains duplicates
let mutable nIndex = 0
for n in items do
nIndex <- nIndex + 1
let mutable mIndex = nIndex
for m in items.[nIndex..] do
mIndex <- mIndex + 1
if n + m = C then do
printfn "Case #%A: %A %A" case nIndex mIndex
case <- case + 1
I would like to find out items which add up to C value but not in a usual imperative way - I want functional approach.
You don't specify how you would solve the problem, so it's hard to give advices.
Regarding reading inputs, you can express it as a series of transformation on Seq. High-order functions from Seq module are very handy:
let data =
"../../../../data/A-small-practice.in"
|> System.IO.File.ReadLines
|> Seq.skip 1
|> Seq.windowed 3
|> Seq.map (fun lines -> let C = int(lines.[0])
let L = int(lines.[1])
let items = lines.[2].Split([|' '|]) |> Array.map int
(C, L, items))
UPDATE:
For the rest of your example, you could use sequence expression. It is functional enough and easy to express nested computations:
let results =
seq {
for (C, _, items) in data do
for j in 1..items.Length-1 do
for i in 0..j-1 do
if items.[j] + items.[i] = C then yield (i, j)
}
Seq.iteri (fun case (i, j) -> printfn "Case #%A: %A %A" case i j) results

Converting a loop to pure functions

I have this code written for a Project Euler problem in c++:
int sum = 0;
for(int i =0; i < 1000; i++)
{
//Check if multiple of 3 but not multiple of 5 to prevent duplicate
sum += i % 3 == 0 && i % 5 != 0 ? i: 0;
//check for all multiple of 5, including those of 3
sum += i % 5 == 0 ? i: 0;
}
cout << sum;
I'm trying to learn f# and rewriting this in f#. This is what I have so far:
open System
//function to calculate the multiples
let multiple3v5 num =
num
//function to calculate sum of list items
let rec SumList xs =
match xs with
| [] -> 0
| y::ys -> y + SumList ys
let sum = Array.map multiple3v5 [|1 .. 1000|]
What I have may be complete nonsense...so help please?
Your sumList function is a good start. It already iterates (recursively) over the entire list, so you don't need to wrap it in an additional Array.map. You just need to extend your sumList so that it adds the number only when it matches the specified condition.
Here is a solution to a simplified problem - add all numbers that are divisible by 3:
open System
let rec sumList xs =
match xs with
| [] -> 0 // If the list is empty, the sum is zero
| y::ys when y % 3 = 0 ->
// If the list starts with y that is divisible by 3, then we add 'y' to the
// sum that we get by recursively processing the rest of the list
y + sumList ys
| y::ys ->
// This will only execute when y is not divisible by 3, so we just
// recursively process the rest of the list and return
/// that (without adding current value)
sumList ys
// For testing, let's sum all numbers divisble by 3 between 1 and 10.
let sum = sumList [ 1 .. 10 ]
This is the basic way of writing the function using explicit recursion. In practice, the solution by jpalmer is how I'd solve it too, but it is useful to write a few recursive functions yourself if you're learning F#.
The accumulator parameter mentioned by sashang is a more advanced way to write this. You'll need to do that if you want to run the function on large inputs (which is likely the case in Euler problem). When using accumulator parameter, the function can be written using tail recursion, so it avoids stack overflow even when processing long lists.
The idea of a accumulator-based version is that the function takes additional parameter, which represents the sum calculated so far.
let rec sumList xs sumSoFar = ...
When you call it initially, you write sumList [ ... ] 0. The recursive calls will not call y + sumList xs, but will instead add y to the accumulator and then make the recursive call sumList xs (y + sumSoFar). This way, the F# compiler can do tail-call optimization and it will translate code to a loop (similar to the C++ version).
I'm not sure if translating from an imperative language solution is a good approach to developing a functional mindset as instrument (C++ in your case) had already defined an (imperative) approach to solution, so it's better sticking to original problem outlay.
Overall tasks from Project Euler are excellent for mastering many F# facilities. For example, you may use list comprehensions like in the snippet below
// multipleOf3Or5 function definition is left for your exercise
let sumOfMultiples n =
[ for x in 1 .. n do if multipleOf3Or5 x then yield x] |> List.sum
sumOfMultiples 999
or you can a bit generalize the solution suggested by #jpalmer by exploiting laziness:
Seq.initInfinite id
|> Seq.filter multipleOf3Or5
|> Seq.takeWhile ((>) 1000)
|> Seq.sum
or you may even use this opportunity to master active patterns:
let (|DivisibleBy|_) divisior num = if num % divisor = 0 the Some(num) else None
{1..999}
|> Seq.map (fun i ->
match i with | DivisibleBy 3 i -> i | DivisibleBy 5 i -> i | _ -> 0)
|> Seq.sum
All three variations above implement a common pattern of making a sequence of members with sought property and then folding it by calculating sum.
F# has many more functions than just map - this problem suggests using filter and sum, my approach would be something like
let valid n = Left as an exercise
let r =
[1..1000]
|> List.filter valid
|> List.sum
printfn "%i" r
I didn't want to do the whole problem, but filling in the missing function shouldn't be too hard
This is how you turn a loop with a counter into a recursive function. You do this by passing an accumulator parameter to the loop function that holds the current loop count.
For example:
let rec loop acc =
if acc = 10 then
printfn "endloop"
else
printfn "%d" acc
loop (acc + 1)
loop 0
This will stop when acc is 10.

Resources