{"id":261,"date":"2010-07-05T13:27:00","date_gmt":"2010-07-05T18:27:00","guid":{"rendered":"http:\/\/factormystic.net\/blog\/?p=261"},"modified":"2010-07-05T13:27:00","modified_gmt":"2010-07-05T18:27:00","slug":"project-euler-in-fsharp-problem-2","status":"publish","type":"post","link":"https:\/\/factormystic.net\/blog\/project-euler-in-fsharp-problem-2","title":{"rendered":"Project Euler in F#: Problem 2"},"content":{"rendered":"<h2>Problem 2<\/h2>\n<blockquote><p>Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:<br \/>\n1, 2, 3, 5, 8, 13, 21, 34, 55, 89, &#8230;<br \/>\nFind the sum of all the even-valued terms in the sequence which do not exceed four million.<\/p><\/blockquote>\n<h2>The Thinking<\/h2>\n<p>The problem is similar to <a href=\"https:\/\/factormystic.net\/blog\/project-euler-in-fsharp-problem-1\">Problem 1<\/a>, but this time instead of a natural number sequence, we&#8217;re to use a fibbonacci sequence, evens only, less than 4 million.\u00a0Then, we&#8217;ll need to sum them up; that we did in Problem 1 with Seq.sum.\u00a0How can we generate the sequence? I&#8217;ll be taking a simple two-step approach. First, figure out a function to generate a fibbonacci sequence (up through 4,000,000), then take all the evens. We can Seq.sum that resulting sequence to find our answer.<\/p>\n<h2>Generating a Fibonacci Sequence<\/h2>\n<p>Generating a fibbonacci sequence in F# is a textboook case, and so much so that it&#8217;s actually an example snippet for the built-in F# function we&#8217;re going to use to generate it: Seq.unfold.\u00a0Seq.unfold is a \u00a0function that returns a sequence, based on a function we provide.\u00a0It takes two parameters: a sequence element generator function, and the inital value to start with.<br \/>\n[sourcecode]Seq.unfold generator state[\/sourcecode]<br \/>\nThe generator function must be defined with a single input parameter (the &#8220;state value&#8221;), and returning an &#8220;option tuple of the next element in the sequence and the next state value&#8221; (<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ee340363.aspx\">from documentation<\/a>).<\/p>\n<p>A fibbonacci algorithm requires two inputs (the previous two digits), but we can only pass one parameter. Luckily in F# we have <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd233200.aspx\">Tuples<\/a>. A tuple lets us package up several values into a single group, and is written with as a comma separated list inside parenthesis:<br \/>\n[sourcecode]let sometuple = (&#8220;this&#8221;, &#8220;is&#8221;, &#8220;a&#8221;, &#8220;single&#8221;, &#8220;tuple&#8221;)[\/sourcecode]<br \/>\nThe return value is also something new, using the built-in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd233245.aspx\">Option module<\/a>. We&#8217;ll be returning an Option, either Some or None. None is a signal to unfold that this is the end of sequence, and for all the rest of the return results, we need to return Some-thing (the next element of the sequence as well as the next state value in tuple form) as we learned above, from the documentation for unfold.<\/p>\n<p>This might seem like a lot to process all at once, but it ends up looking pretty simple when it&#8217;s all put together. The generator function for fibbonacci numbers less than 4m looks like this:<br \/>\n[sourcecode]let fibgen (x,y) = \/\/define a function &#8216;fibgen&#8217; and pass in a single parameter, a tuple that represents the most recent two digits of the fibbonacci sequence so far<br \/>\nif(x < 4000000) then \/\/ define a cut-off threshold to keep the sequence from going on forever\nSome(x+y, (y, x+y)) \/\/ return an Option tuple; the next elemnet of the sequence: x+y (the two most recent elements added together), and the next state value- a single tuple that will be used next time the funciton is run\nelse None \/\/ we're up to 4m, so tell unfold we're done with the sequence\n[\/sourcecode]\n\nAnd now, we can plug that into Seq.unfold:\n[sourcecode]let fibseq = Seq.unfold fibgen (1,1) \/\/ (1,1) is a single tuple parameter with the initial values for the fibgen function[\/sourcecode]\n\nIf we run this in the Interactive F# window in Visual Studio, we can confirm this produces the full fibbonacci sequence:\n[sourcecode]val it : seq = seq [2; 3; 5; 8; ...][\/sourcecode]\n\n\n\n<h2>Getting Just The Evens<\/h2>\n<p>If you recall our solution to <a href=\"https:\/\/factormystic.net\/blog\/project-euler-in-fsharp-problem-1\">Problem 1<\/a>, it should be easy to figure out how to make a new sequence with only the even values by using seq, modulo, and yield that we&#8217;ve already learned.<br \/>\n[sourcecode]let fibevens = seq{for i in fibseq do if i % 2 = 0 then yield i}[\/sourcecode]<\/p>\n<h2>My Solution<\/h2>\n<p>Putting it all together, with Seq.sum to add up the sequence:<br \/>\n[sourcecode]let fibgen (x,y) = if(x < 4000000) then Some(x+y, (y, x+y)) else None\nlet fibseq = Seq.unfold fibgen (1,1)\nlet fibevens = seq{for i in fibseq do if i % 2 = 0 then yield i}\nlet result = Seq.sum fibevens\nprintfn \"%A\" result\n[\/sourcecode]\n\nProject Euler Problem 2: <strong><a href=\"http:\/\/projecteuler.net\/index.php?section=profile&#038;profile=factormystic\">Answered<\/a><\/strong><\/p>\n<h2>Further Reading<\/h2>\n<ul>\n<li><a href=\"http:\/\/www.ctocorner.com\/fsharp\/book\/ch8.aspx\">Chapter 8- Functions &amp; Functional Concepts<\/a>, The F# Survival Guide<\/li>\n<li><a href=\"http:\/\/geekswithblogs.net\/MarkPearl\/archive\/2010\/06\/23\/f-seq.unfold.aspx\">Mark Pearl&#8217;s post on Seq.Unfold<\/a>, using tuple parameters and pipelines<\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ee340363.aspx\">Seq.unfold<\/a><\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd233245.aspx\">Options module<\/a><\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd233200.aspx\">Tuples<\/a><\/li>\n<\/ul>\n<h2>A Post Script<\/h2>\n<p>Each part of the above solution is named for clarity. We could easily compose these functions for a more compact solution:<br \/>\n[sourcecode]printfn &#8220;%A&#8221; (Seq.sum(seq{for i in ((1,1) |> Seq.unfold(fun (x,y) -> if(x < 4000000) then Some(x+y, (y, x+y)) else None)) do if i % 2 = 0 then yield i}))[\/sourcecode]\nThe only thing that gets weird in this compact version is the anonymous replacement for fibgen, which uses lambda syntax fun &amp; -&gt;, and the pipeline operator, |&gt; to pass in the intial state. There are some goofy rules for when you can and cannot use piplineing; check out the <a href=\"http:\/\/www.ctocorner.com\/fsharp\/book\/ch8.aspx\">Pipeline section<\/a> of Chapter 8 of The F# Survival Guide for a good primer.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Problem 2 Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, &#8230; Find the sum of all the even-valued terms in the sequence which do not exceed [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,25],"tags":[],"class_list":["post-261","post","type-post","status-publish","format-standard","hentry","category-f-sharp","category-project-euler"],"_links":{"self":[{"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/posts\/261","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/comments?post=261"}],"version-history":[{"count":11,"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/posts\/261\/revisions"}],"predecessor-version":[{"id":274,"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/posts\/261\/revisions\/274"}],"wp:attachment":[{"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/media?parent=261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/categories?post=261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/factormystic.net\/blog\/wp-json\/wp\/v2\/tags?post=261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}