patternMinor
FizzBuzzWoof in F#
Viewed 0 times
fizzbuzzwoofstackoverflowprogramming
Problem
I'm learning F#, and have challenged myself to write a good functional implementation of FizzBuzzWoof. (The difference from "standard" FizzBuzz is that any number that either is divisible by or contains the appropriate number must be replaced by the appropriate string of text: 3 = Fizz, 5 = Buzz, 7 = Woof. Also, the strings must be printed in that order.)
I wrote a version using partial matching that I'm quite happy with, except for the one darn
My attempt so far:
I did come up with the idea of replacing the final
And this would work, but it runs the match functions an extra time. In this case this is absolutely fine since they're all quite fast, but what if I have a match function that takes a long time? Is there a way to run each match function just once, yet still avoid the use o
I wrote a version using partial matching that I'm quite happy with, except for the one darn
mutable Boolean in there that makes it feel less than functional to me. Is there a way I can get rid of that mutable Boolean, and still have clean code?My attempt so far:
module FizzBuzzWoof =
let isDivisibleBy a b = (a % b) = 0
let contains a b = a.ToString().Contains(b.ToString())
let fizzBuzzWoofMatcher n = fun i ->
if isDivisibleBy i n then Some ()
elif contains i n then Some ()
else None
let (|Fizz|_|) i = fizzBuzzWoofMatcher 3
let (|Buzz|_|) i = fizzBuzzWoofMatcher 5
let (|Woof|_|) i = fizzBuzzWoofMatcher 7
open FizzBuzzWoof
let runme () =
for i = 1 to 100 do
let mutable matched = false // Want to eliminate this
match i with
| Fizz () -> printf "Fizz"; matched ()
match i with
| Buzz () -> printf "Buzz"; matched ()
match i with
| Woof () -> printf "Woof"; matched ()
if matched
then
printfn ""
else
printfn "%d" i
runme()I did come up with the idea of replacing the final
if matched with another match expression as follows:match i with
| Fizz () -> printfn ""
| Buzz () -> printfn ""
| Woof () -> printfn ""
| _ -> printfn "%d" iAnd this would work, but it runs the match functions an extra time. In this case this is absolutely fine since they're all quite fast, but what if I have a match function that takes a long time? Is there a way to run each match function just once, yet still avoid the use o
Solution
You can avoid using mutable by collecting all matching results and folding them into single bool value.
let matchSmth matchFun msg i =
match matchFun i with
| Some i ->
printf msg
true
| None -> false
let matchFizz = matchSmth (fizzBuzzWoofMatcher 3) "Fizz"
let matchBuzz = matchSmth (fizzBuzzWoofMatcher 5) "Buzz"
let matchWoof = matchSmth (fizzBuzzWoofMatcher 7) "Woof"
let runme() =
for i = 1 to 100 do
let matched = [matchFizz i; matchBuzz i; matchWoof i] |> List.fold (||) false
if matched then printfn ""
else printfn "%d" iCode Snippets
let matchSmth matchFun msg i =
match matchFun i with
| Some i ->
printf msg
true
| None -> false
let matchFizz = matchSmth (fizzBuzzWoofMatcher 3) "Fizz"
let matchBuzz = matchSmth (fizzBuzzWoofMatcher 5) "Buzz"
let matchWoof = matchSmth (fizzBuzzWoofMatcher 7) "Woof"
let runme() =
for i = 1 to 100 do
let matched = [matchFizz i; matchBuzz i; matchWoof i] |> List.fold (||) false
if matched then printfn ""
else printfn "%d" iContext
StackExchange Code Review Q#120375, answer score: 5
Revisions (0)
No revisions yet.