SubsetGenerator.java :  » Game » rugl » com » ryanm » util » sets » Java Open Source

Java Open Source » Game » rugl 
rugl » com » ryanm » util » sets » SubsetGenerator.java
/*
 * Created on 05-Aug-2005 by Ryan McNally
 */

package com.ryanm.util.sets;

/**
 * Utility class for generating the k-subsets of the numbers 0 to n
 * 
 * @author ryanm
 */
public class SubsetGenerator
{
  private final int desiredSubsetSize;

  private final SubsetIterator iterator;

  private int[] nextSubset = null;

  /**
   * Constructs a new {@link SubsetGenerator}
   * 
   * @param setSize
   *           The size of the set
   * @param subsetSize
   *           The desired size of the subsets
   */
  public SubsetGenerator( int setSize, int subsetSize )
  {
    desiredSubsetSize = subsetSize;
    iterator = new SubsetIterator( setSize, subsetSize );

    while( iterator.hasNext() && ( nextSubset == null || nextSubset.length != desiredSubsetSize ) )
    {
      int[] a = iterator.next();
      nextSubset = a;
    }
  }

  /**
   * Gets the next subset
   * 
   * @return A subset
   */
  public int[] next()
  {
    int[] results = nextSubset;

    nextSubset = null;
    while( iterator.hasNext() && ( nextSubset == null || nextSubset.length != desiredSubsetSize ) )
    {
      int[] a = iterator.next();
      nextSubset = a;
    }

    if( nextSubset.length != desiredSubsetSize )
    {
      nextSubset = null;
    }

    return results;
  }

  /**
   * Determines if there are any more subsets to be had
   * 
   * @return <code>true</code> if there are more subsets,
   *         <code>false</code> otherwise
   */
  public boolean hasNext()
  {
    return nextSubset != null;
  }

  private class SubsetIterator
  {

    private boolean hasNext;

    private boolean jump = false;

    private int k = 0;

    private int maxSize, n, is;

    private int[] a;

    /**
     * Constructor.
     * 
     * @param n
     *           number of elements of the set.
     * @param maxSize
     *           maximal size of subset.
     */
    private SubsetIterator( int n, int maxSize )
    {
      if( n < 0 )
      {
        throw new IllegalArgumentException( "n < 0" );
      }

      // if( maxSize < 0 || maxSize > n )
      // throw new IllegalArgumentException( "maxSize < 0 ||
      // maxSize > n" );

      a = new int[ maxSize ];
      this.maxSize = maxSize;
      this.n = n;
      hasNext = n != 0 && maxSize > 0 && maxSize <= n;
    }

    /**
     * Determines whether there are any more subsets to come
     * 
     * @return true if there are more subsets, false otherwise
     */
    public boolean hasNext()
    {
      return hasNext;
    }

    /**
     * Returns the next subset of the n-set. Each subset is
     * represented by an integer array which elements are listed in
     * increasing order.
     * 
     * @return an array with the elements of the original set
     *         present in the subset.
     * @throws IllegalStateException
     *            there are no more subsets.
     */
    public int[] next()
    {
      if( !hasNext )
      {
        throw new IllegalStateException( "no next" );
      }

      if( k == 0 )
      {
        if( !jump )
        {
          is = 0;
          k++;
        }
      }
      else
      {
        if( a[ k - 1 ] == n - 1 )
        {
          k--;

          if( k == 0 )
          {
            return getResultSet();
          }

          is = a[ k - 1 ] + 1;
        }
        else
        {
          is = a[ k - 1 ] + 1;
          if( !jump )
          {
            k++;
          }
        }
      }

      a[ k - 1 ] = is;

      jump = k == maxSize;
      if( a[ 0 ] == n - 1 )
      {
        hasNext = false;
      }

      return getResultSet();
    }

    /**
     * Returns the array with the result.
     * 
     * @return the array with the result.
     */
    private int[] getResultSet()
    {
      int[] result = new int[ k ];
      System.arraycopy( a, 0, result, 0, k );
      return result;
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.