tags:

views:

379

answers:

5

I am currently learning F# and have tried (an extremely) simple example of FizzBuzz.

This is my initial attempt:

for x in 1..100 do 
    if x % 3 = 0 && x % 5 = 0 then printfn "FizzBuzz"  
    elif x % 3 = 0 then printfn "Fizz"
    elif x % 5 = 0 then printfn "Buzz"
    else printfn "%d" x

What solutions could be more elegant/simple/better (explaining why) using F# to solve this problem?

Note: The FizzBuzz problem is going through the numbers 1 to 100 and every multiple of 3 prints Fizz, every multiple of 5 prints Buzz, every multiple of both 3 AND 5 prints FizzBuzz. Otherwise, simple the number is displayed.

Thanks :)

+27  A: 

I think you already have the "best" solution.

If you want to show off more functional/F#-isms, you could do e.g.

[1..100] 
|> Seq.map (function
    | x when x%5=0 && x%3=0 -> "FizzBuzz"
    | x when x%3=0 -> "Fizz"
    | x when x%5=0 -> "Buzz"
    | x -> string x)
|> Seq.iter (printfn "%s")

and use lists, sequences, map, iter, patterns, and partial application.

[1..100]    // I am the list of numbers 1-100.  
            // F# has immutable singly-linked lists.
            // List literals use square brackets.

|>          // I am the pipeline operator.  
            // "x |> f" is just another way to write "f x".
            // It is a common idiom to "pipe" data through
            // a bunch of transformative functions.

   Seq.map  // "Seq" means "sequence", in F# such sequences
            // are just another name for IEnumerable<T>.
            // "map" is a function in the "Seq" module that
            // applies a function to every element of a 
            // sequence, returning a new sequence of results.

           (function    // The function keyword is one way to
                        // write a lambda, it means the same
                        // thing as "fun z -> match z with".
                        // "fun" starts a lambda.
                        // "match expr with" starts a pattern
                        // match, that then has |cases.

    | x when x%5=0 && x%3=0 
            // I'm a pattern.  The pattern is "x", which is 
            // just an identifier pattern that matches any
            // value and binds the name (x) to that value.
            // The "when" clause is a guard - the pattern
            // will only match if the guard predicate is true.

                            -> "FizzBuzz"
                // After each pattern is "-> expr" which is 
                // the thing evaluated if the pattern matches.
                // If this pattern matches, we return that 
                // string literal "FizzBuzz".

    | x when x%3=0 -> "Fizz"
            // Patterns are evaluated in order, just like
            // if...elif...elif...else, which is why we did 
            // the 'divisble-by-both' check first.

    | x when x%5=0 -> "Buzz"
    | x -> string x)
            // "string" is a function that converts its argument
            // to a string.  F# is statically-typed, so all the 
            // patterns have to evaluate to the same type, so the
            // return value of the map call can be e.g. an
            // IEnumerable<string> (aka seq<string>).

|>          // Another pipeline; pipe the prior sequence into...

   Seq.iter // iter applies a function to every element of a 
            // sequence, but the function should return "unit"
            // (like "void"), and iter itself returns unit.
            // Whereas sequences are lazy, "iter" will "force"
            // the sequence since it needs to apply the function
            // to each element only for its effects.

            (printfn "%s")
            // F# has type-safe printing; printfn "%s" expr
            // requires expr to have type string.  Usual kind of
            // %d for integers, etc.  Here we have partially 
            // applied printfn, it's a function still expecting 
            // the string, so this is a one-argument function 
            // that is appropriate to hand to iter.  Hurrah!
Brian
Nice educational comments in your answer, Brian!
Luc C
+1, for the Hurrah.
gradbot
+9  A: 

Yet one solution in F# style (i.e. with Active Patterns usage):

let (|P3|_|) i = if i % 3 = 0 then Some i else None
let (|P5|_|) i = if i % 5 = 0 then Some i else None

let f = function
  | P3 _ & P5 _ -> printfn "FizzBuzz"
  | P3 _        -> printfn "Fizz"
  | P5 _        -> printfn "Buzz"
  | x           -> printfn "%d" x

