home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume2 / choose < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  3.7 KB

  1. From: decvax!tektronix!aeolus!bobl
  2. Subject: choose -- a program to select lines at random
  3. Newsgroups: mod.sources
  4. Approved: john@genrad.UUCP
  5.  
  6. Mod.sources:  Volume 2, Issue 36
  7. Submitted by: tektronix!teklds!bobl (Bob Lewis)
  8.  
  9.  
  10. #!/bin/sh-----cut here-----cut here-----cut here-----cut here-----
  11. # shar:    Shell Archiver
  12. #    Run the following text with /bin/sh to create:
  13. #    README #    choose.1 #    choose.c 
  14. cat - << \SHAR_EOF > README
  15. Here is a program "choose" to select randomly lines from files.  Simply
  16. compile it as
  17.  
  18.     cc -O -o choose choose.c
  19.  
  20. The program works under 4.2bsd and should also work under UTek.  Thanks to
  21. Nigel Horspool (uvicctr!nigelh), Brad Needham (tekig4!bradn), and everyone
  22. else who answered my earlier query on "random(3)".
  23.  
  24.     - Bob Lewis
  25.       ...!tektronix!teklds!bobl
  26. SHAR_EOF
  27. cat - << \SHAR_EOF > choose.1
  28. .TH CHOOSE 1 "7 August 1985"
  29. .UC 4
  30. .SH NAME
  31. choose \- randomly select one or more lines
  32. .SH SYNOPSIS
  33. .B choose
  34. [
  35. .BI \- n
  36. ]
  37. [
  38. .I file ...
  39. ]
  40. .SH DESCRIPTION
  41. .I Choose
  42. randomly chooses lines from its input
  43. .IR file s
  44. (default: standard input).
  45. All such files are concatenated together before the selection takes
  46. place.
  47. .PP
  48. The command line option is:
  49. .TP
  50. .BI \- n
  51. Select
  52. .I n
  53. lines from the input (default: 1).
  54. .SH EXAMPLE
  55. To build your own version of
  56. .IR fortune (1),
  57. put each saying in a file in the directory "wisdom" and then execute
  58. .IP
  59. cat `ls wisdom/* | choose`
  60. .SH FILES
  61. /tmp/choose.*
  62. .SH AUTHOR
  63. Bob Lewis, CAE Systems Division, Tektronix
  64. SHAR_EOF
  65. cat - << \SHAR_EOF > choose.c
  66. #include <stdio.h>
  67. #include <sys/time.h>
  68.  
  69. char *ProgName;
  70.  
  71. #define FN_TMP_TEMPLATE "/tmp/choose.XXXXXX"
  72. char *FnTmp;
  73. FILE *FpTmp;
  74.  
  75. main(NArg, Arg)
  76.     int NArg;
  77.     char *Arg[];
  78. {
  79.     char Ch;
  80.     int NToChoose = 1;
  81.     int NSample;
  82.     FILE *Fp, *efopen();
  83.     char *mktemp();
  84.  
  85.  
  86.     ProgName = *Arg++;
  87.  
  88.     if (NArg > 1 && Arg[0][0] == '-') {
  89.         NToChoose = atoi(&Arg[0][1]);
  90.         if (NToChoose <= 0) {
  91.             fprintf(stderr, "Usage: %s [-<#> [<file>]...]\n", ProgName);
  92.             exit(1);
  93.         }
  94.         Arg++;
  95.     }
  96.  
  97.     FnTmp = mktemp(FN_TMP_TEMPLATE);
  98.     FpTmp = efopen(FnTmp, "w+");
  99.  
  100.     if (*Arg != NULL) {
  101.         NSample = 0;
  102.         while (*Arg != NULL) {
  103.             Fp = efopen(*Arg++, "r");
  104.             NSample += DupCount(Fp, FpTmp);
  105.             fclose(Fp);
  106.         }
  107.     } else
  108.         NSample = DupCount(stdin, FpTmp);
  109.  
  110.     if (NToChoose > NSample) {
  111.         fprintf(stderr, "%s: Can't choose %d from %d.\n",
  112.                 ProgName, NToChoose, NSample);
  113.         Bye(1);
  114.     }
  115.  
  116.     InitRandom();
  117.  
  118.     rewind(FpTmp);
  119.  
  120.     for (;;) {
  121. #ifdef random_is_fixed
  122.         if ((random() % NSample) < NToChoose) {
  123. #else
  124.         /*
  125.          *    According to uvicctr!nigelh, the low order bits of random()
  126.          *    are not very random, hence...  (this limits us to fewer than
  127.          *    2^28 lines of input.  oh well.)
  128.          */
  129.         if (((random() >> 4) % NSample) < NToChoose) {
  130. #endif
  131.             while ((Ch = getc(FpTmp)) != '\n' && Ch != EOF)
  132.                 putchar(Ch);
  133.             putchar('\n');
  134.             NToChoose--;
  135.             if (NToChoose <= 0)
  136.                 Bye(0);
  137.         } else {
  138.             while ((Ch = getc(FpTmp)) != '\n' && Ch != EOF)
  139.                 ;
  140.             if (Ch == EOF) {
  141.                 fprintf(stderr, "%s: Unexpected EOF\n", ProgName);
  142.                 Bye(1);
  143.             }
  144.         }
  145.         NSample--;
  146.     }
  147. }
  148.  
  149. Bye(Stat)        /* get rid of temp file and exit */
  150.     int Stat;
  151. {
  152.     fclose(FpTmp);
  153.     unlink(FnTmp);
  154.     exit(Stat);
  155. }
  156.  
  157. FILE *efopen(file, mode)    /* open file, die if can't (from K&P) */
  158.     char *file, *mode;
  159. {
  160.     FILE *fp, *fopen();
  161.     extern char *ProgName;
  162.  
  163.     if ((fp = fopen(file, mode)) != NULL)
  164.         return fp;
  165.     fprintf(stderr, "%s: can't open file %s mode %s\n", ProgName, file, mode);
  166.     exit(1);
  167. }
  168.  
  169. int DupCount(FpFrom, FpTo)    /* duplicate file and count lines */
  170.     FILE *FpFrom, *FpTo;
  171. {
  172.     char Ch;
  173.     int NLn = 0;
  174.  
  175.     while ((Ch = getc(FpFrom)) != EOF) {
  176.         if (Ch == '\n')
  177.             NLn++;
  178.         putc(Ch, FpTo);
  179.     }
  180.  
  181.     return NLn;
  182. }
  183.  
  184. InitRandom()    /* initialize random sequence -- courtesy of tekig4!bradn */
  185. {
  186.     struct timeval tv;
  187.     struct timezone tz;
  188.  
  189.     gettimeofday(&tv, &tz);
  190.     srandom((int) tv.tv_sec);
  191.  
  192.     return;
  193. }
  194. SHAR_EOF
  195.  
  196.