Project Euler Problem 2 in F# - f#

I'm a bit stuck on the last step of getting the solution to problem 2 on Project Euler. This is the source I've gotten so far.
#light
module pe2 (* Project Euler Problem 2 solution *)
open System
let Phi = 1.6180339887;;
let invPhi = 1.0/Phi;;
let rootOfFive = 2.236067977;;
let maxFib = 4000000.0;
let Fib n =
System.Math.Round((Phi**n - invPhi**n)/rootOfFive);;
let FibIndices = Seq.unfold(fun i -> Some(i, i+3.0)) 3.0;;
let FibNos = FibIndices |> Seq.map(fun index -> Fib(index));;
let setAllowedFibNos = FibNos |> Seq.filter(fun fn -> (fn <= maxFib));;
// let answer = setAllowedFibNos |> Seq.fold (+) 0.0;
When I uncomment the last line, the process never seems to finish. So I was hoping that someone could give me a gentle nudge in the right direction. I did look at setAllowedFibNos and it looks right but it's also an infinite sequence so I only see the first three terms.
Also, could someone point me to the right way to chain the various sequences together? I tried something like this:
let answer = Seq.unfold(fun i-> Some(i, i + 3.0)) 3.0
|> Seq.map (fun index -> Fib(index))
|> Seq.filter(fun fn -> (fn <= maxFib))
|> Seq.fold (+) 0.0;;
But that didn't work. As you can probably guess I'm just learning F# so please go gentle and if this sort of question has been asked and answered before, please post a link to the answer and I'll withdraw this one.

let rec Fib(n) =
if (n < 2) then
1
else
Fib(n-2) + Fib(n-1)
Seq.initInfinite Fib
|> Seq.takeWhile (fun a -> a <= 4000000)
|> Seq.filter (fun a -> (a % 2) = 0)
|> Seq.fold (+) 0

'setAllowedFibNos' is indeed an infinite seq computation; 'fold' needs the whole sequence, so the 'filter' will run forever looking for another number <= maxFib.
Take a look at takeWhile:
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/FSharp.Core/Microsoft.FSharp.Collections.Seq.html
I think it is what you want instead of filter.
Also note that you can use 'sqrt 5.0'.

