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.