# Matrix falling effect

How can I make this matrix effect more like the matrix movie?

#include<stdlib.h>
#include<stdio.h>
int main()
{
srand((unsigned) time(0));
int i,j;
system("color 0a");

while(1)
{
i = rand() % 2;
j= rand() % 2;
if(j)
{
printf("%d ", i);
}
else
{
printf(" %d", i);
}

}
return 0;
}


Here is how it looks like:

Of course it is better if it was moving but that's all what I can show.

Also it takes a notable time to compile, is there anything wrong I'm doing?

• How is it not like the movie... what are you trying to do? – Hogan Apr 5 '14 at 15:18
• nb - a google search of "matrix animation javascript" will turn up a number of good examples in javascript. The key is to index the display to place the character at a given x, y to achieve the "rain" effect. – Hogan Apr 5 '14 at 16:53

## What You Have Now:

You code is simple and concise. That in and of itself can be a desirable quality. I think we can make the code a little bit more concise while gaining some runtime efficiency.

Some changes I would make:

Change srand((unsigned) time(0)); to srand(time(NULL));

• While both are correct, this is how I have seen seeds set more often, hence it is the idiomatic approach

Change return 0 to return EXIT_SUCCESS

• Exit codes are included in stdlib, since you already using that library, you should also use the provided exit codes.

Change rand()%2 to rand()&1

• The modulo operator (%) can be very inefficient on some architectures. Since you are only using rand() to get binary values, we can much more efficiently use the bitwise and operator (&) to get a 1 if the number is odd and a 0 if the number is even.

Change your while loop to remove intermediate variables:

while(1) {
if(rand() & 1)
printf("%d ", rand() & 1);
else
printf(" %d", rand() & 1);
}


All together I think you could simplify your code to this:

#include<stdlib.h>
#include<stdio.h>
int main() {
srand(time(NULL));
system("color 0a");

while(1) {
if(rand() & 1)
printf("%d ", rand() & 1);
else
printf(" %d", rand() & 1);
}

return EXIT_SUCCESS;
}


This is a pretty small and eloquent code for generating a matrix style output. If your happy with this you can stop right here.

However, it should be pointed out that printf is a little heavy handed for just printing spaces, ones, and zeros. You could utilize putchar which will, unsurprisingly, put a character to STDOUT.

while(1) {
if(rand() & 1) {
putchar(48 + (rand()&1))
putchar(' ');
}
else {
putchar(' ')
putchar(48 + (rand()&1));
}
}


Note that now we have a Magic Number 48 in out code, that is no good! Let's let the preprocessor help us make the code a little bit more readable:

#define ASCII_NUMBER_OFFSET 48
while(1) {
if(rand() & 1) {
putchar(ASCII_NUMBER_OFFSET + (rand()&1));
putchar(' ');
}
else {
putchar(' ');
putchar(ASCII_NUMBER_OFFSET + (rand()&1));
}
}


Next is a matter of personal preference. I personally don't like 2 line if statements. If the if statement has 3 lines, it should probably be abstracted into a separate method, if it has one line, that’s perfect, but if we have 2 lines... that's murky water.

We could use the comma operator to clean up the line a little:

#define ASCII_NUMBER_OFFSET 48
while(1) {
if(rand() & 1)
putchar(ASCII_NUMBER_OFFSET + (rand()&2)), putchar(' ');
else
putchar(' '), putchar(ASCII_NUMBER_OFFSET + (rand()&1));
}


Using the comma operator is a matter of preference. I think that there are times that it is perfectly clear & reasonable to use it, others say the comma operator should never be used because it is too opaque. While that code is more compact, I don't think it helps readability or efficiency.

Lets try abstraction that into a method instead and see how that looks:

while(1) {
if(rand() & 1)
printLeft();
else
printRight();
}
.
.
.
#define ASCII_NUMBER_OFFSET 48
void printLeft() {
putchar(' ');
putchar(ASCII_NUMBER_OFFSET + (rand()&1));
}

void printRight() {
putchar(ASCII_NUMBER_OFFSET + (rand()&1));
putchar(' ');
}


That makes the while loop look better but the methods might incur some performance cost. Since your tag Optimization implies that you care most about runtime efficiency and not readability/maintainability lets try something else.

You will notice in your all the code examples above, there is some repetition in the while loop. In all the cases we have 2 statements printing the one or zero. Repetition is often a good thing to focus on because it can alert you to things that can be improved. There is a mantra of Don't Repeat Yourself (DRY) in programming which is designed to help programmers locate inefficiencies and refactor their code for better readability & efficency.

Consider this loop:

int b;
while(1) {
if(b = rand() & 1)
putchar(' ');
putchar(ASCII_NUMBER_OFFSET + (rand() & 1));
if(!b)
putchar(' ');
}


Here we have a single binary number printing statement but conditionally print a space before or after the number. From a runtime efficiency perspective this is probably optimal (though I have not done any benchmarking).

If we put this all together we have the following:

#include<stdlib.h>
#include<stdio.h>
#define ASCII_NUMBER_OFFSET 48

int main() {
int b;
srand(time(NULL));
system("color 0a");

while(1) {
if(b = (rand() & 1))
putchar(' ');
putchar(ASCII_NUMBER_OFFSET + (rand() & 1));
if(!b)
putchar(' ');
}

return EXIT_SUCCESS;
}


I hope this has given you a lot of different angles to view you code from and given you the tools to decide what you value when improving this code, readability or runtime efficiency.

• good call, I forgot about that... – recursion.ninja Apr 5 '14 at 16:52
• "Change return 0 to return EXIT_SUCCESS" - Just get rid of the return completely, thanks to C99 & C11 §5.1.2.2(3); your parameters should be declared as void, if you don't take anything in (for example: main(void)); you should always initialize your variable on creation; and if you only have one statement in a test conditional, you should mimic this style to prevent bugs. – syb0rg Apr 5 '14 at 21:07
• Also, you should make a note to not use system(), and instead use ANSI escape codes. All modern terminals implement them, and they will speed up the code. And you forgot to #include <time.h> when you used time(). – syb0rg Apr 5 '14 at 21:23

If you are talking optimization (not sure you are) then one clear change is to remove printf -- printf is very slow. You are only displaying 0, 1, and .

putc is much faster -- it does not have to parse for formatting. If you change the code to use putc instead of printf you should see a dramatic speed boost.

• You're wrong. I mean, there is no need to turn print into putchar. Indeed, the compiler will do that automatically if needed, even with no optimization flag turned on. Checked on gcc. – edmz Apr 5 '14 at 16:57
• @no1 - The printf (not print) optimization only happens for string literals, %s and %c. None of which is true for this example which is a %d. This is why awashburn's answer requires the ASCII_NUMBER_OFFSET define. I'm not wrong, you are. More info: ciselant.de/projects/gcc_printf/gcc_printf.html – Hogan Apr 6 '14 at 3:43
• There is no need to use that ugly macro, since you can directly 1) convert to char 2) add 0x30 - '0'. Hence, either you call printf("%c", n) or putchar(n + 0x30) will be equivalent. Good to point out, though. – edmz Apr 6 '14 at 10:00