
์ ๋ฃฐ๋ฌ ์คํ ๋งํ(CA)๋ ๊ฒฉ์ ํํ๋ก ๋ฐฐ์ด๋ ์ (Cell)๋ค์ด ์ฃผ๋ณ ์ ์ ์ํ์ ๋ฏธ๋ฆฌ ์ ํด์ง ๋จ์ํ ๊ท์น์ ๋ฐ๋ผ ์์ ์ ์ํ๋ฅผ ๋ณํ์ํค๋ฉฐ ์๊ฐ์ ์งํํ๋ ์์คํ ์ ๋๋ค. ์ด ์์คํ ์ ๊ฐ์ฅ ์ ๋ช ํ ์๊ฐ ๋ฐ๋ก ์ฝ์จ์ด์ ์๋ช ๊ฒ์(Conwayโs Game of Life, GOL)์ ๋๋ค.
GOL์ ํ์(Birth)๊ณผ ์ฃฝ์(Death)์ด๋ผ๋ ๋จ ๋ค ๊ฐ์ง์ ๋จ์ํ ๊ท์น๋ง์ผ๋ก ์์ธก ๋ถ๊ฐ๋ฅํ๊ณ ๋ณต์กํ๋ฉฐ, ์ฌ์ง์ด ์ด๋ํ๊ฑฐ๋ ์ง๋ํ๋ ๋ฏํ ๋ณต์กํ ์๋ช ํ์์ ๊ตฌํํฉ๋๋ค. ์ด๋ ๋จ์ ๊ท์น์ด ์ด๋ป๊ฒ ๋ณต์ก์ฑ์ ์ฐฝ๋ฐ(Emergence)์ํค๋์ง ๋ณด์ฌ์ฃผ๋ ํ๋ฅญํ ์์์ ๋๋ค.

