Skip to content

Instantly share code, notes, and snippets.

@markjgap
Last active August 29, 2015 14:10
Show Gist options
  • Save markjgap/0007ed6319c21c8983c2 to your computer and use it in GitHub Desktop.
Save markjgap/0007ed6319c21c8983c2 to your computer and use it in GitHub Desktop.
Written in C, program is an example of discrete event simulation, where a world of entities live, die, or are born based on their surrounding neighbors. Each time step simulates another round of living or dying.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
/*
* An example of discrete event simulation, where a world of entities live, die, or are born based on their surrounding neighbors.
* Each time step simulates another round of living or dying. This cellular automation can take any initial configuration and
* be observed as it evolves through its life creating unique patterns.
*/
///////////////// Forward Declarations /////////////////
int *init_board(int rows, int columns);
int getPos(int x, int y, int columns);
void printBoard(int *board, int rows, int columns, int step);
int *tick(int *board, int rows, int columns);
int countNeighbors(int *board, int rows, int columns, int x, int y);
/////////////// Main ///////////////
int main(int argc, char *argv[]) {
struct timeval start_time; // holds beginning time
struct timeval end_time; // holds completion time
// checks command line input contains 3 arguments
// If not 3, prints a usage message
if(argc != 3){
printf("Usage: %s <file> <num>\n", argv[0]);
printf(" Note: <num> = 1 or 0\n");
printf("Example:\n");
printf(" linux> %s file.txt 0\n", argv[0]);
printf(" linux> %s file.txt 1\n", argv[0]);
exit(1);
}
char *filename = argv[1]; // saves string of text file passed into gol
FILE *file = fopen(filename, "r"); // opens and read text file
if(file == NULL) {
printf("%s: File open failed.\n", argv[1]);
exit(1);
}
int arg_input = strtol(argv[2], NULL, 10); // converts string into int
// verifies only 1 or 0 is inputted
// 1 enables gol board print
// 0 disables gol board print
if (arg_input != 0 && arg_input != 1){
printf("Usage: %s <file> <num>\n", argv[0]);
printf(" Note: <num> = 1 or 0\n");
printf("Example:\n");
printf(" linux> %s file.txt 0\n", argv[0]);
printf(" linux> %s file.txt 1\n", argv[0]);
exit(1);
}
// board initialization
int rows, columns, step, x, y;
int ret = fscanf(file, "%d", &rows); // first line in file is row size
ret = fscanf(file, "%d", &columns); // second line in file is column size
ret = fscanf(file, "%d", &step); // third line in file is number of iterations
int *board = init_board(rows, columns);
int pairs = 0;
ret = fscanf(file, "%d", &pairs); // fouth line is total of live cells to start
while(ret != -1) {
ret = fscanf(file, "%d %d", &y, &x);
board[getPos(x,y,columns)] = 1;
}
fclose(file);
int i = 0;
// begin timer
ret = gettimeofday(&start_time, NULL);
while(i <= step) {
// prints board if it is enabled. argv[2] = 1
if(arg_input == 1){
printBoard(board, rows, columns, i);
}
board = tick(board, rows, columns);
i++;
}
// end timer
ret = gettimeofday(&end_time, NULL);
// calculates the time difference from start to end.
struct timeval diff;
diff.tv_sec = end_time.tv_sec - start_time.tv_sec;
diff.tv_usec = end_time.tv_usec - start_time.tv_usec;
double seconds = (double)diff.tv_sec;
double micro = (double)diff.tv_usec;
micro /= 1000000.0;
printf("Total time for %d iterations of %dx%d world is %f secs\n\n"
, step, rows, columns,seconds+micro);
free(board);
return 0;
}
/////////////// Functions ////////////////
/*
* Function initializes board with 0 (non-live cells)
* @param rows - number of rows on board
* @param columns - number of columns to print
* @return - 0 at specified coordinates
*/
int *init_board(int rows, int columns) {
int *board = malloc(sizeof(int)*rows*columns);
if(board == NULL) {
printf("Malloc failed. Exiting.");
exit(1);
}
int i;
for(i = 0; i < rows*columns; i++) {
board[i] = 0;
}
return board;
}
/*
* Function updates board
* @param board - pointer to board
* @param rows - row size
* @param columns - column size
* @return - updated board
*/
int *tick(int *board, int rows, int columns) {
// allocates space for new board
int *temp = malloc(sizeof(int)*rows*columns);
if(temp == NULL) {
printf("Malloc failed. Exiting.");
exit(1);
}
int x, y, count;
for(y = 0; y < rows; y++) {
for(x = 0; x < columns; x++) {
count = countNeighbors(board, rows, columns, x, y);
if(board[getPos(x,y,columns)] == 1) {
if(count < 2 || count > 3) temp[getPos(x,y,columns)] = 0;
else temp[getPos(x,y,columns)] = 1;
}
else {
if(count == 3) temp[getPos(x,y,columns)] = 1;
else temp[getPos(x,y,columns)] = 0;
}
}
}
free(board); // frees old board memory
return temp;
}
/*
* Function counts live cells around a particular center cell
* @param board - pointer to board
* @param rows - row size
* @param column column size
* @param x - x coordinate of center cell
* @param y - y coordinate of center cell
* @return - number of live cells around center cell.
*/
int countNeighbors(int *board, int rows, int columns, int x, int y) {
int count = 0;
int n1, n2, n3, n4, n5, n6, n7, n8; // the surrounding cells
int l = x-1;
int r = x+1;
int u = y-1;
int d = y+1;
if(l < 0) l = columns-1;
if(r >= columns) r = 0;
if(u < 0) u = rows-1;
if(d >= rows) d = 0;
n1 = getPos(l, u, columns); // top left corner cell
n2 = getPos(x, u, columns); // top cell
n3 = getPos(r, u, columns); // top right corner cell
n4 = getPos(l, y, columns); // left cell
n5 = getPos(r, y, columns); // right cell
n6 = getPos(l, d, columns); // bottom left corner cell
n7 = getPos(x, d, columns); // bottom cell
n8 = getPos(r, d, columns); // bottom right corner cell
// total number of live cells around center cell
count = board[n1] + board[n2] + board[n3] + board[n4] + board[n5] +
board[n6] + board[n7] + board[n8];
return count;
}
/*
* Function prints board status with '@' representing live cells
* and '-' represents non-live cells.
* @param board - pointer to current board
* @param rows - row size
* @param column - column size
* @param step - number of iterations to do
*/
void printBoard(int *board, int rows, int columns, int step) {
system("clear"); // helps keep the print out in a consistant location
printf("Time Step: %d\n", step);
int x, y;
int count;
for(y = 0; y < rows; y++) {
for(x = 0; x < columns; x++) {
count = countNeighbors(board, rows, columns, x, y);
if(board[getPos(x,y,columns)] == 0) printf("- ");
else printf("@ ");
}
printf("\n");
}
usleep(200000); // pauses program for .2 seconds to view board changes
}
/*
* Function takes coordinates of a 2D array and converts to an index of a 1D array
* @param x - column number of cell
* @param y - row number of cell
* @param columns - column size
* @return - equivalent index position in a 1D array.
*/
int getPos(int x, int y, int columns) {
return (columns*y)+x;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment