import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
import javax.swing.BorderFactory;
import javax.swing.border.Border;



public class gcd extends Applet implements ActionListener
{ private JTextField txtInputA, txtInputB;
  private JButton butGCD_DecrementAlgorithm, butGCD_EuclideanAlgorithm;
  private JButton butClear;

  private JList listOutput;
  private DefaultListModel listModelOutput;
  private JScrollPane scrollPane;

  private Font myFont;

  //Construct the applet
  public gcd() {}

  //Start the applet
  public void start() {}

  //Stop the applet
  public void stop() {}

  //Destroy the applet
  public void destroy() {}

  //Initialize the applet
  public void init()
  { try
    { jbInit();
    }
    catch(Exception e)
    { e.printStackTrace();
    }
  }

  // =========================================================================
  // GUI Widget initialization
  // =========================================================================
  private void jbInit() throws Exception
  { this.setLayout(null);

    JPanel mainPanel = new JPanel();
    this.add(mainPanel);
    mainPanel.setBackground(Color.LIGHT_GRAY);
    mainPanel.setLayout(null);
    mainPanel.setBounds(0,0,500,300);
    Border etchedBorder = BorderFactory.createEtchedBorder();
    mainPanel.setBorder(etchedBorder);

    myFont = new Font("SansSerif", Font.BOLD, 16);


    txtInputA = addText("20", mainPanel);
    txtInputB = addText("12", mainPanel);
    txtInputA.setBounds(10, 10, 100, 30);
    txtInputB.setBounds(120, 10, 100, 30);

    butGCD_DecrementAlgorithm = addButton("Decrement Algorithm", mainPanel, this);
    butGCD_EuclideanAlgorithm = addButton("Euclidean Algorithm", mainPanel, this);

    butGCD_DecrementAlgorithm.setBounds(250, 10, 200, 30);
    butGCD_EuclideanAlgorithm.setBounds(250, 50, 200, 30);

    butClear = addButton("Clear", mainPanel, this);
    butClear.setBounds(30, 50, 100, 30);

    listModelOutput= new DefaultListModel();
    listOutput= new JList(listModelOutput);
    scrollPane = new JScrollPane(listOutput);
    mainPanel.add(scrollPane);
    listOutput.setFont(myFont);
    scrollPane.setBounds(10, 90, 480, 200);
  }

  public void actionPerformed(ActionEvent evt)
  { Object source = evt.getSource();

    if (source == butClear)
    { listModelOutput.removeAllElements();
      return;
    }

    int a=0, b=0;
    try
    { a = Integer.parseInt(txtInputA.getText());
      b = Integer.parseInt(txtInputB.getText());
      if (a <= 0 || b <= 0) throw new Exception();
    }
    catch(Exception e)
    { print("Error: Input must be an integer > 0");
      return;
    }
    print(" ");

    if (source == butGCD_DecrementAlgorithm) GCD_decrementAlgorithm(a,b);
    if (source == butGCD_EuclideanAlgorithm) GCD_EuclideanAlgorithm(a,b);
  }

  public JTextField addText(String str, Container parent)
  { JTextField text = new JTextField(str);
    text.setEditable(true);
    parent.add(text);
    text.setFont(myFont);
    return text;
  }

  public JButton addButton(String str, Container parent, ActionListener listener)
  { JButton myBut = new JButton(str);
    myBut.setForeground(Color.black);
    parent.add(myBut);
    myBut.addActionListener(listener);
    myBut.setFont(myFont);
    return myBut;
  }

  public void print(String str)
  { //Add string to scrolling list.
    listModelOutput.addElement(str);
  }


  //==========================================================================
  // Find the Greatest Common Divisor (GCD) of a pair of positive integers.
  // This is an obvious, but slow algorithm.
  //
  // The algorithm begins initializing the first guess of the GCD with
  // the smaller of the two input numbers.
  // The first number is then divided by the guess.
  // If the remainder is zero, then the second number is divided by the guess.
  // If the remainder is again zero, then the GCD has been found.
  // If the remainder is not zero, then the guess is decremented by 1 and
  // tried again.
  // This continues until a GCD is found.
  //
  // This algorithm takes time in liner proportion to the size of the
  // smaller of the two numbers.
  // =========================================================================
  public int GCD_decrementAlgorithm(int a, int b)
  { print("GCD_decrementAlgorithm(" + a + ", " + b + ")");
    int i, k, r;
    int gcd = 0;
    if (a<b) i=a; else i=b;
    while (gcd == 0)
    { k = a/i;
      r = a - k*i;
      print("    " + a + "/" + i +": " + a + " = " + k + "(" + i + ") + " + r);
      if (r == 0)
      { k = b/i;
        r = b - k*i;
        print("        " + b + "/" + i +": " + b + " = " + k + "(" + i + ") + " + r);
        if (r == 0) gcd = i;
      }
      i--;
    }
    print("  Greatest Common Divisor of (" + a + ", " + b + ") = " + gcd);
    return i;
  }




  //==========================================================================
  // Find the Greatest Common Divisor (GCD) of a pair of positive integers.
  // This method uses the Euclidean algorithm.
  //
  // The Euclidean algorithm is based on repeated application of two theorems:
  // 1) If n and m are integers and n > 0, we can write m = kn + r for integers
  //    k and r with 0<= r < n. Moreover, there is just one way to do this.
  //
  // 2) If a | b, and a | c, where b > c, then a | (b-c)
  //
  // Using these two theorems together gives the result that if n divides
  // a and b, then it also must divide r, since r = a – kb. Similarly, if n
  // divides b and r, then it must divide a. Therefore, the common divisors of
  // a and b are the same as the common divisors of b and r, so
  // GCD(a,b) = GCD(b, r). This is an important result because r is smaller
  // (by a factor of k) than a. Therefore, GCD(b,r) is an easier problem to
  // solve than GCD(a,b). By repeated application of this result, the problem
  // is quickly reduced.
  // =========================================================================
  public int GCD_EuclideanAlgorithm(int a, int b)
  { print("GCD_EuclideanAlgorithm(" + a + ", " + b + ")");

    // Swap a and b, if b > a.
    if (b > a)
    { int tmp = a;  a = b;  b = tmp;
    }

    // The variables r0, r1, and r2 are a series of remainders
    // with r2 being the most recent.
    int k = a/b;
    int r2 = a - k*b;
    print("    " + a + "/" + b +": " + a + " = " + k + "(" + b + ") + " + r2);
    int r1 = b;
    int r0 = 1;
    while (r2>0)
    { r0 = r1;
      r1 = r2;
      k = r0/r1;
      r2 = r0 - k*r1;
      print("    " + r0 + "/" + r1 +": " + r0 + " = " + k + "(" + r1 + ") + " + r2);
    }
    print("  Greatest Common Divisor of (" + a + ", " + b + ") = " + r1);
    return r1;
  }
}