์ด ์ฝ๋๋ ๊ฒฉ์(Grid)๋ฅผ ๊ตฌ์ฑํ๊ณ , draw() ํจ์๊ฐ ๋ฐ๋ณต๋ ๋๋ง๋ค ์ฃผ๋ณ ์
์ ์์ฌ(็ๆฎบ) ์ฌ๋ถ์ ๋ฐ๋ผ ๋ค์ ์ธ๋๋ฅผ ๊ณ์ฐํ๊ณ ํ๋ฉด์ ๊ทธ๋ฆฝ๋๋ค.
// ====== ์ ์ญ ๋ณ์ ์ค์ ======
let grid; // ํ์ฌ ์ธ๋์ ์ํ (0: Dead, 1: Alive)
let cols;
let rows;
let resolution = 5; // ์
ํ๋์ ํฌ๊ธฐ (ํฝ์
)
function setup() {
// ์บ๋ฒ์ค๋ฅผ 600x600์ผ๋ก ์์ฑํฉ๋๋ค.
createCanvas(600, 600);
// ์
์ ๊ฐ์ ๊ณ์ฐ
cols = floor(width / resolution);
rows = floor(height / resolution);
// ์๋ฎฌ๋ ์ด์
์๋๋ฅผ ์กฐ์ ํฉ๋๋ค. (์ด๋น 5 ํ๋ ์)
// ๋๋ฌด ๋น ๋ฅด๋ฉด ํจํด ๋ณํ๋ฅผ ๊ด์ฐฐํ๊ธฐ ์ด๋ ต์ต๋๋ค.
frameRate(5);
// ์ด๊ธฐ ๊ฒฉ์ ์ํ๋ฅผ ์ค์ ํ๊ณ ๋ฌด์์๋ก ์๋ช
์ฒด๋ฅผ ๋ฐฐ์นํฉ๋๋ค.
grid = initializeRandomGrid(cols, rows);
// ๋ฐฐ๊ฒฝ์ ์ด๋์ด ์์ผ๋ก ์ค์ ํฉ๋๋ค.
background(20);
}
function draw() {
// 1. ํ์ฌ ์ธ๋ ๊ทธ๋ฆฌ๊ธฐ
background(20); // ๋งค ํ๋ ์๋ง๋ค ๋ฐฐ๊ฒฝ์ ๋ค์ ์น ํด ์์์ ์ ๊ฑฐํฉ๋๋ค.
drawGrid(grid);
// 2. ๋ค์ ์ธ๋ ๊ณ์ฐ
// CA์ ํต์ฌ: ํ์ฌ ์ํ(grid)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ์ํ(nextGrid)๋ฅผ ๊ณ์ฐํฉ๋๋ค.
let nextGrid = computeNextGeneration(grid);
// 3. ์ํ ์
๋ฐ์ดํธ
// ๊ณ์ฐ๋ ๋ค์ ์ธ๋๋ฅผ ํ์ฌ ์ธ๋๋ก ๊ต์ฒดํฉ๋๋ค.
grid = nextGrid;
}
// ====== ์ ํธ๋ฆฌํฐ ํจ์ ======
/**
* 2์ฐจ์ ๋ฐฐ์ด์ ์์ฑํ๊ณ ๋ฌด์์ ์ด๊ธฐ๊ฐ์ ์ค์ ํฉ๋๋ค.
*/
function initializeRandomGrid(cols, rows) {
let arr = new Array(cols);
for (let i = 0; i < cols; i++) {
arr[i] = new Array(rows);
for (let j = 0; j < rows; j++) {
// 50% ํ๋ฅ ๋ก 0(์ฃฝ์) ๋๋ 1(์์กด)์ ๋ถ์ฌํฉ๋๋ค.
arr[i][j] = floor(random(2));
}
}
return arr;
}
/**
* ํ์ฌ ๊ฒฉ์์ ์ํ๋ฅผ ์บ๋ฒ์ค์ ๊ทธ๋ฆฝ๋๋ค.
*/
function drawGrid(currentGrid) {
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
let x = i * resolution;
let y = j * resolution;
if (currentGrid[i][j] == 1) {
// ์์กดํ ์
(Alive): ํฐ์
fill(200, 170, 80);
stroke(20); // ์
๊ฒฝ๊ณ์ ์ ๋ฐฐ๊ฒฝ์๊ณผ ๋น์ทํ๊ฒ ์ค์
rect(x, y, resolution, resolution);
} else {
// ์ฃฝ์ ์
(Dead): ๊ทธ๋ฆฌ์ง ์์ (๋ฐฐ๊ฒฝ์ ์ ์ง)
// noStroke();
// fill(20);
// rect(x, y, resolution, resolution);
}
}
}
}
/**
* ์ฝ์จ์ด์ ์๋ช
๊ฒ์ ๊ท์น์ ์ ์ฉํ์ฌ ๋ค์ ์ธ๋๋ฅผ ๊ณ์ฐํฉ๋๋ค.
*/
function computeNextGeneration(currentGrid) {
// ๋ค์ ์ธ๋๋ฅผ ๋ด์ ์๋ก์ด ๊ฒฉ์๋ฅผ ๋ง๋ญ๋๋ค. (์ค์: ํ์ฌ ๊ฒฉ์๋ฅผ ์ง์ ์์ ํ๋ฉด ์ ๋ฉ๋๋ค!)
let newGrid = initializeEmptyGrid(cols, rows);
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
// 1. ํ์ฌ ์
์ ์ํ
let state = currentGrid[i][j];
// 2. ์ด์ ์
(8๋ฐฉํฅ) ์ค ์ด์์๋ ์
์ ๊ฐ์๋ฅผ ์
๋๋ค.
let liveNeighbors = countLiveNeighbors(currentGrid, i, j);
// 3. ์ฝ์จ์ด์ 4๊ฐ์ง ๊ท์น ์ ์ฉ
if (state == 0 && liveNeighbors == 3) {
// ๐ ๊ท์น 4: ํ์ (Birth)
// ์ฃฝ์ ์
์ด ์ด์ 3๊ฐ๋ฅผ ๊ฐ์ง๋ฉด ์ด์๋ฉ๋๋ค.
newGrid[i][j] = 1;
} else if (state == 1) {
if (liveNeighbors < 2 || liveNeighbors > 3) {
// ๐ ๊ท์น 1 & 3: ๊ณผ์/๊ณผ๋ฐ์ ์ํ ์ฃฝ์ (Death)
// ์ด์์ด 2๊ฐ ๋ฏธ๋ง์ด๊ฑฐ๋ 3๊ฐ๋ฅผ ์ด๊ณผํ๋ฉด ๊ณ ๋
๋๋ ๊ณผ๋ฐ๋ก ์ฃฝ์ต๋๋ค.
newGrid[i][j] = 0;
} else {
// ๐ ๊ท์น 2: ์์กด (Survival)
// ์ด์์ด 2๊ฐ ๋๋ 3๊ฐ๋ฉด ๋ค์ ์ธ๋์๋ ์์กดํฉ๋๋ค.
newGrid[i][j] = 1;
}
}
// ๊ทธ ์ธ์ ๊ฒฝ์ฐ (state=0, liveNeighbors!=3), ์
์ 0(์ฃฝ์ ์ํ)์ ์ ์งํฉ๋๋ค.
}
}
return newGrid;
}
/**
* ์ด์ ์
์ ์์กด ๊ฐ์๋ฅผ ์
๋๋ค. (ํ ๋ฌ์ค ๊ฒฝ๊ณ ์กฐ๊ฑด ์ ์ฉ)
*/
function countLiveNeighbors(grid, x, y) {
let sum = 0;
// ํ์ฌ ์
์ ์ฃผ๋ณ 8๊ฐ ์
์ ์ํ (-1, 0, 1)
for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
// โ ๏ธ ๊ฒฝ๊ณ ์กฐ๊ฑด ์ฒ๋ฆฌ (Toroidal Boundary - ํ ๋ฌ์ค/๋๋ ๋ชจ์)
// ๊ฒฉ์ ๋์ ๋์ด๊ฐ๋ฉด ๋ฐ๋ํธ์ผ๋ก ์ด์ด์ง๊ฒ ๊ณ์ฐํฉ๋๋ค.
let col = (x + i + cols) % cols;
let row = (y + j + rows) % rows;
// ์ด์ ์
์ ์ํ๋ฅผ ํฉ์ฐํฉ๋๋ค.
sum += grid[col][row];
}
}
// ์๊ธฐ ์์ ์ ์ด์์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก, ํฉ์ฐ์์ ์ ์ธํฉ๋๋ค.
sum -= grid[x][y];
return sum;
}
/**
* ๋น 2์ฐจ์ ๋ฐฐ์ด(๋ชจ๋ ๊ฐ 0)์ ์์ฑํฉ๋๋ค.
*/
function initializeEmptyGrid(cols, rows) {
let arr = new Array(cols);
for (let i = 0; i < cols; i++) {
arr[i] = new Array(rows).fill(0);
}
return arr;
}
CA ์๋ฎฌ๋ ์ด์ ์์ ๊ฐ์ฅ ์ค์ํ ๋ถ๋ถ์ ๋์ ์ ๋ฐ์ดํธ์ ๋๋ค.
grid: ํ์ฌ ์ธ๋์ ์ํ๋ฅผ ์ ์ฅํฉ๋๋ค.nextGrid: ํ์ฌ grid์ ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ์ธ๋์ ์
์ด ์ด์์์์ง ์ฃฝ์์ง๋ฅผ ๊ณ์ฐํ์ฌ ์์๋ก ์ ์ฅํฉ๋๋ค.๋ง์ฝ ํ๋์ ๋ฐฐ์ด๋ง ์ฌ์ฉํ๊ณ ๊ณ์ฐ๊ณผ ๋์์ ์ ๋ฐ์ดํธํ๋ฉด, ๋จผ์ ์ ๋ฐ์ดํธ๋ ์ ์ด ๋์ค์ ๊ณ์ฐ๋๋ ์ ์ ์ํฅ์ ์ฃผ์ด ๊ท์น์ด ์ค์ผ๋ฉ๋๋ค. ๋ ๊ฐ์ ๊ฒฉ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ์ ์ ์ ๋ฐ์ดํธ๊ฐ ๋์์ ์ด๋ฃจ์ด์ง๋ CA์ ๋ณธ์ง์ ์ ํํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
์ด ํจ์๋ ๋ชจ๋ ์ ์ ์ํํ๋ฉฐ ๋ค์ ๋ค ๊ฐ์ง ๊ท์น์ ์ ์ฉํฉ๋๋ค.
๊ฒฝ๊ณ ์กฐ๊ฑด (Boundary Condition): ๊ฒฉ์์ ๊ฐ์ฅ์๋ฆฌ์ ์๋ ์ ์ ์ด์์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง๊ฐ ์ค์ํฉ๋๋ค. ์ด ์์ ์์๋ ํ ๋ฌ์ค(Toroidal) ๊ฒฝ๊ณ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๊ตฌํ: ๋ฐฐ์ด ์ธ๋ฑ์ค๋ฅผ ๊ณ์ฐํ ๋ (x + i + cols) % cols ์ ๊ฐ์ด ๋ชจ๋๋ก ์ฐ์ฐ(%)์ ์ฌ์ฉํ์ฌ, ์ค๋ฅธ์ชฝ ๋์ ๋์ด๊ฐ๋ฉด ์๋์ผ๋ก ์ผ์ชฝ ๋์ผ๋ก, ์์ชฝ ๋์ ๋์ด๊ฐ๋ฉด ์๋์ชฝ ๋์ผ๋ก ์ฐ๊ฒฐ๋๋๋ก ๋ง๋ญ๋๋ค. ๋ง์น ๊ฒฉ์๊ฐ ๋๋์ฒ๋ผ ๋ฅ๊ธ๊ฒ ์ด์ด์ง ๊ฒ์ฒ๋ผ ๋์ํ์ฌ ๊ฒฝ๊ณ๋ฉด ์์ด ์์ฐ์ค๋ฌ์ด ํจํด ์ด๋์ ๊ด์ฐฐํ ์ ์์ต๋๋ค.

