scala函数式斐波那契数列

scala函数式斐波那契数列

新手


object fibonacci {
  
  def main(args:Array[String]): Unit = {
    println(fib(20))
  }


  def fib(n:Long): Long = {
    @annotation.tailrec
    def go(m:Long,frist:Long,last:Long): (Long,Long) = {
      if(m==1)
        (frist,last)
      else
        go(m-1,last,frist+last)

    }
    go(n,0,1)._2
  }
}

Scheme


(define (fibonacci n)
  (define (fib count a b)
    (if (= count n)
        b
        (fib (+ count 1) b (+ a b))))   
  (fib 1 0 1))                           
    
(display (fibonacci 20))

学了模式匹配后


object fibonacci {

  def main(args: Array[String]): Unit = {

    def num(x: Long): (Long, Long) = x match {
      case 0 => (0, 1)
      case 1 => (1, 1 + 1)
      case n => val tmp = num(n - 1);(tmp._2, tmp._1 + tmp._2)

    }

    println(num(20))

  }
}

foldr/foldl党


object fibonacci {
    
	def main(args: Array[String]): Unit = {

        val numbers =List.tabulate(20)(_ => 0:Long)

        val ans = numbers.foldLeft(List[Long](1,0))((m:List[Long],_) =>  (m.head + m.drop(1).head)+:m)

        val ans2 = numbers.foldRight(List[Long](1,0))((_ ,n:List[Long]) => (n.head + n.drop(1).head)+:n)

        println(ans)
        println(ans2)
    }
}

Lazy evaluation技能Get


object fibonacci {

  def main(args:Array[String]): Unit = {

    lazy val fibs = {

      def f(a: Int, b: Int): LazyList[Int] = a #:: f(b, a + b)

      f(1, 1)

    }

    val bigs = fibs drop 20 take 1

    println(bigs.head)

  }

}

强行迭代


object fibonacci {

  def main(args: Array[String]): Unit = {

    println(fabIteration(20))


    def fabIteration(index: Int): Long = {
      if (index == 1 || index == 2) {
        1L
      } else {
        var f1 = 1L
        var f2 = 1L
        var f3 = 0L
        for (_ <- 1 to index - 1) {
          f3 = f1 + f2
          f1 = f2
          f2 = f3
        }
        f3
      }
    }
    
  }
}

入”Points-free” 邪教


object fibonacci {

  def main(args: Array[String]): Unit = {

    val pointFree = sumPrecedingOnes andThen enumFromTo(1,20)
    println(pointFree((1,1)))
  }

}

object sumPrecedingOnes extends ( (((Long, Long)))=> ((Long, Long),((Long, Long)) => (Long, Long))){
  override def apply(con: ((Long, Long))): ((Long, Long), ((Long, Long)) => (Long, Long)) = (con,(t:(Long,Long)) =>(t._2,t._1+t._2))
}

object enumFromTo extends ( (Int,Int) => (((Long, Long),((Long, Long)) => (Long, Long))) => (Long, Long)){
  override def apply(begin: Int, end: Int) = {
    (con) => {
      var some = con._1
      for (_ <- begin to end) {
        some =  con._2(some)
      }
      some
    }
  }
}


Continuation passing style


object fibonacci {
  
  def main(args:Array[String]): Unit = {

    val cc = (ones:(Long,Long)) => (ones._2,ones._1 + ones._2)

    @annotation.tailrec
    def facCps(index:Int,ones:(Long,Long),k: ((Long,Long)) => (Long,Long)): (Long,Long) = {
      if(index == 1) {
        ones
      } else {
        facCps(index - 1, k(ones),k)
      }
    }

    val ans = facCps(20,(0,1),cc)
    println(ans._2)

  }
}

参考

Haskell程序员的进化

By example: Continuation-passing style in JavaScript