3
\$\begingroup\$

I implemented the "frozen window" from my preview paper A Fractal Streaming Algorithm, Prime Patterning and the Infinitude of Twin Primes in order to count the "letters" in the stability zone of my prime sieve up to n=250000. The sieve consists of tapes and tape CPn contains symbols that encode the natural numbers. Symbol L (live) means can be prime or composite or one. Symbol M (multiple) means composite. All symbol combinations can be described by four letter combinations: letter a LMLMMM, letter b is LMMMMM, letter c is MMLMMM and letter d is MMMMMM.

Here is my code, which also can be downloaded from https://github.com/cerebrummi?tab=repositories.

CODE

package enums;

public enum Letter
{
   a("LMLMMM"), 
   b("LMMMMM"), 
   c("MMLMMM"), 
   d("MMMMMM");
   
   public final String pattern;

   Letter(String pattern)
   {
      this.pattern = pattern;
   }
}

CODE

package common;

import enums.Letter;

public class LetterFA
{
   private static final int _19 = 19;
   /**
    * 4 is the step where letter a has formed.
    */
   private int walksetBn = 4;
   private String walksetBPn = "M";

   private int offset = 0;
   StringBuilder walksetCPn = new StringBuilder(Letter.a.pattern);

   private int counterA;
   private int counterB;
   private int counterC;
   private int counterD;

   public void step()
   {
      walksetBn++;

      walksetBPn = String.valueOf(walksetCPn.charAt(0));

      fractalProcessMove();

      if ("L".equalsIgnoreCase(walksetBPn.toString()))
      {
         if (walksetBn < _19)
         {
            fractalProcessCopy();
         }
         fractalProcessChange();
      }

      counterA = 0;
      counterB = 0;
      counterC = 0;
      counterD = 0;

      String copyCPn = walksetCPn.toString();
      int start = offset;
      int end = offset + 6;
      int stabilityZone = walksetBn;
      for (; end < stabilityZone;)
      {
         String letter = copyCPn.substring(start, end);
         matchLetter(letter);
         start += 6;
         end += 6;
      }
   }

   public void matchLetter(String letter)
   {
      if (Letter.a.pattern.equals(letter))
      {
         counterA++;
      }
      else if (Letter.b.pattern.equals(letter))
      {
         counterB++;
      }
      else if (Letter.c.pattern.equals(letter))
      {
         counterC++;
      }
      else if (Letter.d.pattern.equals(letter))
      {
         counterD++;
      }
      else
      {
         System.err.println("invalid letter " + letter + " n = " + walksetBn);
         System.exit(1);
      }
   }

   private void fractalProcessChange()
   {
      int index = walksetBn + 1;
      for (int i = 0; i < walksetCPn.length(); i++)
      {
         if ((index % walksetBn) == 0)
         {
            walksetCPn.replace(i, i + 1, "M");
         }
         index++;
      }
   }

   private void fractalProcessCopy()
   {

      String copy = walksetCPn.toString();

      for (int i = 1; i < walksetBn; i++)
      {
         walksetCPn.append(copy);
      }
   }

   private void fractalProcessMove()
   {
      String firstSymbol = walksetCPn.substring(0, 1);
      walksetCPn.deleteCharAt(0);
      if (walksetBn < _19)
      {
         walksetCPn.append(firstSymbol);
      }
      offset--;
      if (offset < 0)
      {
         offset = 5;
      }

   }

   public int getCounterA()
   {
      return counterA;
   }

   public int getCounterB()
   {
      return counterB;
   }

   public int getCounterC()
   {
      return counterC;
   }

   public int getCounterD()
   {
      return counterD;
   }

   public int getWalksetBn()
   {
      return walksetBn;
   }

   public Integer getPatternSize()
   {
      return walksetCPn.length();
   }
}

CODE

package common;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.StringJoiner;

public class StartLetterFa
{
   private final static int NUMBER_OF_STEPS = 250000;

   private static HashMap<Integer,Integer[]> counter = new HashMap<>();

