/*
 * Buffon.java by Richard J. Davies
 * from `Introductory Java for Scientists and Engineers'
 * chapter: `The Standard Libraries'
 * section: `Example - Buffon's Needle'
 *
 * This program computes pi using the statistical problem of Buffon's needle.
 * A needle of unit length is repeatedly thrown onto a plane covered in
 * parallel lines a unit distance apart. The probability that the needle lands
 * crossing a line is 2/pi. We compute pi by simulating throws and counting
 * the frequency with which the needle does cross the line. In order not to use
 * pi in the simulation, we pick the needle direction by picking a random
 * point in a unit circle about the first end and moving it to the
 * circumference. This program is intended to demonstrate use of the package
 * java.lang.Math.
 */
public class Buffon
{
  // The number of times that we throw the needle
  public static final int THROWS = 1000;

  // This method returns if a point lies inside
  // the unit circle at the origin, but is not
  // actually the origin.
  public static boolean inCircle(double x, double y)
  {
    if ((x*x + y*y < 1) && !(x==0 && y==0))
      return true;
    else
      return false;
  }

  // Throw the needle once and return if it
  // crosses a line.
  public static boolean checkCross()
  {
    double x1, y1, x2, y2;
    double dist;

    // Position one end randomly
    x1 = Math.random();
    y1 = Math.random();

    // Pick another point in the unit circle to
    // get the needle direction
    do
    {
      x2 = Math.random();
      y2 = Math.random();
    }
    while (!inCircle(x2, y2));

    // Renormalize the direction into a unit
    // vector
    dist = Math.sqrt(x2*x2 + y2*y2);
    x2 /= dist;
    y2 /= dist;

    // Add the first end's position to get
    // the second end's position.
    x2 += x1;
    y2 += y1;

    // Return whether the two end are on
    // different sides of a line
    if (Math.round(x1) != Math.round(x2))
      return true;
    else
      return false;
  }

  // This method calls checkCross to throw
  // the needle THROWS times and counts the
  // number that cross.
  public static void main(String[] argv)
  {
    int count = 0;

    // Do the throwing and counting
    for (int i=0; i<THROWS; i++)
    {
      if (checkCross())
        count++;
    }

    // The fraction that cross should be 2 / Pi
    System.out.println("Pi is " + Math.PI);
    System.out.println("Our estimate: ");
    System.out.println(THROWS * 2.0 / count);
  }
}

