Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Please I need help with this project, it needs to be written in a C programming language. Task Cellular automata have a long history in

Please I need help with this project, it needs to be written in a C programming language.

Task

Cellular automata have a long history in mathematics and computer science and were first discovered in the 1940s by John von Neumann and Stanislaw Ulam, two of the founding fathers of computer science. Since then they have found many applications in diverse field including artificial life, physics and biology. While simple to describe and implement, they are capable of generating amazingly complex behaviour, including chaotic dynamics and universal computation.

For this task you will implement the simplest type of cellular automaton - an elementary cellular automaton. You should first read this chapter, which will give you a good introduction to what an elementary cellular automaton is (you only need to read up to and not including Section 7.6). It also provides some example code. You should not copy this code directly, but use it to help you understand how to implement your own program.

Your program when run should take three values from the user as command line arguments. These values are:

  1. the number of cells in the one-dimensional grid (a positive integer)
  2. the number of generations to evolve and output the cellular automata for (a positive integer)
  3. the Wolfram code specifying which the rule set to evolve your cellular automata with (an integer in the range [0,255]).

These three arguments should be specified in this order on the command line when the user runs your program. You should check that the arguments are all valid and within the ranges given. If the user enters the wrong number of arguments or invalid arguments e.g. the number of cells as -10, then your program should print an error message and exit with a non-zero exit value.

For the values specified by the user, your program should calculate and print each generation of the cellular automata on a newline. You should print a * (asterisk) character to show a cell is alive, and a (space) character to show a cell is dead. For the initial generation, you should start with a row of cells that are all dead, except for the centre cell (or left of centre cell for an even number of cells) which is alive. You should assume that your row wraps around, that is, the neighbour of the left-most cell is the right-most cell and vice versa.

For example, the output when the users run your program with 30 cells for 20 generations with rule 110 should be:

$ ./task1 30 20 110 * ** *** ** * ***** ** * *** ** ** * *** ******* * ** *** *** ** * ** * ***** ***** ** * ** * *** ** *** **** * *** ** * ** ***** * ******* ** *** * **** ** * ** ** * ***** *** *** **** * ** *

You are free to choose whichever method you want to implement your program with the following restrictions:

  • your implementation must contain a correctly declared main function
  • you are not allowed to use global variables

Some hints for possible ways to implement your program are given below.

You could store the states of cells in the current and next generations in two arrays. The length of each array will be the number of cells specified by the user. Since this length is specified at runtime, you will need to allocate the memory for these arrays dynamically using malloc or calloc.

The main computation in your program could be performed by two nested loops. The outer loop would iterate over each generation. For each generation, an inner loop would iterate over all the cells in the current generation array. Based on the state in the current generation of each cell and its two neighbours, you can calculate the state in the next generation and store this in the next generation array. After calculating the next generation states for all cells in the current generation, you can then print out the next generation. Finally you can copy the next generation array to the current generation array, and perform the whole procedure again for the next generation.

To calculate the state of a cell in the next generation from it and its neighbours current state, you can use some simple binary manipulation. For example, say you were using the ruleset with Wolfram code 110 and you wanted to calculate the state in the next generation of a dead cell with two live neighbours i.e. 101. First, treat 101 as a binary number and convert it to decimal i.e. 5. Now right shift the rule number i.e. 110 by 5 and look at the value of the least significant bit i.e. 0. This is the state of the cell in the next generation. A complete set of pictures for each Wolfram code is given here. Rule 90 and Rule 110 are particular interesting.

Your program should handle dynamically allocated memory correctly i.e. free all dynamically allocated memory. As discussed in lectures, a good tool for assessing if a program has handled dynamic memory allocation correctly is valgrind. To check your program using valgrind you can type:

$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./task1

If your program has correctly handled dynamic memory allocation, the last line of output should read:

ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Financial management theory and practice

Authors: Eugene F. Brigham and Michael C. Ehrhardt

12th Edition

978-0030243998, 30243998, 324422695, 978-0324422696

Students also viewed these Programming questions

Question

Describe the purpose of conducting a factor analysis.

Answered: 1 week ago