
// Goldbach.java
// Andrew Davison, ad@coe.psu.ac.th, April 2023

/* Draw a graph of Goldbach's comet based on examining 
   the even numbers up to n.

   Goldbach's conjecture states that every even 
   number greater than 2 is the sum of two prime numbers. 

   goldbach() returns the number of ways of producing an integer 
   using the primes loaded from primes1M.txt. 
   The results are plotted on a graph, which is called
   Goldbach's comet.

   https://en.wikipedia.org/wiki/Goldbach%27s_conjecture
and
   https://towardsdatascience.com/prime-numbers-and-goldbach-s-conjecture-visualization-60d1993a1424

   Usage:
     > compile Goldbach.java
     > run Goldbach <n>
   e.g.
     > run Goldbach 1000
     > run Goldbach 10000

*/

import java.awt.Color;
import java.util.*;

import com.github.plot.Plot;
import com.github.plot.Plot.*;


public class Goldbach
{

  public static void main(String[] args)
  { 
    if (args.length != 1) {
      System.out.println("Usage: run Goldbach <n>");
      return;
    }
    int n = Math.abs(Nut.parseInt(args[0]));

    int[] primes = Nut.loadPrimes("primes1M.txt");
    System.out.println("Loaded " + primes.length + " primes");

    Plot.Data plotData = Plot.data();
    for (int i=4; i <= n; i = i+2)  // check even numbers
      plotData.xy(i, goldbach(i, primes));

    // plot configuration
    Plot plot = Plot.plot( Plot.plotOpts().
                      title("No. of Goldbach Combinations up to " + n));

    plot.xAxis("Evens", Plot.axisOpts().
                      format(Plot.AxisFormat.NUMBER_INT));
    plot.yAxis("Count", Plot.axisOpts().
                      format(Plot.AxisFormat.NUMBER_INT));

    DataSeriesOptions dataOpts = Plot.seriesOpts().
                       line(Plot.Line.NONE).
                       marker(Plot.Marker.CIRCLE).
                       markerSize(5).
                       color(Color.RED).
                       markerColor(Color.RED);

    // add data and draw
    plot.series("", plotData, dataOpts);
    PlotUtils.viewPlot("Goldbach Comet", plot);
  } // end of main()


  private static int goldbach(int n, int[] primes)
  /* return the number of ways of producing n using
     pairs of primes in the array */
  {
    if ((n <= 2) || (n % 2 != 0)) {
      System.out.println("Invalid Input " + n);
      return 0;
    }
 
    // Check upto half the number
    int count = 0;
    for (int i = 0; primes[i] <= n/2; i++) {
      int diff = n - primes[i];
      if ( Nut.isPrime(diff, primes))
        count++;
    }
    return count;
  }  // end of goldbach()

}  // end of Goldbach class