[net.sources] permute the lines of a program, a lost art

eklhad@ihnet.UUCP (K. A. Dahlke) (07/20/84)

/* shuffle.c:  shuffle the lines of a computer program */
/* This program brings back a bit of nostalgia.
*  Remember the days of punch-cards?  No editors. no interactive setions.
*  Wasn't it fun writing a 1,900 line program, and dropping the box of cards
*  on the way to the computing center?
*  The wind blew your cards all over the campus.
*  You then had the pleasure of collecting and sorting them
*  before the project was due.
*  This aspect of computer science must not be forgotten in the wake
*  of ever advancing technology.
*  This program can help!!!
*  It will randomly permute the lines of a file for you.
*
*  cc -s -O -o shuffle shuffle.c
*  shuffle file
*
*  Your file can be in any language (even assembly).
*  We can even extend the concept, try it on a document.
*
*  Unfortunately, this program cannot recapture the excitement of collecting
*  the cards as they fly in the wind.
*  Perhaps a later release will leave each line in a separate
*  file, scattered throughout the UNIX directory structure.
*  Until then, you can still enjoy sorting your programs.
*  Enjoy!!!
*/

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

extern char *malloc();

int fd; /* file descriptor */
off_t flen; /* file length */
char *fstart; /* start of file in memory */
char *fend;
char **lptrs; /* pointers to lines */
char **eptrs;
int nlines;

struct stat filstat;

main(argc, argv)
char **argv;
{
	register char *s;
	register i;

	if(argc!=2){
		fprintf(stderr,"usage: shuffle file\n");
		exit(1);
	}

	fd=open(argv[1],O_RDWR);
	if(fd<0){
		fprintf(stderr,"cannot access %s\n",argv[1]);
		exit(1);
	}

	fstat(fd,&filstat);
	if((filstat.st_mode&S_IFMT)!=S_IFREG){
		fprintf(stderr,"%s is not a regular file\n",argv[1]);
		exit(1);
	}

	flen=filstat.st_size;
	if(!flen) exit(0);

	fstart=malloc(flen);
	if(!fstart){
		fprintf(stderr,"cannot allocate enough memory\n");
		exit(1);
	}
	fend=fstart+flen;

	/* read file */
	if(read(fd,fstart,flen)<flen){
		fprintf(stderr,"bad read on file %s\n",argv[1]);
		exit(1);
	}

	/* count lines */
	for(i=0,s=fstart;s<fend;++s)
		if(*s=='\n') ++i;
	nlines=i;
	if(nlines>32767){
		fprintf(stderr,"too many lines in file %s\n",argv[1]);
		exit(1);
	}
	if(nlines<2) exit(0);

	/* partial line (at EOF) will not be shuffled */

	lptrs=(char **)malloc(2*nlines*sizeof(char*));
	if(!lptrs){
		fprintf(stderr,"cannot allocate enough memory\n");
		exit(1);
	}
	eptrs=lptrs+nlines;

	/* set pointers to the beginning and end of each line */
	for(s=fstart,i=0;i<nlines;++i){
		lptrs[i]=s;
		while(*s++!='\n')  ;
		eptrs[i]=s;
	}

	shuffle();
}

shuffle(){
	register i,j;
	extern long time();

	srand(time()&32767);
	lseek(fd,0,0);

	for(i=nlines;i>0;--i){
		j=(rand()*i)>>15;
		write(fd,lptrs[j],eptrs[j]-lptrs[j]);
		lptrs[j]=lptrs[i-1];
		eptrs[j]=eptrs[i-1];
	}
}
-- 

Karl Dahlke    ihnp4!ihnet!eklhad