Skip to content

Instantly share code, notes, and snippets.

@paradoja
Created May 4, 2012 20:53
Show Gist options
  • Save paradoja/2597645 to your computer and use it in GitHub Desktop.
Save paradoja/2597645 to your computer and use it in GitHub Desktop.
Haskell's brute force Scala-like inverse fizzbuzz
-- http://www.jasq.org/2/post/2012/05/inverse-fizzbuzz.html
import Control.Applicative -- para <*>
import Data.List -- para sortBy
import qualified Data.Map as M
divides m n = n `mod` m == 0
fizzbuzzTest n = [divides 3, divides 5] <*> [n]
isFizzbuzz = or . fizzbuzzTest
-- de la forma del artículo:
-- isFizzbuzz n = n `mod` 3 == 0 || n `mod` 5 == 0
toFizzbuzz n = case fizzbuzzTest n of
[True, True] -> "fizzbuzz"
[True, _] -> "fizz"
_ -> "buzz"
fizzbuzz = map toFizzbuzz . filter isFizzbuzz
fizzbuzzGoogle = fizzbuzz [1..]
gAll = [[x..y] | x <- [1..100], y <- [x..100]]
results = map fizzbuzz gAll
creaComp f x y= compare (f x) (f y)
io = sortBy (creaComp snd) $ zip gAll results
inverses = map keyFirst $ groupBy (\x y -> snd x == snd y) io
where keyFirst l = (snd $ head l, map fst l)
-- *Main> length inverses
-- 302
answer k = M.lookup k (M.fromList inverses) >>= (Just . head . sortBy (creaComp
scala> val isFizzBuzz = ((x:Int) => x%3 ==0 || x%5 ==0)
scala> val toFizzBuzz = ((x:Int) => (x%3,x%5) match {
case (0,0) => "fizzbuzz"
case (0,_) => "fizz"
case _ => "buzz"
})
scala> val fizzbuzz = new PartialFunction[Int,String] {
def isDefinedAt(x:Int) = isFizzBuzz(x)
def apply(x:Int) = toFizzBuzz(x)
}
scala> val all = (1 to 100).map(x=> (x to 100).map( y=> (x,y) )).flatten
scala> val results = all.map( x=> (x._1 to x._2).collect( fizzbuzz ))
scala> val io = all.zip( results )
scala> val inverses = io.groupBy( x=> x._2)
scala> val answer = inverses.keys.map( k=> (k,inverses(k).minBy(x => x._1._2 - x._1._1)._1)).toMap
@ayosec
Copy link

ayosec commented May 6, 2012

Alternative version for Scala:

I'm sure that there are better ways to do this, but I think this approach is very Scala-ish.

class FizzBuzzSequence(val bottom: Int, val top: Int) {

  lazy val length = top - bottom

  lazy val range = (bottom, top)

  lazy val items = (bottom to top) collect ( new PartialFunction[Int,String] {
    def isDefinedAt(x: Int) = x % 3 == 0 || x % 5 == 0
    def apply(x: Int) = (x % 3, x % 5) match {
      case (0,0) => "fizzbuzz"
      case (0,_) => "fizz"
      case _     => "buzz" 
    }
  })

  override def toString = "FizzBuzzSequence(" + bottom + ", " + top + ", " + items + ")"

}

final val max = 100

val result =
  (1 to max) flatMap { bottom =>
    (bottom to max) map { top =>
      new FizzBuzzSequence(bottom, top)
    }
  } groupBy {
    _.items
  } map { group =>
    val (items, seqs) = group
    (items, seqs minBy { _.length } range)
  } toMap

println(result)

This solution has more lines, but using a class (FizzBuzzSequence) to encapsulate the boilerplate/ugly logic is more common in Scala.

The final block, with no intermediate values, is closer to the FP style.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment