Question

Here is my code for a cellular automaton I am working on:

UPDATE:

public class Lif1ID {

private Rule rule;
private int stepCount;

public static void main (String [ ] args) {
        Lif1ID simulation = new Lif1ID ( );
        simulation.processArgs (args);
        simulation.producePBM ( ); LINE 9
}

// Print, in Portable Bitmap format, the image corresponding to the rule and step count
// specified on the command line.
public void producePBM ( ) {
        int width = (stepCount*2+1);
        System.out.println("P1 " + width + " " + (stepCount+1));
        String prev_string = "";
        // constructs dummy first line of rule
        for (int i = 0; i < width; i++){
                if (i == stepCount+1){
                        prev_string += "1";
                } else {
                        prev_string += "0";
                }
        }
        // contructs and prints out all lines prescribed by the rule, including the first
        for (int i = 0; i < stepCount; i++) {
                String next_string = "";
                for (int j = 0; j < width; j++) {
                    // prints next line, one character at a time

                        System.out.print(prev_string.charAt(j) + " ");
                        // specifies cases for the edges as well as for normal inputs to Rule
                        if (j == 0) { 

                                next_string += rule.output(0, Character.getNumericValue(prev_string.charAt(0)), Character.getNumericValue(prev_string.charAt(1)));
                        } else if (j == width-1) {
                                next_string += rule.output(Character.getNumericValue(prev_string.charAt(width-2)), Character.getNumericValue(prev_string.charAt(width-1)), 0);
                        } else {
                                String rule_input = prev_string.substring(j-1, j+2);
                                int first = Character.getNumericValue(rule_input.charAt(0));
                                int second = Character.getNumericValue(rule_input.charAt(1));
                                int third = Character.getNumericValue(rule_input.charAt(2));
                                next_string += rule.output(first, second, third); LINE 43
                        }
                }
                // sets prev_string to next_string so that string will be the next string in line to be printed
                prev_string = next_string;
                System.out.println();
        }
}


// Retrieve the command-line arguments, and convert them to values for the rule number
// and the timestep count.
private void processArgs (String [ ] args) {
        if (args.length != 2) {
                System.err.println ("Usage: java Life1D rule# rowcount");
                System.exit (1);
        }
        try {
                rule = new Rule (Integer.parseInt(args[0]));
        } catch (Exception ex) {
                System.err.println ("The first argument must specify a rule number.");
                System.exit (1);
        }
        try {
                stepCount = Integer.parseInt (args[1]);
        } catch (Exception ex) {
                System.err.println ("The second argument must specify the number of lines in the output.");
                System.exit (1);
        }
        if (stepCount < 1) {
                System.err.println ("The number of output lines must be a positive number.");
                System.exit (1);
        }
   }
}

 class Rule {

private int a, b, c;
private String rulebin;

public Rule (int ruleNum) {
        rulebin = convertToBinary(ruleNum);
}

private String convertToBinary(int input) // get the binary presentation as you want
{                                         // if the input is 2 you'll get "00000010"
    String binary = "";
    for (int i = 0; i < 8; i++){
      if ((1 << i & input) != 0)
        binary += "1";
      else 
          binary+= "0";
    }
    binary = new StringBuffer(binary).reverse().toString();
    return binary;
}

// Return the output that this rule prescribes for the given input.
// a, b, and c are each either 1 or 0; 4*a+2*b+c is the input for the rule.
public char output (int a, int b, int c) {    
    return rulebin.charAt(7 - 4*a + 2*b + c); LINE 106
}

}

Here is the error message I get when I type in rule 30 with 3 timesteps:

java Life1D 30 3

UPDATED error message:

P1 7 4
0 0 0 0Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String       index      out of range: 151
at java.lang.String.charAt(String.java:686)
at Rule.output(Life1D.java:106)
at Life1D.producePBM(Life1D.java:43)
at Life1D.main(Life1D.java:9)

The corresponding lines are noted in the code. Why am I getting this error, and how can I fix it? I've been trying to find the error for hours, and it'll a blessing if I could be helped.

Was it helpful?

Solution

The problem is that Rule.output() expects three int parameters, but what you're calling it with on the line

next_string += rule.output(0, prev_string.charAt(0), prev_string.charAt(1));

is actually an int and then 2 chars. Now, the actual character is '0', but due to the implicit conversion the language does for you, you get the ASCII code of '0', which is 48 and that's what's passed to the function Rule.output().

Now, to fix this problem you need to use the method Character.getNumericValue() like so:

next_string += rule.output(0, Character.getNumericValue(prev_string.charAt(0)), Character.getNumericValue(prev_string.charAt(1)));

Don't forget to change the other two invocations of Rule.output()

However, note that this is not the only problem in your code, as I'm still getting String index out of range: 7, because the parameters with which the Rule.output() method is called with are now all 0, but I've answered your original question. If you need more help, let me know.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top