package taskspaces.rna;

/**
 * Contains methods to generate random RNA
 * sequence Strings from a sequence over a set space of 
 * partitions given a number of objects and modules.
 *
 * @author Rob Markel
 * @version 1.00
 */
public class Partition implements java.io.Serializable
{
   /** Holds number of objects. */
   int objects;

   /** Holds number of modules. */
   int modules;

   /** Holds partition values. */
   int[] partitions;

  /**
   * Returns the partition percentages when
   * passed a percentage. 
   * @param percentage indicates percent steps.
   * @return the current percentage values. 
   */
   public float[] getPercentages(float percentage)
   {
      float[] f=new float[partitions.length];
      for(int i=0; i<partitions.length; i++)
      {
         float value=partitions[i]*percentage;
         f[i]=value;
      }
      return f;
   }

  /**
   * Returns the current number of objects. 
   * @return the current number of objects.
   */
   public int getObjectNumber() {return objects;}

  /**
   * Sets the current number of objects.
   * @param i the desired number of objects. 
   * @return void 
   */
   public void setObjectNumber(int i) {this.objects=i;}

  /**
   * Returns the current number of modules.
   * @return the current number of modules.
   */
   public int getModuleNumber() {return modules;}

  /**
   * Sets the current number of modules.
   * @param i the desired number of modules.
   * @return void
   */
   public void setModuleNumber(int i) {this.modules=i;}

  /**
   * Returns the partition array.
   * @return the current partition array.
   */
   public int[] getPartitions() {return partitions;}

  /**
   * Sets the partition array to the 
   * given array.
   * @param i the partition array to set as the
   * current partition array.
   * @return void
   */
   public void setPartitions(int[] i) {this.partitions=i;}

  /**
   * Resets the partitions. 
   * @return void. 
   */
   public void reset() throws Exception
   {
      if(modules>objects)
      { 
         throw new Exception("modules "+modules+" > objects "+objects);
      }
      partitions=fill(objects,modules);
   }

  /**
   * Sets the partition array to the correct values.
   * @param o the number of objects.
   * @param m the number of modules.
   * @return the array of values.
   */
   public int[] fill(int obs,int mods) throws Exception
   {
      int[] array=new int[mods];
      for(int i=0; i<array.length; i++)
      {
         array[i]=1;
      }
      array[0]=obs-mods+1;
      return array;
   }

  /**
   * Returns the next permutation of the partition 
   * array.
   * @return the next permutation of the partition array.
   */
   public int[] next() throws Exception
   {
       int index=partitions.length-2;
       while(partitions[index]==1 && index>0) {index--;}
       partitions[index]--;
       int[] prefix=new int[index+1];
       System.arraycopy(partitions,0,prefix,0,index+1);
       int sum=sum(prefix);
       int[] suffix=fill(objects-sum,modules-(index+1));
       int[] result=new int[modules];
       System.arraycopy(prefix,0,result,0,prefix.length);
       System.arraycopy(suffix,0,result,prefix.length,suffix.length);
       setPartitions(result);
       return getPartitions();
    }

  /**
   * Sums the elements of a given int[]. 
   * @param ia the integer array to sum.
   * @return the sum value of the array elements.
   */
   public int sum(int[] array)
   {
      int sum=0;
      for(int i=0; i<array.length; i++)
      {
         int num=array[i];
         sum+=num;
      }
      return sum;
   }
}
