
// FareyGrid.java
// Andrew Davison, ad@coe.psu.ac.th, April 2023

/* Display a Farey sequence as a grid of colored boxes.
   https://en.wikipedia.org/wiki/Farey_sequence

   Usage:
     > compile FareyGrid.java
     > run FareyGrid <n>
   e.g.
     > run FareyGrid 8
     > run FareyGrid 9
          // this appears on the wiki page
     > run FareyGrid 30

   The Farey sequence is generated by the FareySeq object
   using a default range of [0, 1]. The n argument is the
   maximum denominator used in the generated sequence.

   Other Farey examples can be found in:
     FareySeq.java, FordCircles.java
*/

import java.math.*;
import java.util.*;

import org.apache.commons.numbers.fraction.*;
import org.apache.commons.numbers.core.*;


public class FareyGrid
{
  private static final int MAX_WIDTH = 1200;
  private static final int BOX_SIZE = 22;

  public static void main(String[] args)
  {
    if (args.length != 1) {
      System.out.println("Usage: run FareyGrid <n>");
      return;
    }
    int n = Math.abs(Nut.parseInt(args[0]));

    System.out.println("Farey Sequence " + n + ":");
    FareySeq fs = new FareySeq(n); 
    ArrayList<Fraction> fseq = fs.getFareySeq();
    System.out.println("Farey Sequence; den=" + n + "; [0 - 1]:");
    System.out.println(fseq + "\n");

    // extract the sequence's denominators
    int[] denoms = new int[fseq.size()];
    for(int i=0; i < fseq.size(); i++)
       denoms[i] = fseq.get(i).getDenominator();
    System.out.println("Denominators: " + Arrays.toString(denoms));

    // reduce the grid's box size to handle long sequences
    int boxSize = BOX_SIZE;
    while (boxSize*denoms.length > MAX_WIDTH) {
      boxSize--;
      if (boxSize == 0) {
        boxSize = 1;   // minimum size
        break;
      }
    }

    StdDraw.setCanvasSize(boxSize*denoms.length, boxSize*n);
    StdDraw.setXscale(0, denoms.length);
    StdDraw.setYscale(1, n+1);   // no 0 denominator on y-axis

    StdDraw.clear();

    // draw a grid of empty boxes
    StdDraw.setPenColor(StdDraw.BLACK);
    for(int i=0; i < denoms.length; i++)
      for(int j=1; j < n+1; j++)   // no 0 denominator
        StdDraw.square(i+0.5, j+0.5, 0.5);

    // color in the boxes (i, denoms[i]) for the denominators
    StdDraw.setPenColor(StdDraw.BLUE);
    for(int i=0; i < denoms.length; i++)
      StdDraw.filledSquare(i+0.5, denoms[i]+0.5, 0.5);

  } /* main */

}  // end of FareyGrid class
