I use a string to avoid the inner loop. The problem here is the printf()
inside. A 3000-row triangle redirected to /dev/null
takes 50ms, but now only 4ms.
I reformatted the output. And I left dots as fillers to see what is going on.
$ ./a.out
...*...
..***..
.*****.
*******
It starts with one *
in the so-called middle, and every row-iteration only sets two more bytes to *
before it prints.
The complicated part is preparing the string i.e. array of chars. You can use calloc()
to clear the right side, but it still takes a step to put blanks on the left side.
#include <stdio.h>
#include <string.h>
int trihi = 4;
char PIX = '*';
int main(void){
int width = trihi * 2 - 1;
char s[width + 1];
memset(s, '.', width);
s[width] = '\0';
int mid = trihi - 1;
s[mid] = PIX;
printf("%s\n", s);
for (int i = 1; i < trihi; i++) {
s[mid - i] =
s[mid + i] = PIX;
printf("%s\n", s);
}
}
This should add up. s[mid + i]
runs up to 2*mid
= 2*(trihi-1)
.
The '\0' sits at width = 2*trihi - 1
which is one higher, and is the highest legal index for s
.
It is very easy to make a small mistake and not have the \0
at the correct place.
It also works with a triangle height of 1:
$ ./a.out
*
And by setting ... = --PIX;
in the loop:
$ ./a.out
.....*.....
....)*)....
...()*)(...
..'()*)('..
.&'()*)('&.
%&'()*)('&%
The So-Called Middle
This is how a triangle of height 4 is laid out. Size is 8. The middle is s[3]; there are 3 spaces to the left.
01234567 --- "offset", "index"
...*...0
| | |
| | +-- s[width] (width = 2*trihi - 1)
| +------ s[mid] (mid = trihi - 1)
+--------- s[0]
You start with trihi=4, but what you need is mostly 3 and 7...the geometrical base width is also 7.
Just any Triangle
If this is enough (with original height = 3):
$ ./a.out
*
**
***
then the code gets much simpler:
#include <stdio.h>
#include <stdlib.h>
int trihi = 3;
char PIX = '*';
int main(void){
char *s = calloc(trihi+1, 1);
for (int i = 0; i < trihi; i++) {
s[i] = PIX;
printf("%s\n", s);
}
}
I kicked everything out except the basic idea: re-using a prepared string/array. Here the calloc-zeroes are only after the PIXes. No need for a filler like space or dots via memset() anymore. But it is also not the same user experience...and the triangle is half the size.
Overiq.com has a double-loop version of a C Program to print Half Pyramid pattern using *. It takes much longer than the above (tri2.c below).
$ gcc -O2 over.c
$ time ./a.out |wc -l
3001
real 0m0.029s
user 0m0.020s
sys 0m0.014s
$ gcc -O2 tri2.c
$ time ./a.out |wc -l
3000
real 0m0.006s
user 0m0.000s
sys 0m0.011s