0

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.

1 Answers1

0

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.

  • Hey, I figured as much that it was because of the character typing. How would you recommend going about the last error? – John Cheung Apr 09 '13 at 22:20
  • That's a logic error most likely. When you're running the program with the first argument 30, it makes a string with size 5 because 30 in binary is 11101 (if I'm not mistaken), and on your first invocation of `Rule.output()` you try to get the character at index 7, which doesn't exist. If you're working with an IDE with debugging capabilities such as Eclipse, I recommend using them to your advantage. :) – Emma Gospodinova Apr 09 '13 at 22:31
  • Okay, I updated the code, created a better binary converter. But I'm still getting an error! this is annoying. Could you please take one last look at my code? Many thanks. – John Cheung Apr 09 '13 at 22:42
  • You've forgotten the call in the `else if` statement: `next_string += rule.output(prev_string.charAt(width-2), prev_string.charAt(width-1), 0);` – Emma Gospodinova Apr 09 '13 at 22:54
  • By the way, are you sure this line is correct: `return rulebin.charAt(7 - 4*a + 2*b + c);`? Shouldn't it be: `return rulebin.charAt(7 - (4*a + 2*b + c));` – Emma Gospodinova Apr 09 '13 at 22:57
  • YES IT WORKED THIS IS A MIRACLE – John Cheung Apr 09 '13 at 22:59