
// Hailstone.java
// Andrew Davison, ad@coe.psu.ac.th, April 2023


/* Generate the Hailstone sequence for a given number,
   and plot that sequence on a graph.

   The next number in the Hailstone sequence is 
   generated using the operations:
      1. If the number is even, divide it by two.
      2. If the number is odd, triple it and add one.

   The Collatz conjecture asks whether repeating these 
   operations will eventually send every positive integer 
   to 1.

   https://en.wikipedia.org/wiki/Collatz_conjecture
and
   https://rosettacode.org/wiki/Hailstone_sequence
   https://projecteuler.net/problem=14

   Usage:
     > compile Hailstone.java
     > run Hailstone <n>
   e.g.
     > run Hailstone 27
*/


import java.util.*;

import com.github.plot.Plot;
import com.github.plot.Plot.*;



public class Hailstone
{

  public static void main(String[] args)
  {
    if (args.length != 1) {
      System.out.println("Usage: run Hailstone <n>");
      return;
    }
    int n = Math.abs(Nut.parseInt(args[0]));

    List<Long> seq = hailSeq(n);
    System.out.println("Sequence for " + n + " has " + 
             seq.size() + " elements: " + seq);

    // use the sequence as graph data
    Plot.Data plotData = Plot.data();
    for (int i=0; i < seq.size(); i++)
      plotData.xy(i, seq.get(i));

    // plot configuration
    Plot plot = Plot.plot( Plot.plotOpts().
                      title("HailStores " + n));
    plot.xAxis("Steps", Plot.axisOpts().
                      format(Plot.AxisFormat.NUMBER_INT));
    plot.yAxis("Values", Plot.axisOpts().
                      format(Plot.AxisFormat.NUMBER_INT));

    // add data and draw
    plot.series("", plotData, Plot.seriesOpts().
                                 marker(Plot.Marker.NONE));
    PlotUtils.viewPlot("Hailstones", plot);
  }  // end of main()


  private static List<Long> hailSeq(long n)
  {
    if (n <= 0)
      throw new IllegalArgumentException(
                    "Invalid starting sequence number");

    List<Long> list = new ArrayList<Long>();
    list.add(Long.valueOf(n));
    while (n != 1) {
      if (n%2 == 0)  
        n = n/2;
      else
        n = 3*n + 1;
      list.add(Long.valueOf(n));
    }
    return list;
  } /* hailSeq */


}  // end of HailStone class
