7

私はまだHaskellを学んでおり、1行のコードを使用して以下のステートメントを表現するためのより冗長な方法があるかどうか疑問に思っていました。

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

生産物: [(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")など

構文と必要以上に戦っているような気がします。Haskellでこれに関する他の質問を見てきましたが、これを1つのステートメントで表現するための最適な方法を探しています(構文をより適切に機能させる方法を理解しようとしています)。

4

8 に答える 8

10

悪臭はいらないmod...

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

または少し短い

import Data.Function(on)

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

または力ずくの方法:

zip [1..100] $ cycle ["","","fizz","","buzz","fizz","","","fizz","buzz","","fizz","","","fizzbuzz"]
于 2012-01-29T13:01:25.447 に答える
7

ワンライナーを主張する場合:

[(x, concat $ ["fizz" | mod x 3 == 0] ++ ["buzz" | mod x 5 == 0]) | x <- [1..100]]
于 2012-01-28T20:10:06.797 に答える
4

どうですか...

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       =  ""
于 2012-01-28T19:23:29.773 に答える
2

反対方向に進んでそれをより複雑にすることに抵抗できませんでした。ほら、いや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")]
于 2012-01-28T21:12:51.820 に答える
1

larsmans の回答と同じ行に沿って:

fizzBuzz = [(x, f 3 "fizz" x ++ f 5 "buzz" x) | x <- [1..100]]
  where f k s n | n `mod` k == 0 = s
                | otherwise      = ""
于 2012-01-28T19:47:38.003 に答える
1

構文と戦っているように感じるのは、あまりにも多くの型を混ぜているからだと思います。

印刷しようとする代わりに:

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

文字列を印刷することを考えてみてください:

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

私の試み:

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"...]

Int を String に変換するには、次を使用します。

show x
于 2012-01-28T23:50:20.050 に答える
1

勉強のためだけに

zipWith (\a b -> b a) (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"]

生産する

["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"]
于 2016-05-24T20:31:36.157 に答える
0

Writer モナドは見栄えがするかもしれません (気に入らない場合concat):

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

特に簡潔ではありませんが。

于 2012-01-29T16:38:13.497 に答える