/*
* Calculate and display Pascal's triangle.
*
* Copyright (C) 2005 George Gesslein II.
*/
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <termios.h>
#define true 1
#define false 0
#define MAX_LINES 100 /* max number of lines of Pascal's triangle allowed */
void calculate_triangle(void);
void display_triangle(void);
int center_buf(int line_number, int cell_size);
void usage(void);
int lines = 26;
int cell_size = 6;
long double *array[MAX_LINES];
int screen_columns = 80;
int centered = true;
char line_buf[1000];
char *prog_name = "matho-pascal";
int
main(int argc, char *argv[])
{
int i;
struct winsize ws;
prog_name = strdup(basename(argv[0]));
ws.ws_col = 0;
ws.ws_row = 0;
ioctl(1, TIOCGWINSZ, &ws);
if (ws.ws_col > 0) {
screen_columns = ws.ws_col;
}
if (screen_columns >= sizeof(line_buf)) {
screen_columns = sizeof(line_buf) - 1;
}
switch (argc) {
case 0:
case 1:
break;
case 2:
centered = false;
if (isdigit(argv[1][0])) {
lines = atoi(argv[1]);
break;
}
default:
usage();
}
if (lines <= 0 || lines > MAX_LINES) {
fprintf(stderr, "%s: Number of lines out of range (1..%d).\n", prog_name, MAX_LINES);
exit(1);
}
for (i = 0; i < lines; i++) {
array[i] = (long double *) malloc(sizeof(long double) * lines);
if (array[i] == NULL) {
fprintf(stderr, "%s: Not enough memory.\n", prog_name);
exit(2);
}
}
calculate_triangle();
display_triangle();
exit(0);
}
void
calculate_triangle()
{
int i, j;
for (i = 0; i < lines; i++) {
for (j = 0; j <= i; j++) {
if (j == 0 || j == i) {
array[i][j] = 1.0;
} else {
array[i][j] = array[i-1][j-1] + array[i-1][j];
}
}
}
}
void
display_triangle()
{
int i, j;
int len;
if (centered && lines > 20) {
len = center_buf(19, 8);
if (len > 0 && len < screen_columns) {
cell_size = 8; /* for very wide screens */
}
}
for (i = 0; i < lines; i++) {
if (centered) {
len = center_buf(i, cell_size);
if (len <= 0 || len >= screen_columns) {
return; /* stop here because of wrap-around */
}
/* center on screen */
for (j = (screen_columns - len) / 2; j > 0; j--) {
printf(" ");
}
printf("%s", line_buf);
} else {
for (j = 0; j <= i; j++) {
printf("%.19Lg ", array[i][j]);
}
}
printf("\n");
}
}
/*
* Create a line of output in line_buf[] for centering mode.
* Return length if successful, otherwise return 0.
*/
int
center_buf(int line_number, int cell_size)
{
int j, k;
int i1;
int len;
char buf2[100];
assert(cell_size < sizeof(buf2));
line_buf[0] = '\0';
for (j = 0; j <= line_number; j++) {
assert(strlen(line_buf) + cell_size < sizeof(line_buf));
len = snprintf(buf2, sizeof(buf2), "%.19Lg", array[line_number][j]);
if (len >= cell_size) {
return(0); /* cell_size too small */
}
/* center in the cell */
for (k = i1 = (cell_size - len) / 2; k > 0; k--) {
strcat(line_buf, " ");
}
strcat(line_buf, buf2);
for (k = len + i1; k < cell_size; k++) {
strcat(line_buf, " ");
}
}
return(strlen(line_buf));
}
void
usage()
{
fprintf(stderr, "Usage: %s [number-of-lines]\n\n", prog_name);
fprintf(stderr, "Display up to %d lines of Pascal's triangle.\n", MAX_LINES);
exit(1);
}
syntax highlighted by Code2HTML, v. 0.9.1