/** Copyright Henry Bottomley March 2002*/

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.math.BigInteger;


public class partition2constraints extends Applet
 implements ActionListener
    {TextField box0, box1, box2, messagebox;
     CheckboxGroup chooseRadio;
             
     public void init()
        {
         box0 = new TextField(10); 
         add (box0); 
         Button calculate = new Button("Calculate partitions");
         calculate.addActionListener(this);
         add (calculate);
         chooseRadio = new CheckboxGroup();
         add(new Checkbox("Up to ... terms and largest term up to ...",chooseRadio,true));
         add(new Checkbox("Exactly ... terms and largest term up to ...",chooseRadio,false));
         add(new Checkbox("Up to ... terms and largest term equal to ...",chooseRadio,false));
         add(new Checkbox("Exactly ... terms and largest term equal to ...",chooseRadio,false));
         add(new Checkbox("Up to ... distinct terms and largest term up to ...",chooseRadio,false));
         add(new Checkbox("Exactly ... distinct terms and largest term up to ...",chooseRadio,false));
         add(new Checkbox("Up to ... distinct terms and largest equal to ...",chooseRadio,false));
         add(new Checkbox("Exactly ... distinct terms and largest equal to ...",chooseRadio,false));
         box1 = new TextField(6); 
         add (box1); 
         box2 = new TextField(6); 
         add (box2); 
         messagebox = new TextField(80); 
         add (messagebox);
        }    
                 
     public int triangle(int x)
        {return (x*(x+1))/2;
        }

     public void actionPerformed(ActionEvent event)
        {String arg=event.getActionCommand();
                         
        if (arg=="Calculate partitions")
           {
            int maxx=1;
            int maxy=1; 
            int maxz=1;
            int total=Integer.parseInt(box0.getText().trim());
            int terms=Integer.parseInt(box1.getText().trim());
            int limit=Integer.parseInt(box2.getText().trim());
            String labelRadio=chooseRadio.getCurrent().getLabel();

            if (labelRadio=="Up to ... distinct terms and largest term up to ..." 
             || labelRadio=="Up to ... distinct terms and largest equal to ...") // do uthis in 
               {if (labelRadio=="Up to ... distinct terms and largest term up to ...") 
                   {maxx=limit;
                    maxy=total;
                    maxz=terms;
                   }
                else if (labelRadio=="Up to ... distinct terms and largest equal to ...")
                   {maxx=limit-1;
                    maxy=total-limit;
                    maxz=terms-1;
                   }
                                                      
                if (total==0 && terms==0) //to catch a strange case
                   {maxx=0;
                    maxy=0;
                    maxz=0;
                   }
                if (maxx<maxz) //no point in looking at more distinct terms than possible terms
                   {maxz=maxx;
                   }
                if (maxy<triangle(maxz) && maxy>=0) //no point in looking at more distinct terms than could add up total
                   {maxz=(int) (Math.sqrt(2.0d*maxy));
                    while (maxy<triangle(maxz))
                       {maxz=maxz-1;
                       }
                   }
                if (maxy<maxx) //no point in looking at terms bigger than total
                   {maxx=maxy;
                   }
                                  
                if ( (triangle(maxx)-triangle(maxx-maxz)<maxy) || maxy<0 ) // Cannot highest term smaller than number of terms, or sum of largest terms less than total
                   {messagebox.setText(Integer.toString(total) + "    " + Integer.toString(terms) + "    " + Integer.toString(limit) + "    " + Integer.toString(0));
                   }
                else        // Start the heavy work - possibly a better way of doing this
                   { 
                    BigInteger rArray[][] = new BigInteger[maxx+1][maxy+1];  // this is large and growing and a potential memory problem
                    for (int x=0; x<=maxx; x++)
                       {for (int y=maxy; y>=0; y--)
                           {rArray[x][y]=BigInteger.valueOf(0l);     //start with all zero, except ... 
                           }  
                       }        
                    rArray[0][0]=BigInteger.valueOf(1l);             //... except for a single one. 
                    BigInteger sumPartitions=BigInteger.valueOf(0l); // to start a sum
                    for (int z=0; z<=maxz; z++)            //Iteration starts here
                       {for (int x=1; x<=maxx-z; x++)        //Need to increase to use previous values
                           {for (int y=maxy-triangle(z); y>=z; y--)    //Need to decrease to use previous values, but does not change if y<z
                               {if (y>=x)                                    
                                   {rArray[x][y]=rArray[x-1][y].add(rArray[x][y-x]);  //the recurrence: rArray[x-1][y] is new while rArray[x][y-x] is old 
                                   }
                                else
                                   {rArray[x][y]=rArray[x-1][y];  // rArray[x][y-x] does not exist if x>y
                                   }  // end of else 
                               }      // end of y loop  
                           }          // end of x loop   
                        sumPartitions=sumPartitions.add(rArray[maxx-z][maxy-triangle(z)]); //what we are aiming for  
                        messagebox.setText(Integer.toString(z));   // to see what is going on
                       }              // end of z loop 
                    messagebox.setText(Integer.toString(total) + "    " +Integer.toString(terms) + "    " + Integer.toString(limit) + "    " + sumPartitions.toString());
                   }                  // end of else      
               } // end of up to ... distinct if
            else
               {if (labelRadio=="Up to ... terms and largest term up to ...") 
                   {maxy=total;
                    maxz=terms;
                    maxx=limit;
                   } 
                else if (labelRadio=="Exactly ... terms and largest term up to ...") 
                   {maxy=total-terms;
                    maxz=terms;
                    maxx=limit-1;
                   } 
                else if (labelRadio=="Up to ... terms and largest term equal to ...") 
                   {maxy=total-limit;
                    maxz=terms-1;
                    maxx=limit;
                   } 
                else if (labelRadio=="Exactly ... terms and largest term equal to ...") 
                   {maxy=total-limit-terms+1;
                    maxz=terms-1;
                    maxx=limit-1;
                   } 
                else if (labelRadio=="Exactly ... distinct terms and largest term up to ...") 
                   {maxy=total-triangle(terms);
                    maxz=terms;
                    maxx=limit-terms;
                   } 
                else if (labelRadio=="Exactly ... distinct terms and largest equal to ...") 
                   {maxy=total-limit-triangle(terms-1);
                    maxz=terms-1;
                    maxx=limit-terms;
                   }
                if (total==0 && terms==0) //to catch a strange case
                   {maxx=0;
                    maxy=0;
                    maxz=0;
                   }
                if (maxz<maxx) // result same if maxx and maxz interchanged and can save memory
                   {int tempmax=maxx;
                    maxx=maxz;
                    maxz=tempmax;
                   }
                if (2*maxy>maxx*maxz) // result is symmetric about maxx*maxz/2  
                   {maxy=maxx*maxz-maxy;
                   }
                if (maxy<maxz) // do not need to look at terms larger than total... 
                   {maxz=maxy;
                   }
                if (maxy<maxx) // ...or more terms than total
                   {maxx=maxy;
                   }
                if ( (maxy<0) || (maxx<0) || (maxz<0) ) // Cannot reach negative total (or more than maxx*maxz) or have negative terms or negative number of terms
                   {messagebox.setText(Integer.toString(total) + "    " + Integer.toString(terms) + "    " + Integer.toString(limit) + "    " + Integer.toString(0));
                   }
                else        // Start the heavy work
                   { 
                    BigInteger rArray[][] = new BigInteger[maxx+1][maxy+1];  // this is large and growing and a potential memory problem
                    for (int x=0; x<=maxx; x++)
                       {for (int y=maxy; y>=0; y--)
                           {rArray[x][y]=BigInteger.valueOf(0l);   //start with all zero, except ... 
                           }  
                       }        
                    rArray[0][0]=BigInteger.valueOf(1l);             //... except for a single one. 
                    for (int z=0; z<=maxz; z++)             //Iteration starts here
                       {for (int x=1; x<=maxx; x++)        //Need to increase to use previous values
                           {for (int y=maxy; y>=z; y--)    //Need to decrease to use previous values, but does not change if y<z
                               {if (y>=x)                                    
                                   {rArray[x][y]=rArray[x-1][y].add(rArray[x][y-x]);  //the recurrence: rArray[x-1][y] is new while rArray[x][y-x] is old 
                                   }
                                else
                                   {rArray[x][y]=rArray[x-1][y];  // rArray[x][y-x] does not exist if x>y
                                   }  // end of else 
                               }      // end of y loop  
                           }          // end of x loop   
                        messagebox.setText(Integer.toString(z));   // to see what is going on
                       }              // end of z loop 
                    messagebox.setText(Integer.toString(total) + "    " +Integer.toString(terms) + "    " + Integer.toString(limit) + "    " + rArray[maxx][maxy].toString());
                   }                  // end of else      
               }                      // end of not up to ... distinct else
           }                          // end of calculate partitions
       }                              // end of actionPerormed
   }                                  // end of class partition2constraints
 
 