Project Euler #8 in F# - f#

I disgress, I am stuck and I really can't wrap my head around what's wrong. The problem reads.
Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
Now I store the digit as a string, I only fetch the numbers, I loop through and grab each 13-digit "substring" as an array, multiply them together and compare them. Now I have verified that I am only getting a 1000-digit char array, I have verified that I get exactly 75 char arrays of equal size. Yet I am not getting the right answer.
Here is the code
let problem8() =
let str = #"731671765313306..."
|> Seq.filter (Char.IsDigit)
|> Seq.toArray
(* We only need to go to 987 because 1000 isn't divisble by 13 and if we were to take the last 11 digits from 987
we would end up with 0 anyhow. *)
seq { for i in 0.. 13 ..987 -> str.[i..i + 12] }
|> Seq.map (Seq.fold (fun acc chr -> acc * int64 (Char.GetNumericValue(chr))) 1L)
|> Seq.max
problem8()
|> printfn "%d"

If you are using 0 .. 13 .. 987 in the sequence expression, then you are partitioning the array like this (for simplicity, using 3-sized blocks in 10 digits):
[012][345][678]9
I suppose that the question wants you to look for all possible sub-strings, i.e.
[012][345][678]9
0[123][456][789]
01[234][567]89
So, you probably need to try all indices using 0 .. 987.
By the way, I'd suspect that converting char to int64 will be faster using int64 c - 48L.

Related

F#: How to process a list of tuples?

I'm working on a homework assignment. And I'm trying to learn F# so I don't want any shortcuts besides using basic things like List.Map or lambdas or something.
I'm trying to process a list of tuples, but I'm having trouble accessing the tuples in the list.
I want to take the list of tuples, add up the numbers in each tuple, and return that number, printing it out each time.
let listTup = [(2,3,4); (4,5,6); (6,7,8)]
let getSum (a,b,c) =
a+b+c
let rec printSum tpList =
let total = 0
match tpList with
| [] -> total //return 0 if empty list
| hd::tl ->
print (getSum hd)
The first thing you want to do is map your tuples through the getSum function. This can be done very simply by piping the list of tuples into List.map getSum. Then you want to print each element in the list, so you pipe the result of List.map getSum into List.iter with the function printfn "%d". This works because of the functions having curried parameters. printfn "%d" applies the "%d" parameter to printfn and returns a function taking an integer, which it then prints. The whole thing would look like this:
let listTup = [(2,3,4); (4,5,6); (6,7,8)]
let getSum (a,b,c) =
a + b + c
let printSum tpList =
tpList |> List.map getSum |> List.iter (printfn "%d")
This prints:
9
15
21
We can even simplify the function further if we take advantage of function composition (the >> operator). Notice that printSum takes tpList as its parameter, and then just uses it as input to two functions that are pipelined together. Since pipelining just takes the output of one function and passes it as the last parameter of another function, all we really need to do is compose the function List.map getSum, which takes a list of int 3-tuples and returns a list of ints with List.iter (printfn "%d"), which takes a list of ints and returns unit. That would look like this:
let printSum = List.map getSum >> List.iter (printfn "%d")
This will print the same results, but is a simpler way of expressing the function.
F# has imperative loops as well. In this case I think an imperative loop matches the problem most idiomatically.
let listTup = [(2,3,4); (4,5,6); (6,7,8)]
for a,b,c in listTup do
let sum = a + b + c
printfn "%d" sum

Project Euler Q8 Largest product in a series - Why is my code wrong?