๊ฐ๋จํ 1์ฐจ์ ๊ท์น์ 2์ฐจ์ ํ์ฅ
์ด ์์ ๋ 1์ฐจ์ ์
๋ฃฐ๋ฌ ์คํ ๋งํ(Elementary Cellular Automata, ECA)์ ์์ด๋์ด๋ฅผ 2์ฐจ์์ผ๋ก ํ์ฅํ์ฌ ์ฌ์ฉํฉ๋๋ค. ๊ฐ ์
์ ์ค์ง ์์ ๊ณผ ๋ฐ๋ก ์์ชฝ ์ด์๋ค์ ์ํ์๋ง ์์กดํ์ฌ ๋ค์ ์ํ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ์ด๋ GOL์ฒ๋ผ 8๋ฐฉํฅ ์ด์์ ๋ณด๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๊ฐ๋จํ ๊ท์น์ด์ง๋ง, ๋ฐ๋ณต๋๋ฉด ๋งค์ฐ ๋ณต์กํ๊ณ ํฅ๋ฏธ๋ก์ด ํ๋ํ์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๋
๋๋ค.
// ====== ์ ์ญ ๋ณ์ ์ค์ ======
let grid; // ์
์ํ๋ฅผ ์ ์ฅํ 2์ฐจ์ ๋ฐฐ์ด
let cols;
let rows;
let resolution = 8; // ์
ํ๋์ ํฌ๊ธฐ (ํฝ์
)
let currentRow = 0; // ํ์ฌ ํจํด์ ๊ณ์ฐํ๊ณ ์๋ ํ
let rule = 90; // ์ฌ์ฉํ 1์ฐจ์ CA ๊ท์น ๋ฒํธ (Rule 90)
let ruleset; // ๊ท์น ๋ฒํธ์ ํด๋นํ๋ 8๋นํธ ๊ท์น ๋ฐฐ์ด
function setup() {
// ์บ๋ฒ์ค ์์ฑ ๋ฐ ๊ธฐ๋ณธ ์ค์
createCanvas(800, 800);
// ์
์ ๊ฐ์ ๊ณ์ฐ
cols = floor(width / resolution);
rows = floor(height / resolution);
// ์ด๊ธฐ ๊ฒฉ์๋ฅผ ๋ชจ๋ '์ฃฝ์ ์ํ(0)'๋ก ์ด๊ธฐํ
grid = initializeEmptyGrid(cols, rows);
// ์ด๊ธฐ ์๋ (Seed) ์ค์ : ๊ฐ์ฅ ์์ค ์ค์ ์
๋ง '์ด์์๋ ์ํ(1)'๋ก ์์
grid[floor(cols / 2)][0] = 1;
// ๊ท์น ๋ฒํธ๋ฅผ 8๋นํธ ๋ฐฐ์ด๋ก ๋ณํ
ruleset = decimalToBinaryArray(rule);
// ๋ฐฐ๊ฒฝ์ ๊ฒ์์์ผ๋ก ์ค์
background(0);
}
function draw() {
// ํ์ฌ ํ์ ๊ทธ๋ฆฝ๋๋ค.
drawRow(currentRow);
// ๋ค์ ํ์ ๊ณ์ฐํฉ๋๋ค.
if (currentRow < rows - 1) {
computeNextRow(currentRow);
currentRow++;
} else {
// ๋ชจ๋ ํ์ ๋ค ์ฑ์ฐ๋ฉด ๋ฉ์ถฅ๋๋ค.
noLoop();
console.log("ํจํด ์์ฑ์ด ์๋ฃ๋์์ต๋๋ค.");
}
}
// ====== ์ ํธ๋ฆฌํฐ ํจ์ ======
/**
* ๋น 2์ฐจ์ ๋ฐฐ์ด(๋ชจ๋ ๊ฐ 0)์ ์์ฑํฉ๋๋ค.
*/
function initializeEmptyGrid(cols, rows) {
let arr = new Array(cols);
for (let i = 0; i < cols; i++) {
arr[i] = new Array(rows).fill(0);
}
return arr;
}
/**
* ๊ท์น ๋ฒํธ (Decimal)๋ฅผ 8๋นํธ ๋ฐฐ์ด (Binary)๋ก ๋ณํํฉ๋๋ค.
* ์: Rule 90 -> [0, 1, 0, 1, 1, 0, 1, 0]
*/
function decimalToBinaryArray(decimal) {
// 10์ง์๋ฅผ 8์๋ฆฌ 2์ง์ ๋ฌธ์์ด๋ก ๋ณํํ๊ณ ๋ฐฐ์ด๋ก ๋ง๋ญ๋๋ค.
let binaryString = decimal.toString(2).padStart(8, "0");
// ๋ฐฐ์ด์ ๋ค์ง๋ ์ด์ : 1์ฐจ์ CA ๊ท์น์ ๋ณดํต ์ฐ์ธก ๋นํธ(์ธ๋ฑ์ค 0)๋ถํฐ ์ค์๋๊ฐ ๋ฎ์
// ์ปจํ
์คํธ: [111, 110, 101, 100, 011, 010, 001, 000] ์ ๋์
return Array.from(binaryString).reverse().map(Number);
}
/**
* ํ์ฌ ํ์ ์
์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ํ์ ์ํ๋ฅผ ๊ณ์ฐํฉ๋๋ค.
* ๊ท์น: ํ์ฌ ์
์ ์ํ๋ ๋ฐ๋ก ์ 3๊ฐ ์ด์ (์ผ์ชฝ ์, ์, ์ค๋ฅธ์ชฝ ์)์ ์ํด ๊ฒฐ์ ๋ฉ๋๋ค.
*/
function computeNextRow(y) {
let nextY = y + 1;
// ๊ฐ ์ด์ ์ํํ๋ฉฐ ์๋ก์ด ํ์ ์ํ๋ฅผ ๊ฒฐ์
for (let x = 1; x < cols - 1; x++) {
// 1. ์์ชฝ 3๊ฐ์ ์ด์ ์ํ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
// ๊ฒฝ๊ณ ์กฐ๊ฑด ์ฒ๋ฆฌ๋ฅผ ์ํด (x=0, x=cols-1) ์ด์ ๋ฌด์ํฉ๋๋ค.
let left = grid[x - 1][y]; // ์ผ์ชฝ ์
let center = grid[x][y]; // ๋ฐ๋ก ์
let right = grid[x + 1][y]; // ์ค๋ฅธ์ชฝ ์
// 2. 3๋นํธ ํจํด์ 10์ง์ ์ธ๋ฑ์ค๋ก ๋ณํํฉ๋๋ค.
// ์: [1, 0, 1] -> 1*2^2 + 0*2^1 + 1*2^0 = 5
let index = left * 4 + center * 2 + right * 1;
// 3. ๊ท์น ๋ฐฐ์ด(ruleset)์์ ํด๋น ์ธ๋ฑ์ค์ ๊ฐ์ ๊ฐ์ ธ์ ๋ค์ ์ํ๋ก ์ค์ ํฉ๋๋ค.
// ruleset[index]๋ 0 ๋๋ 1 (๋ค์ ์ธ๋์ ์ํ)
grid[x][nextY] = ruleset[index];
}
}
/**
* ํ์ฌ ํ์ ์
์ํ๋ฅผ ์บ๋ฒ์ค์ ๊ทธ๋ฆฝ๋๋ค.
*/
function drawRow(y) {
for (let x = 0; x < cols; x++) {
let cellState = grid[x][y];
let drawX = x * resolution;
let drawY = y * resolution;
if (cellState == 1) {
// ์์กดํ ์
(Alive): ํฐ์
fill(70, 200, 180);
noStroke();
rect(drawX, drawY, resolution, resolution);
}
// ์ฃฝ์ ์
(0): ๊ทธ๋ฆฌ์ง ์์ (๋ฐฐ๊ฒฝ์ ์ ์ง)
}
}
๐ก ์ฝ๋ ์์ธ ์ค๋ช : 1์ฐจ์ CA ๊ท์น์ 2D ์ ์ฉ
draw() ๋ฃจํ: GOL์ฒ๋ผ ์ ์ฒด ๊ฒฉ์๋ฅผ ๋์์ ๊ณ์ฐํ๋ ๋์ , ์ด ์์ ๋ draw() ํจ์๊ฐ ๋ฐ๋ณต๋ ๋๋ง๋ค ํ๋์ ํ(row)์ฉ ํจํด์ ์๋๋ก ์์ฑํด ๋๊ฐ๋๋ค.
currentRow: ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ currentRow๊ฐ 0๋ถํฐ rows-1๊น์ง ์ฆ๊ฐํ๋ฉฐ, ์ด๋ ํจํด์ด ์๊ฐ์ ํ๋ฆ์ ๋ฐ๋ผ ์์์ ์๋๋ก ์์ด๋ ๊ฒ์ ์๊ฐํํฉ๋๋ค.
์ด ํจ์๋ GOL์ computeNextGeneration๋ณด๋ค ํจ์ฌ ๋จ์ํ ๊ท์น์ ์ฌ์ฉํฉ๋๋ค.
์ด์ ์ ์: ์ค์ง ๋ฐ๋ก ์ ํ์ 3๊ฐ ์ (์ผ์ชฝ, ์ค์, ์ค๋ฅธ์ชฝ)๋ง์ ์ด์์ผ๋ก ๊ฐ์ฃผํฉ๋๋ค.
์ธ๋ฑ์ค ๋ณํ: left 4 + center 2 + right * 1 ๊ณต์์ 3๊ฐ์ 1(Alive) ๋๋ 0(Dead) ์ํ๋ฅผ 0๋ถํฐ 7๊น์ง์ ๊ณ ์ ํ 10์ง์ ์ธ๋ฑ์ค๋ก ๋ณํํฉ๋๋ค.
์ํ ๊ฒฐ์ : newGrid[x][nextY] = ruleset[index]๋ฅผ ํตํด, ํด๋น ํจํด์ ๋ฏธ๋ฆฌ ์ ์๋ ๊ท์น(0 ๋๋ 1)์ ๋ฐ๋ผ ๋ค์ ์ ์ ์ํ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
ํ๋ํ ํจํด: Rule 90์ ์คํํ๋ฉด ์์๋ฅดํ์คํค ๊ฐ์คํท๊ณผ ์ ์ฌํ ๋์นญ์ ์ด๊ณ ํ๋ํ์ ์ธ ๊ตฌ์กฐ๋ฅผ ์์ฑํฉ๋๋ค.
ํจํด ๋ค์์ฑ: let rule = 90 ๊ฐ์ ๋ค๋ฅธ ๊ท์น ๋ฒํธ(์: Rule 30, Rule 110, Rule 184)๋ก ๋ฐ๊พธ๋ฉด ์์ ํ ๋ค๋ฅธ ์๊ฐ์ ํจํด์ ๊ด์ฐฐํ ์ ์์ต๋๋ค. ํนํ Rule 110์ ํ๋ง ์์ ์ฑ(Turing Completeness)์ ๊ฐ์ง ๊ฒ์ผ๋ก ์๋ ค์ ธ ์์ด ๋ณต์ก์ฑ์ด ๋งค์ฐ ๋์ต๋๋ค.
๋ฉ๋ชจ๋ฆฌ ํจ์จ: GOL๊ณผ ๋ฌ๋ฆฌ ์ด์ ๊ณ์ฐ์ด 8๊ฐ๊ฐ ์๋ 3๊ฐ๋ก ๋จ์