
// PrimeSpiral.java
// Andrew Davison, ad@coe.psu.ac.th, Nov. 2022

/* Draw an Ulam spiral

  https://en.wikipedia.org/wiki/Ulam_spiral
  https://github.com/tszambor/introcs/blob/master/Spiral.java
  https://rosettacode.org/wiki/Ulam_spiral_(for_primes)#Java

   Usage:
     > compile PrimeSpiral.java
     > run PrimeSpiral <num pts>
   e.g.
     > run PrimeSpiral 10000
*/

public class PrimeSpiral
{
  private static final int PAUSE = 10;  // ms


  public static void main(String[] args)
  {
    if (args.length != 1) {
      System.out.println("Usage: java PrimeSpriral <num pts>");
      System.exit(1);
    }
    long numPts = Long.parseLong(args[0]);
    int len = (int)Math.ceil( Math.sqrt(numPts));  // length of the sides

    StdDraw.setXscale(0, len);
    StdDraw.setYscale(0, len);
    StdDraw.setPenRadius(0.005);

    int x = 0, y = 0;    // (x,y) coord relative to (0,0)
    int step = 1;   // number of steps taken in one direction
    int dirX = 1, dirY = 1;   // directions in which to move

    StdDraw.clear();
    StdDraw.setPenColor(StdDraw.BLACK);

    long val = 1;     // the number to test for primality
    int numLoops = 0;
    while (val <= len * len) {
      if (numLoops % 2 == 0) {    // move horizontally
        for (int i = 0; i < step; i++) {  
          if (isPrime(val)) {
            StdDraw.point(x + len/2, y + len/2);  // relative to center
            StdDraw.pause(PAUSE);
          }
          x += dirX;
          val++;
        }
        dirX *= -1;  // toggle x-direction
      }
      else {   // move vertically
        for (int i = 0; i < step; i++) {
          if (isPrime(val)) {
            StdDraw.point(x + len/2, y + len/2);
            StdDraw.pause(PAUSE);
          }
          y += dirY;
          val++;
        }
        dirY *= -1;  // toggle y-direction
        step++;
      }
      numLoops++;
    }
    System.out.println("Spiral finished");
  } /* main */


  private static boolean isPrime(long val)
  {
    for (long i = 2; i <= val/i; i++)
      if (val % i == 0)
        return false;
    return true;
  } /* isPrime */


}  // end of PrimeSpiral class