I'm still trying to get used to the Seq approach. But, here is my solution without it.
#light
let rec fib n =
match n with
|0|1 -> n
|_ -> fib(n-1) + fib(n-2)
let maxFib = 4000000
let phi = (1.0 + sqrt(5.0)) / 2.0
let upperBound = 1 + int( log10((float(maxFib) - 0.5) * sqrt(5.0)) / log10(phi))
[1..upperBound] |> List.filter (fun x-> x%3=0) |> List.map fib |> List.filter (fun x -> x%2 = 0) |> List.filter (fun x -> x List.sum |> printfn "%d"

My solution is:
Seq.unfold (fun state ->
if (fst state + snd state > 4000000) then None
else Some(fst state + snd state, (snd state, fst state + snd state))) (0,1)
|> Seq.filter (fun x -> x % 2 = 0)
|> Seq.sum;;

Related

Better way to sum rows

I'm learning F# (again) and I'm trying to sum some rows in excel. This is my attempt.
let sumRows (source: seq<double[]>) =
source
|> Seq.reduce (fun a b -> (a, b) ||> Seq.map2 (fun x y -> x + y) |> Seq.toArray)
Can it be done better? I already discovered double forward pipe operator, but now, whole part fun a b -> (a, b) ||> seems quite redundant...
You are right it is redundant, because the double pipe operator is convenient only when you need to convert a tuple into two separate parameters. In this case you already have them as 2 separate parameters so you could just pass them like this:
let sumRows (source: seq<double[]>) =
source
|> Seq.reduce (fun a b -> Seq.map2 (fun x y -> x + y) a b |> Seq.toArray)
We can get rid of the |> Seq.toArray by replacing Seq.map2 with Array.map2:
let sumRows (source: seq<double[]>) =
source
|> Seq.reduce (fun a b -> Array.map2 (fun x y -> x + y) a b)
now we can simplify further by removing the fun a b ->:
let sumRows (source: seq<double[]>) =
source
|> Seq.reduce (Array.map2 (fun x y -> x + y) )
Finally, did you know that an operator like + can be treated as a 2 parameters function
by putting in parenthesis (+)?
let sumRows2 (source: seq<double[]>) =
source
|> Seq.reduce (Array.map2 (+) )
All of this versions have the same signature and they are all correct. You choose whichever suits more your style.
BTW, you maybe tempted to go one further and do this:
let sumRows2 = Seq.reduce (Array.map2 (+) )
but it causes issues with the famous Value restriction error. There are workarounds like adding the type annotation or actually using it somewhere in the code, but the best workaround is to add the parameter, like we had before.

F#, loop control until n-2

I am currently learning functional programming and F#, and I want to do a loop control until n-2. For example:
Given a list of doubles, find the pairwise average,
e.g. pairwiseAverage [1.0; 2.0; 3.0; 4.0; 5.0] will give [1.5; 2.5; 3.5; 4.5]
After doing some experimenting and searching, I have a few ways to do it:
Method 1:
let pairwiseAverage (data: List<double>) =
[for j in 0 .. data.Length-2 do
yield (data.[j]+data.[j+1])/2.0]
Method 2:
let pairwiseAverage (data: List<double>) =
let averageWithNone acc next =
match acc with
| (_,None) -> ([],Some(next))
| (result,Some prev) -> ((prev+next)/2.0)::result,Some(next))
let resultTuple = List.fold averageWithNone ([],None) data
match resultTuple with
| (x,_) -> List.rev x
Method 3:
let pairwiseAverage (data: List<double>) =
// Get elements from 1 .. n-1
let after = List.tail data
// Get elements from 0 .. n-2
let before =
data |> List.rev
|> List.tail
|> List.rev
List.map2 (fun x y -> (x+y)/2.0) before after
I just like to know if there are other ways to approach this problem. Thank you.
Using only built-ins:
list |> Seq.windowed 2 |> Seq.map Array.average
Seq.windowed n gives you sliding windows of n elements each.
One simple other way is to use Seq.pairwise
something like
list |> Seq.pairwise |> Seq.map (fun (a,b) -> (a+b)/2.0)
The approaches suggested above are appropriate for short windows, like the one in the question. For windows with a length greater than 2 one cannot use pairwise. The answer by hlo generalizes to wider windows and is a clean and fast approach if window length is not too large. For very wide windows the code below runs faster, as it only adds one number and subtracts another one from the value obtained for the previous window. Notice that Seq.map2 (and Seq.map) automatically deal with sequences of different lengths.
let movingAverage (n: int) (xs: float List) =
let init = xs |> (Seq.take n) |> Seq.sum
let additions = Seq.map2 (fun x y -> x - y) (Seq.skip n xs) xs
Seq.fold (fun m x -> ((List.head m) + x)::m) [init] additions
|> List.rev
|> List.map (fun (x: float) -> x/(float n))
xs = [1.0..1000000.0]
movingAverage 1000 xs
// Real: 00:00:00.265, CPU: 00:00:00.265, GC gen0: 10, gen1: 10, gen2: 0
For comparison, the function above performs the calculation above about 60 times faster than the windowed equivalent:
let windowedAverage (n: int) (xs: float List) =
xs
|> Seq.windowed n
|> Seq.map Array.average
|> Seq.toList
windowedAverage 1000 xs
// Real: 00:00:15.634, CPU: 00:00:15.500, GC gen0: 74, gen1: 74, gen2: 71
I tried to eliminate List.rev using foldBack but did not succeed.
A point-free approach:
let pairwiseAverage = List.pairwise >> List.map ((<||) (+) >> (*) 0.5)
Online Demo
Usually not a better way, but another way regardless... ;-]

Get a list of invalid drive letters

