CA Ribbon Project


I was eager to write my own program for generating a cellular automaton by the time that I learned imperative programming, having enthusiastically read Stephen Wolfram's A New Kind Of Science in High School. In the middle of the semester, and before I had even learned the basics of classes and objects within the COP 2931 Programming I course using C++, I initiated my own personal project to create that program. Just as the Hello World program is the archetypical first program for every programmer, the Rule 30 cellular automata was the obvious choice when deciding which rule set to implement.

For the sake of preventing overflow within the Xcode Debug area when outputting many iterations, I fixed the width of the resulting 'ribbon' to 25 characters and set the loop calculating the next line to retrieve cell values from the given line as if the line was unbounded (the value at index 0 was retrieved following the value at index 24 of the same line). This modification prevented the occurrence of 'border interactions' which would have almost assuredly contaminated the resulting data. However, in making this modification the automaton was prevented from experiencing the unrestricted growth that would have resulted in the usual Rule 30 output. The new consequence of this configuration is that the once predictable edges of expansion now collide with each other resulting in an inevitable end in growth, but a continuation in automaton development with each iteration.

Example Output


Input a string of 1s and 0s, 25 digits long, to construct first line.
1 for black, 0 white.
0000000000001000000000000

Input how many iterations are sought: 50

            O
           OOO
          OO  O
         OO OOOO
        OO  O   O
       OO OOOO OOO
      OO  O    O  O
     OO OOOO  OOOOOO
    OO  O   OOO     O
   OO OOOO OO  O   OOO
  OO  O    O OOOO OO  O
 OO OOOO  OO O    O OOOO
OO  O   OOO  OO  OO O   O
  OOOO OO  OOO OOO  OO OO
OOO    O OOO   O  OOO  O
O  O  OO O  O OOOOO  OOO
OOOOOOO  OOOO O    OOO
O      OOO    OO  OO  O O
 O    OO  O  OO OOO OOO O
 OO  OO OOOOOO  O   O   O
 O OOO  O     OOOO OOO OO
 O O  OOOO   OO    O   O
OO OOOO   O OO O  OOO OOO
   O   O OO O  OOOO   O
  OOO OO O  OOOO   O OOO
 OO   O  OOOO   O OO O  O
 O O OOOOO   O OO O  OOOO
 O O O    O OO O  OOOO
OO O OO  OO O  OOOO   O
O  O O OOO  OOOO   O OOOO
 OOO O O  OOO   O OO O
OO   O OOOO  O OO O  OO
O O OO O   OOO O  OOOO OO
  O O  OO OO   OOOO    O
 OO OOOO  O O OO   O  OOO
 O  O   OOO O O O OOOOO
OOOOOO OO   O O O O    O
O      O O OO O O OO  OO
OO    OO O O  O O O OOO
O O  OO  O OOOO O O O  OO
  OOOO OOO O    O O OOOO
 OO    O   OO  OO O O   O
 O O  OOO OO OOO  O OO OO
 O OOOO   O  O  OOO O  O
OO O   O OOOOOOOO   OOOOO
   OO OO O       O OO
  OO  O  OO     OO O O
 OO OOOOOO O   OO  O OO
OO  O      OO OO OOO O O
O OOOO    OO  O  O   O O 


main.cpp


//  main.cpp
//  CA Ribbon
//
//  Created by Julien Kuzniarek on 10/21/13.
//
// Elementary cellular automaton, ribbon, unbounded, rule 30

#include <cstdlib>
#include <iostream>
#include <string>

// black = true = 1;
// white = false = 0;
using namespace std;

bool rule30(bool, bool, bool );
bool setcell();
void printcell(bool);

int main()
{
#define linelength 25
    string firstline = "";
	bool repcheck[linelength] = {0};
    unsigned long ribbonwidth = 0;
    int ribbonlength = 0;

	//input starting line
    cout << "Input a string of 1s and 0s, " << linelength << " digits long,";
    cout << " to construct first line." << endl << "1 for black, 0 white. " << endl;
    cin >> firstline;
    ribbonwidth = firstline.length();
    bool line [linelength] = {0};
    bool nextline [linelength] = {0};
    for (int count = 0; count < ribbonwidth; count++)
    {
        if (firstline[count] == '1')
        {
            line[count] = true;
        }
        if (firstline[count] == '0')
        {
            line[count] = false;
        }
    }
	//main loop
    cout << endl << "Input how many iterations are sought: ";
    cin >> ribbonlength;
    cout << endl;
    for (int count1 = 0; count1 < ribbonlength; count1++)
    {
        //calculate next line from line
        nextline[0] = rule30(line[ribbonwidth-1], line[0], line[1]);
        for(int num = 1; num < ribbonwidth; num++)
        {
            nextline[num] = rule30(line[num-1], line[num], line[num+1]);
        }
        nextline[ribbonwidth-1] = rule30(line[ribbonwidth-2], line[ribbonwidth-1], line[0]);

        //print cells then update line with values from next line
        for (int count2 = 0; count2 < ribbonwidth; count2++)
        {
            printcell(line[count2]);
            line[count2] = nextline[count2];
		}
        cout << endl;
		for (int count = 0; (count < linelength); count++)
		{
			if (line[count] == repcheck[count] and count == linelength)
			{
				ribbonlength = count1;
			}
			else
			{
				count = linelength;
			}
		}
    }
}
void printcell(bool cell)
{
	if (cell == true)
	{
		cout << "O";
	}
	if (cell == false)
	{
		cout << " ";
	}
}

//define rule30 function
bool rule30( bool cellL, bool cellC, bool cellR )
{
    bool returnvalue = true;
    //true = black
    //false = white
    if (cellL == true and cellC == true and cellR == true)
    {
        returnvalue = false;
    }
    if (cellL == true and cellC == true and cellR == false)
    {
		returnvalue = false;
    }
    if (cellL == true and cellC == false and cellR == true)
    {
		returnvalue = false;
    }
    if (cellL == true and cellC == false and cellR == false)
    {
		returnvalue = true;
    }
    if (cellL == false and cellC == true and cellR == true)
    {
		returnvalue = true;
    }
    if (cellL == false and cellC == true and cellR == false)
    {
		returnvalue = true;
    }
    if (cellL == false and cellC == false and cellR == true)
    {
		returnvalue = true;
    }
    if (cellL == false and cellC == false and cellR == false)
    {
		returnvalue = false;
    }
    return returnvalue;
}