All Downloads are FREE. Search and download functionalities are using the official Maven repository.

axle.PermutationsFast.scala Maven / Gradle / Ivy

The newest version!
package axle

import scala.collection.mutable.ListBuffer

import spire.implicits.IntAlgebra
import spire.implicits.eqOps

object PermutationsFast {

  def apply[E: Manifest](pool: Seq[E], r: Int): PermutationsFast[E] = new PermutationsFast[E](pool, r)
}

class PermutationsFast[E : Manifest](_pool: Seq[E], r: Int) extends Iterable[IndexedSeq[E]] {

  val pool = _pool.toArray
  val n = pool.length

  override def size: Int = if (r >= 0 && r <= n) { n.factorial / (n - r).factorial } else { 0 }

  val yeeld = new ListBuffer[IndexedSeq[E]]() // TODO substitute for "yield" for now

  if (r <= n) {
    val indices = (0 until n).toBuffer
    val cycles = n.until(n - r, -1).toArray
    yeeld += indices(0 until r).map(pool).toIndexedSeq
    var done = false
    while (n > 0 && !done) {
      var i = r - 1
      var broken = false
      while (i >= 0 && !broken) {
        cycles(i) -= 1
        if (cycles(i) === 0) {
          indices(i until n) = indices(i + 1 until n) ++ indices(i until i + 1)
          cycles(i) = n - i
        } else {
          val j = cycles(i)
          val (v1, v2) = (indices((n - j) % n), indices(i))
          indices(i) = v1
          indices((n - j) % n) = v2
          yeeld += indices(0 until r).map(pool).toIndexedSeq
          broken = true
        }
        if (!broken) {
          i -= 1
        }
      }
      if (!broken) {
        done = true
      }
    }
  }

  def iterator: Iterator[IndexedSeq[E]] = yeeld.iterator

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy