Java explicit configurable nested loop count

I am trying to do a custom number of nested loops, something like this

int size=4;
for ...
  for ...
    for ...
      for ...

      

And when resized, create a new nested loop

int size=6;
for ...
  for ...
    for ...
      for ...
        for ...
          for ...

      

I tried and tested and finally I got this:

    // The amount of nested loops
    int size=3;

    // Variables
    String output="";
    String code="";
    String home=new File("").getAbsolutePath();

    // Generating code

    // Opening
    code+="public class Temp { \n";
    code+="    public static void main(String[] args) { \n";

    String depth="        ";

    // Making the variables
    code+=depth+"int[] data = new int["+size+"];\n";
    code+=depth+"String output = \"\";\n";

    // Making the for loops
    for(int i=0; i<size; i++) {
        // Adding formatting
        for(int x=i; x>0; x--)
            code+="    ";

        // Creating for-loop
        code+=depth+"for (data["+i+"]=0; data["+i+"]<10; data["+i+"]++) {\n";
    }

    // Adding formatting
    for(int x=0; x<size; x++)
        code+="    ";

    // Making the output (data[0]+""+data[1]+""+data[2]+"" etc)
    code+=depth+"output+=";
    for(int i=0; i<size; i++) {
        code+="data["+i+"]+\"\"";
        if(i<size-1)
            code+="+";
    }
    code+=";\n";

    // Adding formatting
    for(int x=0; x<size; x++)
        code+="    ";

    // Adding a newline after the output
    code+=depth+"output+=\"\\n\";\n";

    // Adding formatting and closing for-loops
    for(int i=0; i<size; i++) {
        for(int x=i; x<size-1; x++)
            code+="    ";
        code+=depth+"}\n";
    }

    // Outputting the variable output
    code+=depth+"System.out.println(output);\n";
    code+="    }\n";
    code+="}\n";

    // Outputting the code (for debugging purposes)
    System.out.println(code);

    // Compiling, running and getting output
    try {
        // Making a file called Temp.java
        FileOutputStream fos=new FileOutputStream("Temp.java");
        byte[] buf=code.getBytes();
        fos.write(buf);
        fos.close();

        System.out.println("===== ===== ===== ===== ===== =====");
        System.out.println("\n=====        Compiling        =====\n");

        // Executing
        Process p=Runtime.getRuntime().exec("javac -d "+home+" Temp.java");

        // Getting output and error
        InputStream is=p.getInputStream();
        InputStream es=p.getErrorStream();

        buf=new byte[8192];
        byte[] ebuf=new byte[8192];

        is.read(buf);
        es.read(ebuf);

        System.out.println(new String(buf).trim());
        System.err.println(new String(ebuf).trim());

        System.out.println("\n=====         Running         =====");

        // Executing
        p=Runtime.getRuntime().exec("java Temp");

        // Getting output and error
        is=p.getInputStream();
        es=p.getErrorStream();

         buf=new byte[8192];
        ebuf=new byte[8192];
        is.read(buf);
        es.read(ebuf);

        // Make output the value of the external 'output'
        output=new String(buf).trim();
        System.err.println(new String(ebuf).trim());

        System.out.println("\n=====   Removing temp files   =====");

        // Executing
        p=Runtime.getRuntime().exec("rm -f Temp.java Temp.class");

        // Getting output and error
        is=p.getInputStream();
        es=p.getErrorStream();

        buf=new byte[8192];
        ebuf=new byte[8192];
        is.read(buf);
        es.read(ebuf);

        System.out.println(new String(buf).trim());
        System.err.println(new String(ebuf).trim());

        System.out.println("\n===== ===== ===== ===== ===== =====");

    } catch(Exception e) {
        e.printStackTrace();
    }

    // Outputting the output
    System.out.println("output\n"+output);

      

It works as it should, but I hate the way to create, compile and run an external Java file. Are there better ways to do the same without using an external file?

+3


source to share


2 answers


Recursion is the answer (as above) or manipulating the "i" variables inside the array:



public void nestedLoop(int size, int loopSize) {
    int[] i = new int[size];
    while (i[size-1] < loopSize) {
       doSomethingWith(i);
       increment(i, loopSize);
    }
}

public void increment(int[] i, int maxSize) {
   int idx = 0;
   while (idx < i.length) {
      if (++i[idx] < maxSize) {
         return;
      }
      i[idx++] = 0;
   }
}

      

+2


source


The specific problem you can solve can be solved in several different ways, but here is the general answer.

Usually, when you have a situation where the only way out seems to be writing meta-program

(i.e. code to generate code, often happens to people who start programming), give recursion a thought.

Example


Consider the problem of creating all possible length strings k

that can be created using a set S = {a, b, c, d}

.

One way to do this is to write a metaprogram that generates another program that has k for

loops. Something like:



for `i1` in S:
    for `i2` in S:
    ...
       for `ik` in S:
           print i1 + i2 + ... + ik

      

Then you need to compile it and run the executable so obtained using system()

or a similar function.

A simpler alternative is to use recursion.

For example,

//sg
public class printKStr
{
    int k;
    String S;
    public void printKdigs(int pos, char[] str) {
        if(pos == k) {
            System.out.println(str);
            return;
        }
        int l = S.length();
        for(int i = 0; i < l; i++) {
            str[pos] = S.charAt(i);
            printKdigs(pos + 1, str);
        }
    }

    public static void main(String args[]) {
        printKStr pk = new printKStr();
        pk.S = "abc";
        pk.k = 3;
        char[] temp1 = new char[pk.k + 1];
        pk.printKdigs(0, temp1);
    }

}

      

  • Each activation printKdigs

    in some sense represents a for loop.

  • We need a data structure that can hold the state created by each of these activations, in this case it is string

    str

    .

  • We set the values ​​correctly and recurse. Finally, on completion, the value in the data structures containing the recursive call trail ( str

    here) gives you one legal combination.

+2


source







All Articles