//Next Permutation and Combination Generator
//Created by Jesse Whidden (with help from Patrick McAtee)
//December 14, 2001
//Note:  this program requires a specific input procedure, which is described in
//the Instructions window.  Improved input checking is slated to arrive in the
//near future.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class NextPermComb extends JApplet implements ActionListener{
  JButton PermButton = new JButton();
  JButton CombButton = new JButton();
  JButton HelpButton = new JButton();
  JButton ClearButton = new JButton();
  JTextField PermField = new JTextField();
  JTextField SetField = new JTextField();
  JTextField CombField = new JTextField();
  JTextField PermAnswerField = new JTextField();
  JTextField CombAnswerField = new JTextField();

  public void init()
  {
    this.setVisible(true);
    this.getContentPane().setLayout(null);
    this.getContentPane().setBackground(Color.gray);
    Setup();
  }

  public void Setup()
  {
    //Permutation label
    JLabel PermLabel = new JLabel ("Permutation");
    PermLabel.setForeground(Color.black);
    PermLabel.setBounds(70,10,100,10);
    this.getContentPane().add(PermLabel);
    //Permutation field
    PermField.setBounds(10,30,170,20);
    this.getContentPane().add(PermField);
    //Next Permutation button and label
    JLabel NextPermLabel = new JLabel(" Next Perm.");
    NextPermLabel.setForeground(Color.black);
    PermButton.setBounds(190,27,100,25);
    this.getContentPane().add(PermButton);
    PermButton.add(NextPermLabel);
    PermButton.addActionListener(this);
    PermButton.setActionCommand("NextPerm");
    //Answer label
    JLabel PermAnswerLabel = new JLabel("Answer");
    PermAnswerLabel.setForeground(Color.black);
    PermAnswerLabel.setBounds(328,10,80,10);
    this.getContentPane().add(PermAnswerLabel);
    //Answer field
    PermAnswerField.setBounds(300,30,100,20);
    this.getContentPane().add(PermAnswerField);
    //Set field
    SetField.setBounds(100,60,80,20);
    this.getContentPane().add(SetField);
    //Set label
    JLabel SetLabel = new JLabel ("Set");
    SetLabel.setForeground(Color.black);
    SetLabel.setBounds(127,90,40,10);
    this.getContentPane().add(SetLabel);
    //Combination field
    CombField.setBounds(10,60,80,20);
    this.getContentPane().add(CombField);
    //Combination label
    JLabel CombLabel = new JLabel ("Combination");
    CombLabel.setForeground(Color.black);
    CombLabel.setBounds(13,90,100,10);
    this.getContentPane().add(CombLabel);
    //Next Combination button and label
    JLabel NextCombLabel = new JLabel("Next Comb.");
    NextCombLabel.setForeground(Color.black);
    CombButton.setBounds(190,58,100,25);
    this.getContentPane().add(CombButton);
    CombButton.add(NextCombLabel);
    CombButton.addActionListener(this);
    CombButton.setActionCommand("NextComb");
    //Answer field
    CombAnswerField.setBounds(300,60,100,20);
    this.getContentPane().add(CombAnswerField);
    //Answer label
    JLabel CombAnswerLabel = new JLabel("Answer");
    CombAnswerLabel.setForeground(Color.black);
    CombAnswerLabel.setBounds(328,90,80,10);
    this.getContentPane().add(CombAnswerLabel);
    //Help button and label
    HelpButton.setBounds(10,130,120,35);
    this.getContentPane().add(HelpButton);
    JLabel HelpLabel = new JLabel("  Instructions  ");
    HelpLabel.setForeground(Color.black);
    HelpButton.add(HelpLabel);
    HelpButton.addActionListener(this);
    HelpButton.setActionCommand("Help");
    //Clear button and label
    ClearButton.setBounds(280,130,120,35);
    this.getContentPane().add(ClearButton);
    JLabel ClearLabel = new JLabel("         Clear        ");
    ClearLabel.setForeground(Color.black);
    ClearButton.add(ClearLabel);
    ClearButton.addActionListener(this);
    ClearButton.setActionCommand("Clear");
  }

  public void actionPerformed(ActionEvent e)
  {
    Container contentPane = getContentPane();
    //Output for Permutation function
    if (e.getActionCommand().equals("NextPerm"))
    {
      String PermStringOut = new String();
      int[] PermArray = NextPermutation();
      for (int i = 0; i <= 19; i++)
      {
        while (PermArray[i] != 0)
        {
          PermStringOut = PermStringOut + PermArray[i]+";";
          i++;
        }
        PermAnswerField.setText(PermStringOut);
      }
    }
    //Output for Combination function
    else if (e.getActionCommand().equals("NextComb"))
    {
      int[] CombArray = NextCombination();
      String CombStringOut = new String();
      for (int i = 0; i <= 19; i++)
      {
        while (CombArray[i] != 0)
        {
          CombStringOut = CombStringOut + CombArray[i]+";";
          i++;
        }
        CombAnswerField.setText(CombStringOut);
      }
    }
    //Clears all fields
    else if (e.getActionCommand().equals("Clear"))
    {
      PermField.setText(null);
      PermAnswerField.setText(null);
      SetField.setText(null);
      CombField.setText(null);
      CombAnswerField.setText(null);
    }
    //Brings up Instructions window
    else if (e.getActionCommand().equals("Help"))
    {
      JOptionPane.showMessageDialog(this, "To use this applet, either enter a permutation that uses all n integers from 1\nto n, OR an r-combination (in increasing order) and a set size at least as\nlarge as r.  (Use semicolons (;) between terms.)  Click on the appropriate\nbutton to see the next permutation/combination!");
    }
  }

  //Permutation function
  public int[] NextPermutation()
  {
    int n = 0;
    int x = 0;
    int[] PermArray = new int[20];
    for (int y = 0; y <= 19; y++)
    {
      PermArray[y] = 0;
    }
    //Input for Permutation function
    try
    {
      String PermString = PermField.getText();
      StringTokenizer tokens = new StringTokenizer(PermString, ";");
      while (tokens.hasMoreTokens())
      {
        PermArray[x] = Integer.parseInt(tokens.nextToken());
        x++;
        n++;
      }
    }
    catch (NumberFormatException e)
    {
      JOptionPane.showMessageDialog(this, "Type in positive integers, not something else!");
      return PermArray;
    }
    //Math part of function
    int j = n - 1;
    while (PermArray[j - 1] > PermArray[j])
    {j = j - 1;}
    j = j - 1;
    int k = n;
    while (PermArray[j] > PermArray[k - 1])
    {k = k - 1;}
    int temp = PermArray[k - 1];
    PermArray[k - 1] = PermArray[j];
    PermArray[j] = temp;
    temp = 0;
    int r = n;
    int s = j + 1;
    while (r > s) {
    temp = PermArray[s];
    PermArray[s] = PermArray[r - 1];
    PermArray[r - 1] = temp;
    temp = 0;
    r = r - 1;
    s = s + 1;
    }
    return PermArray;
  }

  //Combination function
  public int[] NextCombination()
  {
    int r = 0;
    int x = 0;
    int n = 0;
    int[] CombArray = new int[20];
    for (int y = 0; y <= 19; y++)
    {
      CombArray[y] = 0;
    }
    //Input from Set field
    String SetString = SetField.getText();
    //Input from Combination field
    try
    {
      n = Integer.parseInt(SetString);
    }
    catch (NumberFormatException e)
    {
      JOptionPane.showMessageDialog(this, "Type in a positive integer, not something else!");
      return CombArray;
    }
    try
    {
      String CombString = CombField.getText();
      StringTokenizer tokens = new StringTokenizer(CombString, ";");
      while (tokens.hasMoreTokens())
      {
        CombArray[x] = Integer.parseInt(tokens.nextToken());
        x++;
        r++;
      }
    }
    catch (NumberFormatException e)
    {
      JOptionPane.showMessageDialog(this, "Type in positive integers, not something else!");
      return CombArray;
    }
    //Math part of Combination function
    int i = r;
    while (CombArray[i - 1] == ((n - r) + i))
    {
      i = i - 1;
    }
    CombArray[i - 1] = CombArray[i - 1] + 1;
    for(int j = i + 1; j <= r; j++)
    {
      CombArray[j - 1] = CombArray[i - 1] + j - i;
    }
    return CombArray;
  }
}