   public static void main(String[] args)
   {
      LetterFA letterFA = new LetterFA();

      for (int i = letterFA.getWalksetBn(); i < NUMBER_OF_STEPS; i++)
      {
         letterFA.step();
         
         counter.put( (i + 1),new Integer[] {
               letterFA.getCounterA(),
               letterFA.getCounterB(),
               letterFA.getCounterC(),
               letterFA.getCounterD()});
      }

      ArrayList<Integer> keys = new ArrayList<>(counter.keySet());
      handleCounter(keys);

   }

   public static void handleCounter(ArrayList<Integer> keys)
   {
      keys.sort(new Comparator<Integer>()
      {

         @Override
         public int compare(Integer o1, Integer o2)
         {
            if( o1 < o2)
            {
               return -1;
            }
            return 1;
         }
      });

      
      
      File file = new File("stabilityzone_lettersABCD_250000.csv");
      
      try(FileOutputStream stream = new FileOutputStream(file);
            OutputStreamWriter writer = new OutputStreamWriter(stream,
                  StandardCharsets.UTF_8);)
      {
         StringJoiner joiner = new StringJoiner("\n");
         joiner.add("n\ta\tb\tc\td");
         
         Integer[] content;
         for (Integer key : keys)
         {
            content = counter.get(key);

            joiner.add(key + "\t"+ content[0]+ "\t"+ content[1]+ "\t"+content[2]+ "\t"+content[3]);

         }

         writer.write(joiner.toString());
         writer.flush();
         writer.close();
      }
      catch (UnsupportedEncodingException e)
      {
         e.printStackTrace();
      }
      catch (FileNotFoundException e)
      {
         e.printStackTrace();
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
   }

}

The code works, but I am happy to have it reviewed.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Is this a follow-up to codereview.stackexchange.com/q/297952/35991, or a different task? \$\endgroup\$ Commented 16 hours ago
  • \$\begingroup\$ It is a different task. \$\endgroup\$ Commented 15 hours ago

1 Answer 1

3
\$\begingroup\$

StartLetterFa

StartLetterFa.counter should be final. However, it should not be static. You should instantiate StartLetterFa; to preserve re-entrance it should be treated as a normal object. This requires that most of the code in main be moved out into a run method.

I don't think that you need a custom comparator; you can use the default Integer compare method.

Your getWalksetBn loop can move the +1 into the loop statement rather than performing it in the put.

I don't think you need a File here; a string will do.

Rather than OutputStreamWriter, I think PrintWriter is more fitting your scenario.

This could look like:

package com.stackexchange;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;

public class StartLetterFa {
    private final static int NUMBER_OF_STEPS = 1000;  // 250000;
    private final HashMap<Integer, Integer[]> counter = new HashMap<>();
    private final LetterFA letterFA = new LetterFA();

    public static void main(String[] args) {
        StartLetterFa program = new StartLetterFa();
        try {
            program.run();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() throws IOException {
        for (int i = 1 + letterFA.getWalksetBn(); i <= NUMBER_OF_STEPS; i++) {
            letterFA.step();
            counter.put(i, new Integer[] {
                letterFA.getCounterA(),
                letterFA.getCounterB(),
                letterFA.getCounterC(),
                letterFA.getCounterD(),
            });
        }

        ArrayList<Integer> keys = new ArrayList<>(counter.keySet());
        handleCounter(keys);
    }

    public void handleCounter(ArrayList<Integer> keys) throws IOException {
        keys.sort(Integer::compare);
        final String filename = "stabilityzone_lettersABCD_250000.tsv";
        try (FileOutputStream stream = new FileOutputStream(filename);
            PrintWriter writer = new PrintWriter(stream))
        {
            writer.println("n\ta\tb\tc\td");

            for (Integer key: keys) {
                Integer[] content = counter.get(key);
                writer.printf("%d\t%d\t%d\t%d\t%d%n",
                    key, content[0], content[1], content[2], content[3]);
            }
        }
    }
}

LetterFA

Writing _19 = 19 is no better than just writing the literal in-place. This needs a different name.

Don't System.exit here; throw an exception instead and catch it at the outer level.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.