Show Case


Generation Generator

Introduction

This was one of the first projects that I did, this is through the CS50 course. The project is called inheritance. The purpose of this project was to learn the fundamentals of the C language, memory allocation, pointers, and objects. The end goal was to print out three generations of blood types that were randomly inherited from the parents blood type.

Inheritance

In the beginning there was life, and then it multiplied.

Generation 0, blood type BB
    Generation 1, blood type AB
        Generation 2, blood type BA
        Generation 2, blood type AB
    Generation 1, blood type BO
        Generation 2, blood type BA
        Generation 2, blood type AO
                        
Inhertance Results

And now for the mess that created the output.
It starts by defining what a person is, that is they have two parents and two alleles.

Prepare objects and functions
Preperation

Next the number of GENERATIONS that will be created is defined, and an INDENT_LENGTH is defined that will be used to seperate the family members as they are printed to the console. This section finishes by defining the functions.

int main(void)

The main function lays out a clear process of operation, create, print, free. Simple enough.

main function
Main Function

person *create_family(int generations)

Create Family function
Create Family

create_family(int generations) takes in an in integer which in theory will determine the number of generation to output. Apparently I didnt take this into consideration at the time so here is the current state.

Tower Picture
Creating Ancestors Part 1
Tower Blurred Picture
Creating Ancestors Part 2

It simply checks that there is more than one generation to create then goes ahead and creates the parents (k for loop, person *p being the parents) and the grandparent (i for loop, with person *pa being each grandparent) of the person.
Here is where the assignment of the alleles is done. Each grandparent is given two random alleles. This is done through the j for loop. Once the grandparents have the alleles this will determine the parents alleles by the rand() % 2 which will get either 0 or 1. The allele at the random index is assigned to the parent.
Finally the parents are assigned to the person *c, and the current person is give random alleles from the parents.

I'm going to do a quick rework on this section.
Jump to Rework

print_family(person *p, int generation)

This function is also recursive.

Print Family function
Print Family Function

The first if statement handles the last generations non-existent parent. It then applies the appropriate indentation for the generation.
Finally it prints the current generation and calls the next parent to be printed.

free_family()

Once again I did not do this very cleanly, in fact it is almost sad how shabby this function looks. I will let you be the final judge though.

Start of free_family()
Free Family start

This function starts off by creating a list of the full ancestor list of the person *p. The int i tracks the current generation being freed. The while loop will then take in p only if it is not already NULL.

Now for the mess...

while of free_family()
Free Family While Loop

tmp and tmp1 are assigned to the parents of person *p This next part gets very muddy. p->parents[1] is assigned to ancestors. Next we check if the address of list[i] is equal to p, if it is p is set to NULL otherwise p is freed. This then allows for the next p->parents[0] to be assigned to p.
The following if statement checks if it is the last generation. If it is, all of the grandparents of the origonal person that was passed in along with the parents. If its the first generation the function ends, otherwise it goes back a generation and goes through the function again.
If it is not the last generation, p->parent[1] is put into the list. These people in the list will be brought into the function as the p->parent[0] are freed.
I will also clean this one up.
Jump to Rework

Some Cleanup

I couldnt handle leaving this in this state considering its going on display so I went through and ironed out the ameteurish and confusing mistakes made. I will run through the major changes.

Create family Function V2
Reworked create_family()
New Functions
New Reworked Functions

I wont spend much time on this but this new method takes advantage of recursion. By utilizing the call stack I am able to create generations to any number. I made the operation two seperate functions where the first simply makes sure there is more than one generation to create and the second creates all of the people in the family. I also broke out the process of creating the final generation to create_last_generation(), and the assignment of alleles to inherit_allele(). This was for easier readability, the biggest problem I had with the first implementation, well first of all it didnt even work properly, but also it was crambed up with for loops which made it hard to follow.

New free_family() Function
Free Family Reworked

I am happy with this one, it reads from top to bottom and does what it should do clear and simple. I think the output from the print statements will show quite clearly how it works but heres a brief explanation.
Check for NULL, Check if parents are NULL, free and return if so, if not store parents, free p call function with parents.

FINAL OUTPUT

    Generation 0, blood type AO
        Generation 1, blood type AA
            Generation 2, blood type AB
                Generation 3, blood type AB
                    Generation 4, blood type BA
                    Generation 4, blood type AB
                Generation 3, blood type BO
                    Generation 4, blood type BB
                    Generation 4, blood type AO
            Generation 2, blood type AA
                Generation 3, blood type AB
                    Generation 4, blood type AB
                    Generation 4, blood type OB
                Generation 3, blood type AA
                    Generation 4, blood type BA
                    Generation 4, blood type BA
        Generation 1, blood type BO
            Generation 2, blood type BO
                Generation 3, blood type OB
                    Generation 4, blood type OO
                    Generation 4, blood type BB
                Generation 3, blood type OO
                    Generation 4, blood type OB
                    Generation 4, blood type OA
            Generation 2, blood type OA
                Generation 3, blood type OB
                    Generation 4, blood type OA
                    Generation 4, blood type BB
                Generation 3, blood type AA
                    Generation 4, blood type AA
                    Generation 4, blood type OA
    freed: AO of generation: 0
    freed: AA of generation: 1
    freed: AB of generation: 2
    freed: AB of generation: 3
    freed: BA of generation: 4
    freed: AB of generation: 4
    freed: BO of generation: 3
    freed: BB of generation: 4
    freed: AO of generation: 4
    freed: AA of generation: 2
    freed: AB of generation: 3
    freed: AB of generation: 4
    freed: OB of generation: 4
    freed: AA of generation: 3
    freed: BA of generation: 4
    freed: BA of generation: 4
    freed: BO of generation: 1
    freed: BO of generation: 2
    freed: OB of generation: 3
    freed: OO of generation: 4
    freed: BB of generation: 4
    freed: OO of generation: 3
    freed: OB of generation: 4
    freed: OA of generation: 4
    freed: OA of generation: 2
    freed: OB of generation: 3
    freed: OA of generation: 4
    freed: BB of generation: 4
    freed: AA of generation: 3
    freed: AA of generation: 4
    freed: OA of generation: 4
                        
Free Family Reworked
For full Code Click here.