Logo Search packages:      
Sourcecode: mathomatic version File versions  Download package

matho-pascal.c

/*
 * Calculate and display Pascal's triangle.
 *
 * Copyright (C) 2005 George Gesslein II.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Usage: matho-pascal [number-of-lines]
 */

#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) {
            screen_columns = ws.ws_col;
      }
      if (screen_columns >= sizeof(line_buf)) {
            fprintf(stderr, "%s: Screen too wide!\n", prog_name);
            exit(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);
}

Generated by  Doxygen 1.6.0   Back to index