Tuesday, November 2, 2010

S12

S-99: Ninety-Nine Scala Problemsを試してみる。
勉強のためにListのAPIはなるべく使わない方向で。

//P12 (**) Decode a run-length encoded list.
//Given a run-length code list generated as specified in problem P10, construct its uncompressed version.
//Example:
//scala> decode(List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e)))
//res0: List[Symbol] = List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)

def decode[T](xs: List[(Int, T)]) = {

  // not tail recursion
  def ntimes_nottail(n: Int, x: T): List[T] = {
    if (n < 0) throw new IllegalArgumentException
    else if (n == 0) Nil
    else x :: ntimes_nottail(n - 1, x)
  }

  // tail recursion
  def ntimes_tail(ntimes: Int, x: T) = {
    def ntimes_rec(n: Int, result: List[T]): List[T] = {
      if (n == 0) result else ntimes_rec(n - 1, x :: result)
    }
    if (ntimes < 0) throw new IllegalArgumentException else ntimes_rec(ntimes, Nil)
  }

  // tail recursion
  def recursive(ys: List[(Int, T)], result: List[T]): List[T] = ys match {
    case Nil => result
    case (times, x) :: tail =>  recursive(tail, result ::: ntimes_tail(times, x))
//    case (times, x) :: tail =>  recursive(tail, result ::: ntimes_nottail(times, x))
  }

  recursive(xs, Nil)
}


val l = List((5, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e))
println(decode(l))


末尾再帰版(ntimes_tail)だと100万回のループでもStackOverFlowにならなかったが、
非末尾再帰版だと10万回でStackOverFlowした。

解答例
そ、そんな!!

No comments:

Post a Comment