The problem is (source)...
The four adjacent digits in the 1000-digit number that have the greatest
product are 9 × 9 × 8 × 9 = 5832.
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
Find the thirteen adjacent digits in the 1000-digit number that have
the greatest product. What is the value of this product?
I have the following F#...
let largestProduct n (s : string) =
[ for i in [0..(s.Length - n)] do yield s.[i..(i + n - 1)]]
|> Seq.map (fun s -> s, s |> Seq.fold (fun p c -> p * (int (string c))) 1)
|> Seq.maxBy snd
You pass the number of digits, and the 1000 digit number as a string. The first line produces a sequence of n-character strings, which are piped into the second line where the product of the digits is calculated. This is wrapped in a tuple with the n-character string, so I can see which set of n characters produced the highest product. The last line gets the maximum product.
If I run this as follows...
largestProduct 4 nStr
...where nStr is the 1000-digit number as a string, it produces the following...
("9989", 5832)
...which is correct. However, if I change the number to 13, to solve the actual problem, it gives me...
("9781797784617", 2091059712)
...which apparently is wrong.
Anyone any idea why my code doesn't work? I've tried it for various small values of n, and it looks like it's working there. I've also tried it on shorter strings, and it seems to work fine.
This exercise causes an Int32 to overflow. The arbitrary-length type bigint solves this for a generally sufficient range of inputs. For example:
let digitsToProduct inp =
inp |> Seq.map (string >> bigint.Parse)
|> Seq.fold (*) 1I
let largestProduct n : (seq<char> -> bigint) =
Seq.windowed n >> Seq.map digitsToProduct >> Seq.max
Edit: note that largestProduct takes a second argument: a string (or any char sequence) of the 1000 digits.
What can be learned from this?
This is a fundamental kind of problem that is worth thinking about. As a rule of thumb, a function should be correct or fail, at least for reasonable inputs. I would argue that, in any context where a developer might make such mistakes, the answer to just use a 64-bit integer is borderline incorrect. After all, it will still fail silently on inputs that are too large.
If you want to use a 32-bit or 64-bit integer for such a function, validate your inputs!
For example, a rough validation could be:
// 32b version
if n > 9 then invalidArg "n" "number of digits too large for Int32."
// 64b version
if n > 19L then invalidArg "n" "number of digits too large for Int64."
This would cause your program to fail properly instead of silently producing nonsensical results.
As you've figured, using int64 solves the problem.
The way I read the assignment, you don't have to return the digits that cause the largest product; only the product itself is required. With that requirement, the implementation is easy:
let largestProduct n : (string -> int64) =
Seq.map (string >> System.Int64.Parse)
>> Seq.windowed n
>> Seq.map (Array.fold (*) 1L)
>> Seq.max
If you want the sequence of digits as well, that's also easy:
let largestProductAndTheDigitsThatProduceIt n : (string -> string * int64) =
Seq.map (string >> System.Int64.Parse)
>> Seq.windowed n
>> Seq.map (fun is -> System.String.Concat is , Array.fold (*) 1L is)
>> Seq.maxBy snd
FSI:
> largestProductAndTheDigitsThatProduceIt 4 nStr;;
val it : string * int64 = ("9989", 5832L)
> largestProductAndTheDigitsThatProduceIt 13 nStr;;
val it : string * int64 = ("5576689664895", 23514624000L)
Whilst searching for some inspiration, I came across a question where someone had the same problem.
The answer was nothing more complex than the fact that the multiplication overflowed the capacity of a 32-bit integer. When I altered the code to use int64, it gave the right answer...
let largestProductInt64 (n : int64) (s : string) =
[ for i in [0L..((int64 s.Length) - n)] do yield s.[(int i)..int(i + n - 1L)]]
|> Seq.map (fun s -> s, s |> Seq.fold (fun p c -> p * (int64 (int (string c)))) 1L)
|> Seq.maxBy snd
Shame, as the code isn't as neat and clean, but it works.
Thanks to #kvb who made the same point in a comment before I had chance to post my own findings.

Adding a list of numbers based on an operator