Seq.iter f {1..100}
//or
for i in 1..100 do f i
ssp
I really like this, but I'd use a single parametrized `(|DivisibleBy|_|)` active pattern and have it return `Some ()` so that you can skip all of the underscores in the matches.
kvb
Thanks @ssp. If you have a chance, would you mind explaining what's going on with each line? I am not totally familiar with |P3|_| and the function | P3 | P3 _ ... Thanks :)
Russell
This is really elegant.
Andres Jaan Tack
@Russel, Tomas has explained how they works. Here is short addition: we can define AP with any number of arguments (f.e. (|A|B|_) a b c d e), and when we use it in pattern match branch, we can parametrize our AP by that arguments, all but last one. I.e. it seems like we use normal function as pattern (f.e. |A a1 b2 c3 d4 e5 -> ...). F# calls our patterns with last argument binded to value which used when defined match variable. (f.e. match 5 with A a b c d e -> ... will be transformed to A a1 b2 c3 d4 5 -> ...) and in case of success F# binds last argument to options value returned by AP.
ssp
+8  A: 

My example is just a minor improvement over the code posted by 'ssp'. It uses parameterized active patterns (which take the divisor as an argument). Here is a more in-depth explanation:

The following defines an active pattern that we can later use in the match expression to test if a value i is divisible by a value divisor. When we write:

match 9 with
| DivisibleBy 3 -> ...

...it means that the value '9' will be passed to the following function as i and the value 3 will be passed as divisor. The name (|DivisibleBy|_|) is a special syntax, whith means that we're declaring an active pattern (and the name can appear in the match on the left side of ->. The |_| bit means that the pattern can fail (our example fails when value is not divisible by divisor)

let (|DivisibleBy|_|) divisor i = 

  // If the value is divisible, then we return 'Some()' which
  // represents that the active pattern succeeds - the '()' notation
  // means that we don't return any value from the pattern (if we
  // returned for example 'Some(i/divisor)' the use would be:
  //     match 6 with 
  //     | DivisibleBy 3 res -> .. (res would be asigned value 2)
  // None means that pattern failed and that the next clause should 
  // be tried (by the match expression)
  if i % divisor = 0 then Some () else None 

Now we can iterate over all the numbers and match them against patterns (our active pattern) using match (or using Seq.iter or some other technique as shown in other answers):

for i in 1..100 do
  match i with
  // & allows us to run more than one pattern on the argument 'i'
  // so this calls 'DivisibleBy 3 i' and 'DivisibleBy 5 i' and it
  // succeeds (and runs the body) only if both of them return 'Some()'
  | DivisibleBy 3 & DivisibleBy 5 -> printfn "FizzBuzz"
  | DivisibleBy 3 -> printfn "Fizz" 
  | DivisibleBy 5 -> printfn "Buzz" 
  | _ -> printfn "%d" i

For more information on F# active patterns, here is an MSDN documentation link. I think that if you remove all the comments, the code will be slightly more readable than the original version. It shows some quite useful tricks :-), but in your case, the task is relatively easy...

Tomas Petricek
+5  A: 

To add one more possible answer - here is another approach without pattern matching. It uses the fact that Fizz + Buzz = FizzBuzz, so you don't actually need to test for all three cases, you only need to see if it is divisible by 3 (then print "Fizz") and also see if it is divisible by 5 (then print "Buzz") and finally, print a new line:

for i in 1..100 do
  for divisor, str in [ (3, "Fizz"); (5; "Buzz") ] do
    if i % divisor = 0 then printf str
  printfn ""

The nested for loop assignes 3 and "Fizz" to divisor and str in the first iteration and then the second pair of values in the second iteration. The beneift is, you could easily add printing of "Jezz" when the value is divisible by 7 :-) ...in case that extensibility of the solution is a concern!

Tomas Petricek
@Tomas - that is another great solution :)
Russell
I don't think this quite works, since it doesn't print anything for the numbers which are not divisible by either 3 or 5, when it should print the number itself in that case.
kvb
@kvb: good point... I guess I could use something like `let l = [ for ... do if ... then yield printf str ]` for the nested `for` loop and then test `l <> []` (meaning that no divisor has been found and we need to print the original number). Or use `fold` with a Boolean state specifying whether something was printed.
Tomas Petricek
+1  A: 

Here is my version:

//initialize array a with values from 1 to 100
let a = Array.init 100 (fun x -> x + 1)

//iterate over array and match *indexes* x
Array.iter (fun x ->
    match x with
        | _ when x % 15 = 0 -> printfn "FizzBuzz"
        | _ when x % 5 = 0 -> printfn "Buzz"
        | _ when x % 3 = 0 -> printfn "Fizz"
        | _ -> printfn "%d" x
) a

This is my first program in F#.

It's not perfect, but I think someone who starts learning F# (like me :)) can figure out what happens here quite fast.

However I am wondering what is the difference between matching to any _ or to x itself in pattern matching above?

Grzegorz Gierlik
Thanks @Grzegorz , that is a good solution too. :) Sorry, I am not sure about the difference between _ or x in the criteria. I know _ will match any value, although so would x (as x is always equal to x I think).
Russell