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

com.barrybecker4.math.combinatorics.Permuter.scala Maven / Gradle / Ivy

The newest version!
/* Copyright by Barry G. Becker, 2000-2018. Licensed under MIT License: http://www.opensource.org/licenses/MIT */
package com.barrybecker4.math.combinatorics

import com.barrybecker4.math.MathUtil

import scala.collection.mutable.ArrayBuffer

/**
  * Provides a way of iterating through all the permutations of a set of N integers (including 0).
  * If there are more than Long.MAX_VALUE permutations, this will not work.
  * The implementation does not require memory for storing the permutations since
  * only one is produced at a time.
  * @param num the number of integer elements to permute.
  * @author Barry Becker
  */
class Permuter(val num: Int) extends Iterator[List[Int]] {
  val numPermutations: Long = MathUtil.factorial(num)
  if (numPermutations < 0)
    throw new IllegalArgumentException("The number of permutations is greater than " + Long.MaxValue)
  private var hasMore = num > 0

  /** the most recently created permutation   */
  private var lastPermutation = new ArrayBuffer[Int](num)

  for (i <- 0 until num)
    lastPermutation.append(i)

  override def hasNext: Boolean = hasMore

  /** @return the next permutation*/
  override def next(): List[Int] = {
    val permutation = lastPermutation
    val nextPermutation = lastPermutation.clone()
    var k = nextPermutation.size - 2
    if (k < 0) {
      hasMore = false
      return lastPermutation.toList
    }
    while (nextPermutation(k) >= nextPermutation(k + 1)) {
      k -= 1
      if (k < 0) {
        hasMore = false
        return lastPermutation.toList
      }
    }
    var len = nextPermutation.size - 1
    while ( {
      nextPermutation(k) >= nextPermutation(len)
    }) len -= 1
    swap(nextPermutation, k, len)
    val length = nextPermutation.size - (k + 1)

    for (i <- 0 until length / 2) {
      swap(nextPermutation, k + 1 + i, nextPermutation.size - i - 1)
    }
    lastPermutation = nextPermutation
    permutation.toList
  }

  /** Swap two entries in the list  */
  private def swap(permutation: ArrayBuffer[Int], i: Int, j: Int): Unit = {
    val temp = permutation(i)
    permutation(i) = permutation(j)
    permutation(j) = temp
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy