2

I am following the textbook The Nature of code's Example 7.1. (The original code is written in Java, but since the processing library is functionally identical to p5.js, I have rewritten it JavaScript out of convenience)

I believe that I have copied the examples code verbatim, yet somehow I have ended up with a result which I did not expect. There is an incomplete portion in the Sierpinski's triangle which is displayed.

I would like to know where I am going wrong in my code, or what I might be misunderstanding to cause this kind of issue.

Sierpinski's Triangle displays incompletely

Here's the Code for the image

class CA {
  constructor(ca_width) {
    this.generation = 0;
    this.w = 5;
    this.cells = new Array(1050 / this.w);
    this.newcells = new Array(this.cells.length);
    this.ruleset = [0, 1, 0, 1, 1, 0, 1, 0]; // [1,1,0,1,1,1,1,0]//

    for (let i = 0; i < this.cells.length; i++) {
      this.cells[i] = 0;
    }

    this.cells[this.cells.length / 2] = 1;
  }


  generate() {
    let nextgen = new Array(this.cells.length);
    for (let i = 1; i < this.cells.length - 1; i++) {
      let left = this.cells[i - 1];
      let me = this.cells[i];
      let right = this.cells[i + 1];
      nextgen[i] = this.rules(left, me, right);
    }
    this.cells = nextgen;
    this.generation++;
  }

  rules(a, b, c) {
    let s = "" + a + b + c;
    let index = parseInt(s, 2);
    return this.ruleset[index];
  }

  display() {
    for (let i = 0; i < this.cells.length; i++) {
      if (this.cells[i] == 0)
        fill(255);
      else fill(0);
      stroke(0);
      rect(i * this.w, this.generation * this.w,
        this.w, this.w);
    }
  }
}

let cA;

function setup() {
  createCanvas(windowWidth, windowHeight);
  cA = new CA(1000);
}

function draw() {
  // createCanvas(windowWidth, 400);
  // background(150);

  cA.display();
  cA.generate();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
ggorlen
  • 44,755
  • 7
  • 76
  • 106
timi95
  • 368
  • 6
  • 23
  • 2
    Could you show how you're calling this? It's easier to help with a runnable snippet. Thanks. Also, have you tried dumping the code in one of the [processing to p5.js converters](https://github.com/terabyte128/pde2js)? Even better, the Nature of Code is [available in p5.js](https://github.com/nature-of-code/noc-book-2) so you could just use that. – ggorlen May 25 '22 at 00:49
  • 1
    @ggorien I've edited the question and added the sketch code which calls my CA class. Thank you for the suggestion of using the converter, I will have a look at the differences in code and see if I can work out my bug. I am afraid I may be a bit code blind at this point though. – timi95 May 25 '22 at 08:10

1 Answers1

1

Based on your logic for computing the next generation, this.cells[0] and this.cells.at(-1) are always undefined, which is rendered as black. You might want to initialize these to 0, and possibly use a wraparound logic for computing their value (i.e. cells[0] = rule(cells.at(-1), cells[0], cells[1])).

I don't know what your Java code looks like, but if you're using a new int[] type, then that'll be zeroed out and probably work as expected, unlike JS Array().

In general, use caution with the Array() constructor in JS. It leaves the cells in an uninitialized state ("empty slots"), so you usually want to chain .fill(0) or spread/map it to make it a usable, unsurprising array that you'd expect such a constructor to emit, as it does in Java.

Keep in mind that the Nature of Code is available in a p5.js version, and there exist automatic translators from Processing to p5.js, like pde2js. Note that I haven't tried pde2js or the other translators but they seem worth a look.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • It was adding the `.fill(0)` whilst initialising the new Array which was the problem. Thank you for accurately diagnosing the problem. I am still not too clear on the wrap around logic which you've described, In my `rule()` function, I use left, middle, and right variables. Finally, I wasn't able to generate the p5.js version last night as I was getting a lot of errors even though I simply followed the basic install guide on the github repo. – timi95 May 25 '22 at 17:56
  • 1
    Wraparound won't take effect until the 1s get closer to the edge, but you can think of it like a rolled up piece of paper where the edge cells check the cell at the other side of the paper as one of their neighbors. It's optional, but can make for some cool effects in CA, like seamless wallpapers. – ggorlen May 25 '22 at 18:01
  • 1
    Thank you, I'll refer back to your answers here when I start to read more about it. It takes me a while to build intuition for new concepts, so I'm grateful to have this as a resource. – timi95 May 25 '22 at 18:24