xref: /csrg-svn/games/caesar/caesar.c (revision 39004)
139003Sbostic /*
2*39004Sbostic  * Copyright (c) 1989 The Regents of the University of California.
3*39004Sbostic  * All rights reserved.
439003Sbostic  *
5*39004Sbostic  * This code is derived from software contributed to Berkeley by
6*39004Sbostic  * Rick Adams.
739003Sbostic  *
8*39004Sbostic  * Authors:
9*39004Sbostic  *	Stan King, John Eldridge, based on algorithm suggested by
10*39004Sbostic  *	Bob Morris
1139003Sbostic  * 29-Sep-82
1239003Sbostic  *
13*39004Sbostic  * Redistribution and use in source and binary forms are permitted
14*39004Sbostic  * provided that the above copyright notice and this paragraph are
15*39004Sbostic  * duplicated in all such forms and that any documentation,
16*39004Sbostic  * advertising materials, and other materials related to such
17*39004Sbostic  * distribution and use acknowledge that the software was developed
18*39004Sbostic  * by the University of California, Berkeley.  The name of the
19*39004Sbostic  * University may not be used to endorse or promote products derived
20*39004Sbostic  * from this software without specific prior written permission.
21*39004Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
22*39004Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
23*39004Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2439003Sbostic  */
2539003Sbostic 
26*39004Sbostic #ifndef lint
27*39004Sbostic char copyright[] =
28*39004Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
29*39004Sbostic  All rights reserved.\n";
30*39004Sbostic #endif /* not lint */
3139003Sbostic 
32*39004Sbostic #ifndef lint
33*39004Sbostic static char sccsid[] = "@(#)caesar.c	5.2 (Berkeley) 09/05/89";
34*39004Sbostic #endif /* not lint */
35*39004Sbostic 
36*39004Sbostic #include <math.h>
3739003Sbostic #include <stdio.h>
3839003Sbostic #include <ctype.h>
3939003Sbostic 
40*39004Sbostic #define	LINELENGTH	2048
41*39004Sbostic #define	ROTATE(ch, perm) \
42*39004Sbostic 	isupper(ch) ? ('A' + (ch - 'A' + perm % 26)) : \
43*39004Sbostic 	    islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch
44*39004Sbostic 
4539003Sbostic main(argc, argv)
46*39004Sbostic 	int argc;
47*39004Sbostic 	char **argv;
4839003Sbostic {
49*39004Sbostic 	/*
50*39004Sbostic 	 * letter frequencies (taken from some unix(tm) documentation)
51*39004Sbostic 	 * (unix is a trademark of Bell Laboratories)
52*39004Sbostic 	 */
53*39004Sbostic 	static double stdf[26] = {
54*39004Sbostic 		7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04,
55*39004Sbostic 		0.42, 3.81, 2.69, 5.92,  6.96, 2.91, 0.08, 6.63, 8.77, 9.68,
56*39004Sbostic 		2.62, 0.81, 1.88, 0.23,  2.07, 0.06,
5739003Sbostic 	};
58*39004Sbostic 	double dot, winnerdot;
59*39004Sbostic 	register int i, ch;
60*39004Sbostic 	register char *inbuf;
61*39004Sbostic 	int bufsize, obs[26], rot, try, winner;
62*39004Sbostic 	char *malloc();
6339003Sbostic 
64*39004Sbostic 	if (argc > 1) {
65*39004Sbostic 		if ((rot = atoi(argv[1])) < 0) {
66*39004Sbostic 			(void)fprintf(stderr, "caesar: bad rotation value.\n");
67*39004Sbostic 			exit(1);
68*39004Sbostic 		}
69*39004Sbostic 		printit(rot);
70*39004Sbostic 		exit(0);
71*39004Sbostic 	}
7239003Sbostic 
73*39004Sbostic 	if (!(inbuf = malloc(LINELENGTH))) {
74*39004Sbostic 		(void)fprintf(stderr, "caesar: out of memory.\n");
75*39004Sbostic 		exit(1);
7639003Sbostic 	}
7739003Sbostic 
78*39004Sbostic 	/* adjust frequency table to weight low probs REAL low */
79*39004Sbostic 	for (i = 0; i < 26; ++i)
80*39004Sbostic 		stdf[i] = log(stdf[i]) + log(26.0 / 100.0);
8139003Sbostic 
82*39004Sbostic 	/* decode each line separately */
83*39004Sbostic 	for (bufsize = 0;;) {
84*39004Sbostic 		for (i = 0; i < 26; obs[i++] = 0);
85*39004Sbostic 
8639003Sbostic 		/* get a sample of the text */
87*39004Sbostic 		for (i = 0; i < LINELENGTH; i++) {
88*39004Sbostic 			if ((ch = getchar()) == EOF)
8939003Sbostic 				exit(0);
90*39004Sbostic 			inbuf[i] = ch;
91*39004Sbostic 			if (ch == '\n')
9239003Sbostic 				break;
93*39004Sbostic 			if (islower(ch))
94*39004Sbostic 				obs[ch - 'a'] += 1;
95*39004Sbostic 			else if (isupper(ch))
96*39004Sbostic 				obs[ch - 'A'] += 1;
9739003Sbostic 		}
98*39004Sbostic 		bufsize = i + 1;
9939003Sbostic 
100*39004Sbostic 		/*
101*39004Sbostic 		 * now "dot" the freqs with the observed letter freqs
102*39004Sbostic 		 * and keep track of best fit
103*39004Sbostic 		 */
104*39004Sbostic 		for (try = winner = 0; try < 26; try += 13) {
10539003Sbostic 			dot = 0;
106*39004Sbostic 			for (i = 0; i < 26; i++)
107*39004Sbostic 				dot += obs[i] * stdf[(i + try) % 26];
10839003Sbostic 			/* initialize winning score */
109*39004Sbostic 			if (try == 0)
11039003Sbostic 				winnerdot = dot;
111*39004Sbostic 			if (dot > winnerdot) {
11239003Sbostic 				/* got a new winner! */
11339003Sbostic 				winner = try;
11439003Sbostic 				winnerdot = dot;
11539003Sbostic 			}
11639003Sbostic 		}
11739003Sbostic 
11839003Sbostic 		/* print out sample buffer */
119*39004Sbostic 		while (bufsize--) {
120*39004Sbostic 			ch = *inbuf++;
121*39004Sbostic 			putchar(ROTATE(ch, winner));
122*39004Sbostic 		}
12339003Sbostic 	}
124*39004Sbostic }
12539003Sbostic 
126*39004Sbostic printit(rot)
127*39004Sbostic 	register int rot;
128*39004Sbostic {
129*39004Sbostic 	register int ch;
13039003Sbostic 
131*39004Sbostic 	while ((ch = getchar()) != EOF)
132*39004Sbostic 		putchar(ROTATE(ch, rot));
13339003Sbostic }
134