To homepage
So, this is my first real project uploaded here, so there we go!
A while ago, i watched Daniel's video on "elementary celular automatons" (here), and i wanted to do such thing myself. At the time, i used a raspberry pi 4b as my main computer and i started writing it in python. One of python inherent problems is, that it is incredibly slow. (OK, not that slow, but you get the point) And so i thought i'd do a rewrite in C, because it was one of the few other languees that i was at least somewhat familiar with at the time, and so i did!
However, it now turns out, i cannot find it anywhere, and it looks like the file is corrupted.
So i figured, LET'S DO ANOTHER REWRITE, this time the proper way! Sort of. So i did!
Now, beware, it doesn't have properly sanitized input, but what's the chance of it being used by anyone, let alone in a more serious environment.
I first quiclky threw together something that sort of worked but it was really buggy and soon i decided to ditch the memcpy, because i didn't have any idea how to use it.
Here's how that went:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool isAlive(bool cell_1_state, bool cell_2_state, bool cell_3_state, int rule) {
// transformation of the rule to binary form
bool rule_binary[8];
for (int i = 0; i < 8; i++) {
rule_binary[i] = rule % 2;
rule /= 2;
}
// the actual rule check
int count = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
if (cell_1_state == i && cell_2_state == j && cell_3_state == k) {
return(rule_binary[count]);
}
count ++;
}
}
}
}
int main() {
// size input and handling
long long size;
printf("Please input an array size (may the number be even, 1 will be added.): ");
scanf("%lli", &size);
if (size < 0) {
printf("Size cannot be negative, quitting.\n");
return(1);
}
if (size % 2 == 0) {
size++;
}
// rule input and handling
int rule;
printf("Please input the rule number (0-255, inclusive): ");
scanf("%d", &rule);
if (rule < 0 || rule > 255) {
printf("Invalid rule size, quitting.\n");
return(1);
}
// steps number input and handling
long long steps;
printf("Please input the desired number of steps to simulate: ");
scanf("%lli", & steps);
if (steps <= 0) {
printf("Size must be greater than 0, quitting.\n");
return(1);
}
// dynamic memory allocation and inicialisation of rows of cells
bool* row = (bool*)calloc(size * sizeof(bool), sizeof(bool));
bool* row_next = (bool*)malloc(size * sizeof(bool));
if (row == NULL || row_next == NULL) {
printf("Memory allocation failed, quitting.\n");
return(-1);
}
row [size / 2] = 1;
// the main loop
for (long long step = 0; step < steps; step++) {
for (long long i = 0; i < size; i++) {
if (row[i]) {
printf("#");
}
else {
printf(" ");
}
if (i == 0) {
row_next[i] = isAlive(row[size-1], row[i], row[i+1], rule);
}
else if (i == size -1) {
row_next[i] = isAlive(row[i-1], row[i], row[0], rule);
}
else {
row_next[i] = isAlive(row[i-1], row[i], row[i+1], rule);
}
}
for (long long i = 0; i < size; i++) {
row[i] = row_next[i];
}
printf("\n");
}
// graceful end
free(row);
free(row_next);
return(0);
}
And this worked well enough! It was working and it was one of the least ugly pieces of code i've written so far.
But the problem i had with it, even though it was plenty fast, was that i felt the copying of the values could be done way more efficiently.
And so i did another rewrite, this time based on the previous code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool isAlive(bool cell_1_state, bool cell_2_state, bool cell_3_state, int rule) {
// transformation of the rule to binary form
bool rule_binary[8];
for (int i = 0; i < 8; i++) {
rule_binary[i] = rule % 2;
rule /= 2;
}
// the actual rule check
int count = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
if (cell_1_state == i && cell_2_state == j && cell_3_state == k) {
return(rule_binary[count]);
}
count ++;
}
}
}
}
int main() {
// input of row size (length) and handling of wrong input
long long size;
printf("Please input an array size (may the number be even, 1 will be added.): ");
scanf("%lli", &size);
if (size < 0) {
printf("Size cannot be negative, quitting.\n");
return(1);
}
if (size % 2 == 0) {
size++;
}
// input of role number and handling of wrong input
int rule;
printf("Please input the rule number (0-255, inclusive): ");
scanf("%d", &rule);
if (rule < 0 || rule > 255) {
printf("Invalid rule size, quitting.\n");
return(1);
}
// input of number of steps and handling of wrong input
long long steps;
printf("Please input the desired number of steps to simulate: ");
scanf("%lli", & steps);
if (steps <= 0) {
printf("Size must be greater than 0, quitting.\n");
return(1);
}
// dynamic memory allocation and inicialisation of rows of cells
bool* row = (bool*)calloc(size * sizeof(bool), sizeof(bool));
bool* row_next = (bool*)malloc(size * sizeof(bool));
if (row == NULL || row_next == NULL) {
printf("Memory allocation failed, quitting.\n");
return(-1);
}
row [size / 2] = 1;
// the main loop
for (long long step = 0; step < steps; step++) {
for (long long i = 0; i < size; i++) {
if (row[i]) {
printf("#");
}
else {
printf(" ");
}
if (i == 0) {
row_next[i] = isAlive(row[size-1], row[i], row[i+1], rule);
}
else if (i == size -1) {
row_next[i] = isAlive(row[i-1], row[i], row[0], rule);
}
else {
row_next[i] = isAlive(row[i-1], row[i], row[i+1], rule);
}
}
memcpy(row, row_next, size * sizeof(bool));
printf("\n");
}
// graceful end
free(row);
free(row_next);
return(0);
}
These are very easy to compile - cc automaton-v1.c -o automaton
Also very easy to run - just type ./automaton in terminal.
And in case anyone wanted, i also compiled a static binary for i486 linux here and also a binary for (some?) Windows here, though it needs Microsoft Visual Studio C/C++ to run. Or maybe MinGW, because it was compiled with it? Idk.
You can test it and leave me a message in the guestbook i guess.