let private GetDrives = seq{
let all=System.IO.DriveInfo.GetDrives()
for d in all do
//if(d.IsReady && d.DriveType=System.IO.DriveType.Fixed) then
yield d
}
let valid={'A'..'Z'}
let rec SearchRegistryForInvalidDrive (start:RegistryKey) = seq{
let validDrives=GetDrives |> Seq.map (fun x -> x.Name.Substring(0,1))
let invalidDrives= Seq.toList validDrives |> List.filter(fun x-> not (List.exists2 x b)) //(List.exists is the wrong method I think, but it doesn't compile
I followed F#: Filter items found in one list from another list but could not apply it to my problem as both the solutions I see don't seem to compile. List.Contains doesn't exist (missing a reference?) and ListA - ListB doesn't compile either.
open System.IO
let driveLetters = set [ for d in DriveInfo.GetDrives() -> d.Name.[0] ]
let unused = set ['A'..'Z'] - driveLetters
Your first error is mixing between char and string, it is good to start with char:
let all = {'A'..'Z'}
let validDrives = GetDrives |> Seq.map (fun x -> x.Name.[0])
Now invalid drive letters are those letters which are in all but not in validDrives:
let invalidDrives =
all |> Seq.filter (fun c -> validDrives |> List.forall ((<>) c))
Since validDrives is traversed many times to check for membership, turning it to a set is better in this example:
let all = {'A'..'Z'}
let validDrives = GetDrives |> Seq.map (fun x -> x.Name.[0]) |> Set.ofSeq
let invalidDrives = all |> Seq.filter (not << validDrives.Contains)

How to make this code more compact and idiomatic?

Hullo all.
I am a C# programmer, exploring F# in my free time. I have written the following little program for image convolution in 2D.
open System
let convolve y x =
y |> List.map (fun ye -> x |> List.map ((*) ye))
|> List.mapi (fun i l -> [for q in 1..i -> 0] # l # [for q in 1..(l.Length - i - 1) -> 0])
|> List.reduce (fun r c -> List.zip r c |> List.map (fun (a, b) -> a + b))
let y = [2; 3; 1; 4]
let x = [4; 1; 2; 3]
printfn "%A" (convolve y x)
My question is: Is the above code an idiomatic F#? Can it be made more concise? (e.g. Is there some shorter way to generate a filled list of 0's (I have used list comprehension in my code for this purpose)). Any changes that can improve its performance?
Any help would be greatly appreciated. Thanks.
EDIT:
Thanks Brian. I didn't get your first suggestion. Here's how my code looks after applying your second suggestion. (I also abstracted out the list-fill operation.)
open System
let listFill howMany withWhat = [for i in 1..howMany -> withWhat]
let convolve y x =
y |> List.map (fun ye -> x |> List.map ((*) ye))
|> List.mapi (fun i l -> (listFill i 0) # l # (listFill (l.Length - i - 1) 0))
|> List.reduce (List.map2 (+))
let y = [2; 3; 1; 4]
let x = [4; 1; 2; 3]
printfn "%A" (convolve y x)
Anything else can be improved? Awaiting more suggestions...
As Brian mentioned, the use of # is generally problematic, because the operator cannot be efficiently implemented for (simple) functional lists - it needs to copy the entire first list.
I think Brians suggestion was to write a sequence generator that would generate the list at once, but that's a bit more complicated. You'd have to convert the list to array and then write something like:
let convolve y x =
y |> List.map (fun ye -> x |> List.map ((*) ye) |> Array.ofList)
|> List.mapi (fun i l -> Array.init (2 * l.Length - 1) (fun n ->
if n < i || n - i >= l.Length then 0 else l.[n - i]))
|> List.reduce (Array.map2 (+))
In general, if performance is an important concern, then you'll probably need to use arrays anyway (because this kind of problem can be best solved by accessing elements by index). Using arrays is a bit more difficult (you need to get the indexing right), but perfectly fine approach in F#.
Anyway, if you want to write this using lists, then here ara some options. You could use sequence expressions everywhere, which would look like this:
let convolve y (x:_ list) =
[ for i, v1 in x |> List.zip [ 0 .. x.Length - 1] ->
[ yield! listFill i 0
for v2 in y do yield v1 * v2
yield! listFill (x.Length - i - 1) 0 ] ]
|> List.reduce (List.map2 (+))
... or you can also combine the two options and use a nested sequence expression (with yield! to generate zeros and lists) in the lambda function that you're passing to List.mapi:
let convolve y x =
y |> List.map (fun ye -> x |> List.map ((*) ye))
|> List.mapi (fun i l ->
[ for _ in 1 .. i do yield 0
yield! l
for _ in 1 .. (l.Length - i - 1) do yield 0 ])
|> List.reduce (List.map2 (+))
The idiomatic solution would be to use arrays and loops just as you would in C. However, you may be interested in the following alternative solution that uses pattern matching instead:
let dot xs ys =
Seq.map2 (*) xs ys
|> Seq.sum
let convolve xs ys =
let rec loop vs xs ys zs =
match xs, ys with
| x::xs, ys -> loop (dot ys (x::zs) :: vs) xs ys (x::zs)
| [], _::(_::_ as ys) -> loop (dot ys zs :: vs) [] ys zs
| _ -> List.rev vs
loop [] xs ys []
convolve [2; 3; 1; 4] [4; 1; 2; 3]
Regarding the zeroes, how about e.g.
[for q in 0..l.Length-1 -> if q=i then l else 0]
(I haven't tested to verify that is exactly right, but hopefully the idea is clear.) In general, any use of # is a code smell.
Regarding overall performance, for small lists this is probably fine; for larger ones, you might consider using Seq rather than List for some of the intermediate computations, to avoid allocating as many temporary lists along the way.
It looks like maybe the final zip-then-map could be replaced by just a call to map2, something like
... fun r c -> (r,c) ||> List.map2 (+)
or possibly even just
... List.map2 (+)
but I'm away from a compiler so haven't double-checked it.
(fun ye -> x |> List.map ((*) ye))
Really ?
I'll admit |> is pretty, but you could just wrote :
(fun ye -> List.map ((*) ye) x)
Another thing that you could do is fuse the first two maps. l |> List.map f |> List.mapi g = l |> List.mapi (fun i x -> g i (f x)), so incorporating Tomas and Brian's suggestions, you can get something like:
let convolve y x =
let N = List.length x
y
|> List.mapi (fun i ye ->
[for _ in 1..i -> 0
yield! List.map ((*) ye) x
for _ in 1..(N-i-1) -> 0])
|> List.reduce (List.map2 (+))

How to find max's index in a Seq, List or Array in F#

Seq.max finds the max number. I'd like to have something like Seq.findIndex
Seq.maxIndex returns the index of the maximum element.
I believe you are looking for something like:
let maxIndex seq =
fst (Seq.maxBy snd (Seq.mapi (fun i x -> i, x) seq))
Note that giving this function an empty sequence will result in an ArgumentException.
(Alternatively, written in pipelining style:
let maxIndex seq =
seq
|> Seq.mapi (fun i x -> i, x)
|> Seq.maxBy snd
|> fst
)
Why not simply use
let l=[1;2;5;3];;
Seq.findIndex (fun x -> x= Seq.max l) l ;;
?
Or maybe as Johan Kullbom suggest in a comment:
"let m = Seq.max l in Seq.findIndex (fun x -> x = m) l"
if you what a little better O(n)
However, the need to get the index looks to me like a imperative "code smell"
.
In FP it's usually better to use existing functions before you roll your own.
I now this in the eyes of a C programmer seems like a for(i (for(j construct but I bet that you probably really don't need to know the index if you start think in FP.
More or less a duplicate of Finding index of element in a list in Haskell?
PS.
I can't resist.
In Haskell (ghc) the way should probably be something like
let cmpSnd (_, y1) (_, y2) = compare y1 y2
let maxIndex l= fst $ maximumBy cmpSnd $ zip [0..] l
However, since zip in F# doesn't seem to allow zip with unequal lengths of the list(?) the use of mapi is probably the way to go (my haskell version in F#)
let cmpSnd xs= snd xs ;;
let zipIndex a= Seq.mapi (fun i x -> i,x) a;;
let maxIndex seq=fst (Seq.maxBy cmpSnd (zipIndex seq));;
and the reason is only so that I can make a list
let l= [[0;199;1];[4;4];[0;0;399]]
test with makeIndex l;;
and decide that what I really want is a
let cmpSnd' (a,(xs: int list)) = Seq.sum xs;;
let maxIndex' seq=fst (Seq.maxBy cmpSnd' (zipIndex seq));;
Now time to decomposite and make makeIndex take a function
let maxIndexF seq maxF=fst (Seq.maxBy maxF (zipIndex seq));;
val l : int list list = [[1; 2; 199]; [3; 3]; [4; 1]; [0; 299]]
> maxIndexF l cmpSnd'
;;
val it : int = 3
> maxIndexF l cmpSnd
;;
val it : int = 2
Finish it up
let maxIndexF' maxF=fst << Seq.maxBy maxF << zipIndex ;;
maxIndexF' cmpSnd' l;;
maxIndexF' cmpSnd l;;

Resources