2012-01-28 19 views
7

Todavía estoy aprendiendo Haskell, y me preguntaba si hay una manera menos detallado para expresar la declaración a continuación por medio de 1 línea de código:FizzBuzz limpieza

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

Produce: [(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

Parece que estoy luchando contra la sintaxis más de lo debido. He visto otras preguntas para esto en Haskell, pero estoy buscando la forma más óptima de expresar esto en una sola declaración (tratando de entender cómo trabajar mejor la sintaxis).

+0

http://www.haskell.org/haskellwiki/index.php?title = & search = fizzbuzz & fulltext = Buscar –

+0

@Sergio, no seas tonto. Solo necesita 2 doctores: P –

Respuesta

7

Si insiste en una sola línea:

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

esto parece muy parecido a lo que estoy pensando. ¿Hay alguna manera de reducir esto para que no se necesite concat? Al leerlo lógicamente, el concat es una forma de ruido de comportamiento para mí. Se lee: hacer una matriz que pasos 1 a 100 con cada elemento que es concat con dos matrices que contienen un solo elemento de cadena empujado el uno al otro (..etc). –

+2

Por cierto, las listas en Haskell son listas de enlace único, no matrices; Las matrices (como las que se encuentran en los paquetes [array] (http://hackage.haskell.org/package/array) y [vector] (http://hackage.haskell.org/package/vector) se usan con relativa poca frecuencia en comparación con otros idiomas. – ehird

+0

marcando esto como la respuesta, ya que lee lo mejor como una declaración de 1 línea sin declaraciones complejas como 'dónde'. También me gusta que la expresión esté construida completamente dentro de una definición de lista dándole un contexto más semántico. –

4

¿Cómo se trata ...

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  = "" 
1

A lo largo de las mismas líneas que larsmans' respuesta:

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

que es esencialmente lo que acabo de hacer: '[(x," Fizz "\' ifDivisibleBy \ '3 ++" Buzz "\' ifDivisibleBy \ '5) | x <- [1..100], let ifDivisibleBy s n = if x \ 'mod \' n == 0 then s else ""] ' – rampion

2

Couldn' Me resisto a ir en la otra dirección y hacerlo más complicado. Mira, hay mod ...

merge [email protected]([email protected](ia,sa):as') [email protected]([email protected](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")] 
+1

mi cabeza explotó, gracias –

1

Creo que la razón por qué se siente como que está luchando la sintaxis es porque usted está mezclando demasiados tipos.

En lugar de tratar de imprimir:

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

Sólo piensen de cadenas de impresión:

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

Mi intento:

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

Para convertir un Int a Cadena utiliza el:

show x 
10

no necesitamos apestoso mod ...

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

o ligeramente más corto

import Data.Function(on) 

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

O el bruto manera vigor:

zip [1..100] $ cycle ["","","fizz","","buzz","fizz","","","fizz","buzz","","fizz","","","fizzbuzz"] 
0

escritor mónada puede parecer agradable (si no te gusta concat):

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

Sin embargo, no es particularmente breve.

1

Sólo para el estudio de

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

produce

["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"] 
Cuestiones relacionadas