Cleaning up FizzBuzz

I am still studying Haskell, and I was wondering if there is a less accurate way to express the statement below using 1 line of code:

map (\x -> (x, (if mod x 3 == 0 then "fizz" else "") ++ if mod x 5 == 0 then "buzz" else "")) [1..100] 

Gives: [(1,""),(2,""),(3,"fizz"),(4,""),(5,"buzz"),(6,"fizz"),(7,""),(8,""),(9,"fizz"),(10,"buzz"),(11,""),(12,"fizz"),(13,""),(14,""),(15,"fizzbuzz"),(16,""),(17,""),(18,"fizz"),(19,""),(20,"buzz"),(21,"fizz"),(22,""),(23,""),(24,"fizz"),(25,"buzz"),(26,""),(27,"fizz"),(28,""),(29,""),(30,"fizzbuzz") , etc.

It just seems like I'm struggling with the syntax more than I should. I saw other questions for this in Haskell, but I'm looking for the most optimal way to express this in one statement (trying to figure out how best to work with the syntax).

+7
source share
8 answers

If you insist on one layer:

 [(x, concat $ ["fizz" | mod x 3 == 0] ++ ["buzz" | mod x 5 == 0]) | x <- [1..100]] 
+7
source

We don't need stinkin ' mod ...

 zip [1..100] $ zipWith (++) (cycle ["","","fizz"]) (cycle ["","","","","buzz"]) 

or a little shorter

 import Data.Function(on) zip [1..100] $ (zipWith (++) `on` cycle) ["","","fizz"] ["","","","","buzz"] 

Or brute force method:

 zip [1..100] $ cycle ["","","fizz","","buzz","fizz","","","fizz","buzz","","fizz","","","fizzbuzz"] 
+10
source

What about...

 fizzBuzz = [(x, fizz x ++ buzz x) | x <- [1..100]] where fizz n | n `mod` 3 == 0 = "fizz" | otherwise = "" buzz n | n `mod` 5 == 0 = "buzz" | otherwise = "" 
+4
source

Could not stand in the other direction and make it more difficult. Look, no mod ...

 merge as@ ( a@ (ia,sa):as') bs@ ( b@ (ib,sb):bs') = case compare ia ib of LT -> a : merge as' bs GT -> b : merge as bs' EQ -> (ia, sa++sb) : merge as' bs' merge as bs = as ++ bs zz (n,s) = [(i, s) | i <- [n,2*n..]] fizzBuzz = foldr merge [] $ map zz [(1,""), (3,"fizz"), (5,"buzz")] 
+2
source

On the same lines as larsmans answer:

 fizzBuzz = [(x, f 3 "fizz" x ++ f 5 "buzz" x) | x <- [1..100]] where fksn | n `mod` k == 0 = s | otherwise = "" 
+1
source

I think the reason you feel you are struggling with syntax is because you mix too many types.

Instead of trying to print:

 [(1, ""), (2,""), (3,"Fizz")...] 

Think of printed lines:

 ["1","2","Fizz"...] 

My attempt:

 Prelude> let fizzBuzz x | x `mod` 15 == 0 = "FizzBuzz" | x `mod` 5 == 0 = "Buzz" | x `mod` 3 == 0 = "Fizz" | otherwise = show x Prelude> [fizzBuzz x | x <-[1..100]] ["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"...] 

To convert Int to String, you use:

 show x 
+1
source

For study only

 zipWith (\ab -> ba) (map show [1..100]) $ cycle [id,id,const "fizz",id,const "buzz",const "fizz",id,id,const "fizz",const "buzz",id,const "fizz",id,id,const "fizzbuzz"] 

produces

 ["1","2","fizz","4","buzz","fizz","7","8","fizz","buzz","11","fizz","13","14","fizzbuzz","16","17","fizz","19","buzz","fizz","22","23","fizz","buzz","26","fizz","28","29","fizzbuzz","31","32","fizz","34","buzz","fizz","37","38","fizz","buzz","41","fizz","43","44","fizzbuzz","46","47","fizz","49","buzz","fizz","52","53","fizz","buzz","56","fizz","58","59","fizzbuzz","61","62","fizz","64","buzz","fizz","67","68","fizz","buzz","71","fizz","73","74","fizzbuzz","76","77","fizz","79","buzz","fizz","82","83","fizz","buzz","86","fizz","88","89","fizzbuzz","91","92","fizz","94","buzz","fizz","97","98","fizz","buzz"] 
+1
source

Writing monad may look pretty (if you don't like concat ):

 fizzBuzz = [(x, execWriter $ when (x `mod` 3 == 0) (tell "fizz") >> when (x `mod` 5 == 0) (tell "buzz")) | x <- [1..100]] 

This is not particularly concise.

0
source

All Articles