Advertisement
Guest User

Ian Grant

a guest
Jan 25th, 2010
758
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.59 KB | None | 0 0
  1. /*
  2.  * cnr.c
  3.  *
  4.  * (c) Ian Douglas Grant 2010.  All rights reserved.
  5.  *
  6.  * A command line interface tool for calculation of and displaying an iteration
  7.  * of combinations of n choose r elements.
  8.  *
  9.  */
  10.  
  11.  
  12.  
  13. /* preprocessor statements */
  14.  
  15. #include <stdlib.h>     /* standard C includes first */
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include <string.h>
  19.  
  20. #include <gmp.h>
  21.  
  22. /*
  23.  * Multiple precision data types and operations.
  24.  * ---------------------------------------------
  25.  *
  26.  * This program requires arbitrary precision. This is achieved through the use
  27.  * of the GNU Multiple Precision library.
  28.  *
  29.  * gmp.h :  needs to be included after stdio.h for certain prototypes required
  30.  * for the multiple precision arithmetic calls mpz_* etc.  this pretty much
  31.  * limits this code to unix-like OSs but I am not sure, maybe cygwin and
  32.  * knowing what you are doing on win32 might help.
  33.  *
  34.  * http://gmplib.org/
  35.  *
  36.  * As far as I know this library is clearly the best option around. NetBSD
  37.  * pkgsrc should have devel/gmp and FreeBSD ports collection has
  38.  * math/libgmp4.
  39.  */
  40.  
  41.  
  42.  
  43.  
  44. /*
  45.  * function prototypes
  46.  *
  47.  */
  48.  
  49. void        usage     (void);
  50. void        factorial (const unsigned long, mpz_t);
  51.  
  52.  
  53.  
  54.  
  55. /*
  56.  * function: main() descr:    program start point & main functionality.
  57.  */
  58.  
  59. int
  60. main(int argc, char *argv[])
  61. {
  62.     mpz_t       term     [4];   /* local declarations */
  63.     mpz_t       cnr;
  64.     mpz_t       i;
  65.     int            *comb = 0;
  66.     int     cmp = 0;
  67.     unsigned long   n = 0, r = 0;
  68.     unsigned long   m = 0, max = 0, j = 0, x = 0;
  69.     char        ch = ' ';
  70.     char        str       [80];
  71.     char           *p;
  72.     int     loop = 1;
  73.  
  74.     if (argc != 3) {    /* input arg sanity checking &
  75.                  * initialisations */
  76.         usage();
  77.         return 1;
  78.     }
  79.     for (x = 0; x < strlen(argv[1]); x++) {
  80.         if (isdigit(argv[1][x]) == 0) {
  81.             usage();
  82.             return 1;
  83.         }
  84.     }
  85.     for (x = 0; x < strlen(argv[2]); x++) {
  86.         if (isdigit(argv[2][x]) == 0) {
  87.             usage();
  88.             return 1;
  89.         }
  90.     }
  91.     if ((n = atoi(argv[1])) < 0 || n > 99) {
  92.         usage();
  93.         return 1;
  94.     }
  95.     if ((r = atoi(argv[2])) < 0 || r > n) {
  96.         usage();
  97.         return 1;
  98.     }
  99.     if ((comb = malloc(r * sizeof(int))) == 0) {
  100.         printf("malloc() failure\n");
  101.         return 2;
  102.     }
  103.     mpz_init(term[0]);
  104.     mpz_init(term[1]);
  105.     mpz_init(term[2]);
  106.     mpz_init(term[3]);
  107.     mpz_init(cnr);
  108.     mpz_init(i);
  109.  
  110.     factorial(n, term[0]);  /* main functionality begins */
  111.     factorial(n - r, term[1]);
  112.     factorial(r, term[2]);
  113.     mpz_mul(term[3], term[1], term[2]);
  114.     mpz_fdiv_q(cnr, term[0], term[3]);  /* C(n,r) = n!/(n-r)!r!  */
  115.     printf("C(%d,%d) = ", n, r);
  116.     mpz_out_str(NULL, 10, cnr);
  117.     while (loop) {      /* user interaction loop */
  118.         printf("\nIterate combinations ? > ");
  119.         p = str;
  120.         while ((*p++ = getchar()) != '\n') {
  121.             if ((str - p) > 50)
  122.                 break;
  123.         }
  124.         *p = '\0';
  125.         ch = str[0];
  126.         if (ch == 'n' || ch == 'N') {
  127.             printf("OK done.\n");   /* handle choice made */
  128.             return 0;
  129.         } else if (ch == 'y' || ch == 'Y')
  130.             loop = 0;
  131.     }
  132.     for (x = 0; x < r; x++) /* C(n, r) iterator code block */
  133.         comb[x] = x + 1;
  134.     for (x = 0; x < r; x++)
  135.         printf("%d ", comb[x]);
  136.     printf("\n");
  137.     for (mpz_set_ui(i, 1); cmp = mpz_cmp(i, cnr); mpz_add_ui(i, i, 1)) {
  138.         m = r - 1, max = n;
  139.         while (comb[m] == max)
  140.             m--, max--; /* this algorithm was written */
  141.         comb[m]++;  /* in C from the pseudocode notation */
  142.         for (j = m + 1; j < r; j++) /* within Discrete
  143.                          * Mathematics 5th ed. */
  144.             comb[j] = comb[j - 1] + 1;  /* by Richard
  145.                              * Johnsonbaugh */
  146.         for (x = 0; x < r; x++)
  147.             printf("%d ", comb[x]);
  148.         printf("\n");
  149.     }
  150.     free(comb);
  151.     return 0;
  152. }
  153.  
  154.  
  155.  
  156.  
  157. /*
  158.  * function: usage() descr:  prints a response to incorrect input arguments
  159.  */
  160. void
  161. usage(void)
  162. {
  163.     printf("usage: cnr [n] [r]\n");
  164.     printf("       Where n is an integer\n");
  165.     printf("       larger than -1 and smaller\n");
  166.     printf("       than 100;  where r is an\n");
  167.     printf("       integer larger than 0 and smaller\n");
  168.     printf("       than or equal to n.\n");
  169. }
  170.  
  171.  
  172.  
  173.  
  174. /*
  175.  * function: factorial() descr: n(n-1)! note: make sure you have called
  176.  * mpz_init() on the  argument mpz_t rop. factorial() follows the form of gmp
  177.  * functions and is return void. You may or may not wish to keep this snippet
  178.  * in such a form. returning a mpz_t would not be a problem.
  179.  */
  180.  
  181. void
  182. factorial(const unsigned long n, mpz_t rop)
  183. {
  184.     mpz_t       answer;
  185.     unsigned long   x = 0;
  186.  
  187.     mpz_init(answer);
  188.  
  189.     if (!n) {       /* A very important fact as */
  190.         mpz_set_ui(rop, 1); /* C(0, 0) = 1 */
  191.         return;
  192.     }
  193.     x = n - 1;
  194.     mpz_set_ui(answer, n);
  195.     while (x) {     /* Iteration avoids function call */
  196.         mpz_mul_ui(answer, answer, x);  /* overhead */
  197.         x--;
  198.     }
  199.     mpz_set(rop, answer);
  200.     return;
  201. }
  202.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement