This is not my blog, just something I saw on Hacker News.

This is not my blog, just something I saw on Hacker News.

Alas, it doesn’t run on my machine. Can you post a screenshot?
Looking at the code, it appears to be a threshold sort of totalistic CA, where cells “die” if too many neighbors are “alive” or become “alive” if enough are alive, and with boundary conditions that are forced to be 0. I can’t tell how many colors there are from the code.
I don’t think circuit patterns are that unusual. For example the 5 neighbor totalistic 2D space has only 64 rules in it (smaller than the ECA space) and many make lines that connect at vertices (or some approximation to that)
Grid[Table[{rn,
ArrayPlot[
CellularAutomaton[{rn, {2, {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}}}, {1,
1}}, RandomInteger[1, {30, 30}], {{{80}}}]]}, {rn, 0, 63, 2}]]
For instance, here is code 38 on a 60 by 60 grid for 80 steps
I added animation to Rob’s post. Sam Gentle (author) posted code as chip.coffee on GitHub - perhaps rules can be figured out from that:
$ = document.querySelector.bind(document)
canvas = $('#chip_canvas')
ctx = canvas.getContext("2d")
DATA_W = 250
DATA_H = 250
DATA_LENGTH = DATA_W*DATA_H
data = new Uint8ClampedArray(DATA_LENGTH)
newdata = new Uint8ClampedArray(DATA_LENGTH)
drawdata = new Uint8ClampedArray(DATA_LENGTH*4) #RGBA
setup = ->
for i in [0...data.length]
data[i] = Math.random() * 255
for i in [0...drawdata.length]
drawdata[i] = if i % 4 is 3 then 255 #Alpha channel
setup()
ctx.scale(canvas.width/DATA_W, canvas.height/DATA_H)
ctx.globalCompositeOperation = "copy"
ctx.imageSmoothingEnabled = false
draw = ->
ctx.clearRect(0, 0, canvas.width, canvas.height)
for i in [0..drawdata.length] by 4
drawdata[i] = drawdata[i+1] = drawdata[i+2] = data[i>>2]
imageData = new ImageData(drawdata, DATA_W, DATA_H)
ctx.putImageData(imageData, 0, 0)
ctx.drawImage(ctx.canvas, 0, 0)
rel = (n, x, y) ->
i = n + x + y * DATA_W
b = n % (DATA_W) + x
return 0 if b > (DATA_W) or b < 0 or i >= DATA_LENGTH or i < 0 # prevent overflows
data[i]
window.rel = rel
# CHIP
SPAWN = 2.0
LIVE = 2.0
DIE = 3.0
SPAWN_POWER = 0.5
DIE_STARVE = 1/1.1
DIE_CROWD = 1/1.1
step = ->
for i in [0...data.length] by 1
neighbours = [
rel i, -1, -1 #top left
rel i, 0, -1 #top
rel i, +1, -1 #top right
rel i, -1, 0 #left
rel i, +1, 0 #right
rel i, -1, +1 #bottom left
rel i, 0, +1 #bottom
rel i, +1, +1 #bottom right
]
alive = 0
sum = 0
for n in neighbours
alive++ if n >= 127
sum += n
avg = sum / neighbours.length
if sum < LIVE*255
newdata[i] = data[i] * DIE_STARVE
else if sum > DIE*255
newdata[i] = data[i] * DIE_CROWD
else if sum >= SPAWN*255
newdata[i] = data[i]*(1-SPAWN_POWER) + 255*SPAWN_POWER
else
newdata[i] = data[i]
[data, newdata] = [newdata, data]
started = false
raf = ->
started = true
step()
draw()
requestAnimationFrame raf
raf()
canvas.addEventListener 'click', -> if started then setup() else raf()
Thanks Rob, I see it now.
I would call this more of a maze than an electric circuit. Technically an electric circuit has to be a circuit, and I think of circuit diagrams as having the funny symbols at the connections.
I have seen several examples of people finding other, neat ways of making mazes, sometimes with fancy mathematics, sometimes with short but complicated code. Even though they usually are not technically mazes (usually there is no solution path), they call them mazes (maybe they don’t try to solve them).
They are common in 2D CA also. Restricting to ones almost always one cell wide, I count 16 in this weight space, which has 128 rules (compared to 1024 rules from the 9-neighbor totalistic space that the above rule might come from)
Table[ArrayPlot[ CellularAutomaton[{rn, {2, {{2, 0, 0}, {0, 1, 0}, {2, 0, 2}}}, {1, 1}},
RandomInteger[1, {40, 40}], {{{50}}}]],
{rn, {11, 14, 35, 41, 42, 43, 44, 45, 46, 47, 58, 59, 62, 84, 113, 116}}]