сопоставление с шаблоном scala - переменная - PullRequest
1 голос
/ 29 августа 2011

Пока я читал это (стр. 14) Я столкнулся с этим алгоритмом:

function fib2(n)
    if n = 0 return 0
    create an array f[0 : : : n]
    f[0] = 0, f[1] = 1
    for i = 2 : : : n:
        f[i] = f[i  1] + f[i  2]
    return f[n]

Если бы я хотел реализовать это в Scala, используя сопоставление с образцом, есть ли способ создать список в части сопоставления с образцом, чтобы использовать его в последнем выражении возврата?

это отличные ответы, но я думаю, что я все еще хотел бы знать, возможно ли определить переменную, которую вы используете только при сопоставлении с образцом. Я знаю, что вы можете сделать это в Haskell, но мне интересно, выполнимо ли это в Scala.

Ответы [ 4 ]

13 голосов
/ 29 августа 2011
lazy val fib: Stream[Int] = Stream.cons(0,Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2)))

fib.take (n) .last вернет результат
другое потоковое решение. Он определяет бесконечную последовательность Фибоначчи. Да, это спасение и бесконечное определение, но все вычисления выполняются, пока вызывается take.
enter image description here просто проверьте здесь для более интересного кода. ссылка

10 голосов
/ 29 августа 2011

Я не вижу особой необходимости в сопоставлении с образцом здесь. Простой перевод в Scala будет выглядеть в основном так же: создайте массив f и переберите индексы 2 until n.

def fib(n: Int): Array[Int] = {
  val f = new Array[Int](math.max(2, n))
  f(0) = 0
  f(1) = 1
  for (i <- 2 until n)
    f(i) = f(i-1) + f(i-2)
  f
}

Если вы хотите полюбить, как насчет ленивого потока ?

def fibFrom(a: Int, b: Int): Stream[Int] = a #:: fibFrom(b, a + b)
fibFrom(0, 1).take(8).toList // returns List(0, 1, 1, 2, 3, 5, 8, 13)
2 голосов
/ 29 августа 2011

Вот рефакторинг решения Джилы. Я думаю, что лучше всегда работать с головой, так как это намного быстрее. Финал reverse не сильно болит.

def fib(s:Int) = {
  def f(s:Int):List[Int] = s match {
    case x if x < 0 => Nil
    case 0 => List(0)
    case 1 => List(1,0)
    case _ => val fibs = f(s-1); (fibs.head + fibs.tail.head) :: fibs
  }
  f(s).reverse
}
1 голос
/ 29 августа 2011

Я думаю, что использование ленивых потоков - лучший подход, но только для того, чтобы напрячь мышцы:

def fib(s:Int):List[Int] = s match {
  case 0 => Nil
  case 1 => 0::fib(s-1)
  case 2 => 0::1::fib(s-2)
  case _ => fib(s-1):::fib(s-1).takeRight(2).sum::Nil
}
...