I am really new to F# and am struggling to adapt to the whole functional programming mindset. Basically I am trying to figure out how to iterate through a list of numbers and add them up while the sum is less than a certain number (200 for instance).
At the moment I have something along the lines of the following:
let nums = [20 .. 50]
let mutable total = 0
let addUp (num, (total : byref<int>)) =
if (num + total < 200) then
total <- total + num
for num in nums do
addUp (num, &total)
This does get the job done, but I feel like there must be a more appropriate way to do this while still remaining within the style of functional programming, and without out having to rely on a mutable. I still feel like I'm approaching things from an imperative mindset.
I was thinking I could somehow use List.fold to do this but after some experimentation I was unable to figure out how to utilize it in conjunction with the whole while < 200 thing. Any help would be hugely appreciated and I apologize in advance if this is a commonly asked and answered question (I couldn't find anything through my own search).
For educational purposes, the answer above is fine as it lets you see what exactly happens within the fold or reduce.
For a real project, it is better to use existing library functions. You can even separate summation and bound checking. Consider this:
let addUp threshold xs =
xs
|> Seq.scan (+) 0 // line 1
|> Seq.takeWhile (fun x -> x < threshold) // line 2
|> Seq.last // line 3
// Usage:
let nums = Seq.initInfinite ( (+) 20) // line 4
nums
|> addUp 200
|> printfn "%d" // prints "188"
A bit of explanation:
line 1 is a contraction of Seq.scan (fun state x -> state + x) 0 so it actually returns a sequence of intermediate sums (20, 41, 63, ...);
in line 2, we take only the elements that match or filtering predicate;
in line 3, we simply take the last element (that matched the filtering above);
in line 4, again, it's a contraction of Seq.initInfinite (fun x -> 20+x). I took my liberty to make your data an infinite sequence (20, 21, 22, ...), but it still works.
Note, the code looks like three calls, but the sequence is evaluated only once.
Note, in line 2, don't try contraction like above. The reason is that (<) threshold evaluates to fun x -> threshold < x which is wrong. If you. however, use (>) threshold, it reads counter-intuitive and confusing.
Note, there's no error checking in the function. Calling it with an empty source sequence will crash at Seq.last.
First, let's try to avoid mutable variable and one way to do it is to create a recursive function to iterate through the list with the latest total.
let rec addUp total nums =
match nums with
| [] -> total
| num::tl ->
let newTotal = num + total
if newTotal < 200 then
addUp newTotal tl
else
total
addUp 0 nums
We create a recursive function addUp which accepts total and the list of numbers. The function extracts the first number of the list and adds it to the total if the new total is less than 200. Since we might still have more numbers on the list, we call addUp again with the new total and the rest of the numbers. Otherwise, we stop and return the new total.
We can also use List.fold which makes the code cleaner, but the whole list will be iterated. Here is the code:
List.fold (fun total num ->
let newTotal = num + total
if newTotal < 200 then
newTotal
else
total
) 0 nums
Since the output is the same type as the member of the input, we can use List.reduce and get rid of initial state (0).
List.reduce (fun total num ->
let newTotal = num + total
if newTotal < 200 then
newTotal
else
total
) nums
Hope this helps.

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.

Avoiding stack overflow (with F# infinite sequences of sequences)

I have this "learning code" I wrote for the morris seq in f# that suffers from stack overflow that I don't know how to avoid. "morris" returns an infinite sequence of "see and say" sequences (i.e., {{1}, {1,1}, {2,1}, {1,2,1,1}, {1,1,1,2,2,1}, {3,1,2,2,1,1},...}).
let printList l =
Seq.iter (fun n -> printf "%i" n) l
printfn ""
let rec morris s =
let next str = seq {
let cnt = ref 1 // Stack overflow is below when enumerating
for cur in [|0|] |> Seq.append str |> Seq.windowed 2 do
if cur.[0] <> cur.[1] then
yield!( [!cnt ; cur.[0]] )
cnt := 0
incr cnt
}
seq {
yield s
yield! morris (next s) // tail recursion, no stack overflow
}
// "main"
// Print the nth iteration
let _ = [1] |> morris |> Seq.nth 3125 |> printList
You can pick off the nth iteration using Seq.nth but you can only get so far before you hit a stack overflow. The one bit of recursion I have is tail recursion and it in essence builds a linked set of enumerators. That's not where the problem is. It's when "enum" is called on the say the 4000th sequence. Note that's with F# 1.9.6.16, the previous version topped out above 14000). It's because the way the linked sequences are resolved. The sequences are lazy and so the "recursion" is lazy. That is, seq n calls seq n-1 which calls seq n-2 and so forth to get the first item (the very first # is the worst case).
I understand that [|0|] |> Seq.append str |> Seq.windowed 2, is making my problem worse and I could triple the # I could generate if I eliminated that. Practically speaking the code works well enough. The 3125th iteration of morris would be over 10^359 characters in length.
The problem I'm really trying to solve is how to retain the lazy eval and have a no limit based on stack size for the iteration I can pick off. I'm looking for the proper F# idiom to make the limit based on memory size.
Update Oct '10
After learning F# a bit better, a tiny bit of Haskell, thinking & investigating this problem for over year, I finally can answer my own question. But as always with difficult problems, the problem starts with it being the wrong question. The problem isn't sequences of sequences - it's really because of a recursively defined sequence. My functional programming skills are a little better now and so it's easier to see what's going on with the version below, which still gets a stackoverflow
let next str =
Seq.append str [0]
|> Seq.pairwise
|> Seq.scan (fun (n,_) (c,v) ->
if (c = v) then (n+1,Seq.empty)
else (1,Seq.ofList [n;c]) ) (1,Seq.empty)
|> Seq.collect snd
let morris = Seq.unfold(fun sq -> Some(sq,next sq))
That basicially creates a really long chain of Seq processing function calls to generate the sequnces. The Seq module that comes with F# is what can't follow the chain without using the stack. There's an optimization it uses for append and recursively defined sequences, but that optimization only works if the recursion is implementing an append.
So this will work
let rec ints n = seq { yield n; yield! ints (n+1) }
printf "%A" (ints 0 |> Seq.nth 100000);;
And this one will get a stackoverflow.
let rec ints n = seq { yield n; yield! (ints (n+1)|> Seq.map id) }
printf "%A" (ints 0 |> Seq.nth 100000);;
To prove the F# libary was the issue, I wrote my own Seq module that implemented append, pairwise, scan and collect using continutions and now I can begin generating and printing out the 50,000 seq without a problem (it'll never finish since it's over 10^5697 digits long).
Some additional notes:
Continuations were the idiom I was looking for, but in this case, they had to go into the F# library, not my code. I learned about continuations in F# from Tomas Petricek's Real-World Functional Programming book.
The lazy list answer that I accepted held the other idiom; lazy evaluation. In my rewritten library, I also had to leverage the lazy type to avoid stackoverflow.
The lazy list version sorta of works by luck (maybe by design but that's beyond my current ability to determine) - the active-pattern matching it uses while it's constructing and iterating causes the lists to calculate values before the required recursion gets too deep, so it's lazy, but not so lazy it needs continuations to avoid stackoverflow. For example, by the time the 2nd sequence needs a digit from the 1st sequence, it's already been calculated. In other words, the LL version is not strictly JIT lazy for sequence generation, only list management.
You should definitely check out
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/FSharp.PowerPack/Microsoft.FSharp.Collections.LazyList.html
but I will try to post a more comprehensive answer later.
UPDATE
Ok, a solution is below. It represents the Morris sequence as a LazyList of LazyLists of int, since I presume you want it to be lazy in 'both directions'.
The F# LazyList (in the FSharp.PowerPack.dll) has three useful properties:
it is lazy (evaluation of the nth element will not happen until it is first demanded)
it does not recompute (re-evaluation of the nth element on the same object instance will not recompute it - it caches each element after it's first computed)
you can 'forget' prefixes (as you 'tail' into the list, the no-longer-referenced prefix is available for garbage collection)
The first property is common with seq (IEnumerable), but the other two are unique to LazyList and very useful for computational problems such as the one posed in this question.
Without further ado, the code:
// print a lazy list up to some max depth
let rec PrintList n ll =
match n with
| 0 -> printfn ""
| _ -> match ll with
| LazyList.Nil -> printfn ""
| LazyList.Cons(x,xs) ->
printf "%d" x
PrintList (n-1) xs
// NextMorris : LazyList<int> -> LazyList<int>
let rec NextMorris (LazyList.Cons(cur,rest)) =
let count = ref 1
let ll = ref rest
while LazyList.nonempty !ll && (LazyList.hd !ll) = cur do
ll := LazyList.tl !ll
incr count
LazyList.cons !count
(LazyList.consf cur (fun() ->
if LazyList.nonempty !ll then
NextMorris !ll
else
LazyList.empty()))
// Morris : LazyList<int> -> LazyList<LazyList<int>>
let Morris s =
let rec MakeMorris ll =
LazyList.consf ll (fun () ->
let next = NextMorris ll
MakeMorris next
)
MakeMorris s
// "main"
// Print the nth iteration, up to a certain depth
[1] |> LazyList.of_list |> Morris |> Seq.nth 3125 |> PrintList 10
[1] |> LazyList.of_list |> Morris |> Seq.nth 3126 |> PrintList 10
[1] |> LazyList.of_list |> Morris |> Seq.nth 100000 |> PrintList 35
[1] |> LazyList.of_list |> Morris |> Seq.nth 100001 |> PrintList 35
UPDATE2
If you just want to count, that's fine too:
let LLLength ll =
let rec Loop ll acc =
match ll with
| LazyList.Cons(_,rest) -> Loop rest (acc+1N)
| _ -> acc
Loop ll 0N
let Main() =
// don't do line below, it leaks
//let hundredth = [1] |> LazyList.of_list |> Morris |> Seq.nth 100
// if we only want to count length, make sure we throw away the only
// copy as we traverse it to count
[1] |> LazyList.of_list |> Morris |> Seq.nth 100
|> LLLength |> printfn "%A"
Main()
The memory usage stays flat (under 16M on my box)... hasn't finished running yet, but I computed the 55th length fast, even on my slow box, so I think this should work just fine. Note also that I used 'bignum's for the length, since I think this will overflow an 'int'.
I believe there are two main problems here:
Laziness is very inefficient so you can expect a lazy functional implementation to run orders of magnitude slower. For example, the Haskell implementation described here is 2,400× slower than the F# I give below. If you want a workaround, your best bet is probably to amortize the computations by bunching them together into eager batches where the batches are produced on-demand.
The Seq.append function is actually calling into C# code from IEnumerable and, consequently, its tail call doesn't get eliminated and you leak a bit more stack space every time you go through it. This shows up when you come to enumerate over the sequence.
The following is over 80× faster than your implementation at computing the length of the 50th subsequence but perhaps it is not lazy enough for you:
let next (xs: ResizeArray<_>) =
let ys = ResizeArray()
let add n x =
if n > 0 then
ys.Add n
ys.Add x
let mutable n = 0
let mutable x = 0
for i=0 to xs.Count-1 do
let x' = xs.[i]
if x=x' then
n <- n + 1
else
add n x
n <- 1
x <- x'
add n x
ys
let morris =
Seq.unfold (fun xs -> Some(xs, next xs)) (ResizeArray [1])
The core of this function is a fold over a ResizeArray that could be factored out and used functionally without too much performance degradation if you used a struct as the accumulator.
Just save the previous element that you looked for.
let morris2 data = seq {
let cnt = ref 0
let prev = ref (data |> Seq.nth 0)
for cur in data do
if cur <> !prev then
yield! [!cnt; !prev]
cnt := 1
prev := cur
else
cnt := !cnt + 1
yield! [!cnt; !prev]
}
let rec morrisSeq2 cur = seq {
yield cur
yield! morrisSeq2 (morris2 cur)
}

Resources