xref: /csrg-svn/games/caesar/caesar.c (revision 39003)
1*39003Sbostic /*
2*39003Sbostic  * program to to decrypt caesar(tm) cypher
3*39003Sbostic  * (caesar is a trademark of the roman empire)
4*39003Sbostic  *
5*39003Sbostic  * to compile:
6*39003Sbostic  *
7*39003Sbostic  *	cc decrypt.c -lm -o decrypt.c
8*39003Sbostic  *
9*39003Sbostic  * usage:
10*39003Sbostic  *
11*39003Sbostic  *	decrypt [n] < file
12*39003Sbostic  *
13*39003Sbostic  * where n is an optional forced rotation.
14*39003Sbostic  *
15*39003Sbostic  * authors: Stan King, John Eldridge, based on algorithm suggested by
16*39003Sbostic  *		Bob Morris
17*39003Sbostic  * 29-Sep-82
18*39003Sbostic  *
19*39003Sbostic  */
20*39003Sbostic 
21*39003Sbostic #ifdef SCCSID
22*39003Sbostic static char	*SccsId = "@(#)caesar.c	1.7	4/16/85";
23*39003Sbostic #endif /* SCCSID */
24*39003Sbostic 
25*39003Sbostic #include <stdio.h>
26*39003Sbostic #include <ctype.h>
27*39003Sbostic #include <math.h>
28*39003Sbostic extern char *calloc();
29*39003Sbostic 
30*39003Sbostic main(argc, argv)
31*39003Sbostic int argc;
32*39003Sbostic char *argv[];
33*39003Sbostic {
34*39003Sbostic 	/* letter frequencies (taken from some unix(tm) documentation) */
35*39003Sbostic 	/* (unix is a trademark of Bell Laboratories) */
36*39003Sbostic 	static double stdf[ 26 ] =
37*39003Sbostic 	{
38*39003Sbostic 		7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49,
39*39003Sbostic 		6.39, 0.04, 0.42, 3.81, 2.69, 5.92, 6.96, 2.91,
40*39003Sbostic 		0.08, 6.63, 8.77, 9.68, 2.62, 0.81, 1.88, 0.23,
41*39003Sbostic 		2.07, 0.06,
42*39003Sbostic 	};
43*39003Sbostic 	int obs[26];
44*39003Sbostic 	int bufsize;
45*39003Sbostic 	int c, i, try;
46*39003Sbostic 	double dot, winnerdot;  /* .. */
47*39003Sbostic 	int winner, forced = 0;
48*39003Sbostic 	char *inbuf;
49*39003Sbostic 
50*39003Sbostic 	bufsize = 0;
51*39003Sbostic 	if( argc > 1 )
52*39003Sbostic 		sscanf( argv[1], "%d", &forced );
53*39003Sbostic 	if( forced == 0 )
54*39003Sbostic 		forced = -1000;
55*39003Sbostic 
56*39003Sbostic 	inbuf = calloc( BUFSIZ, 1 );
57*39003Sbostic 
58*39003Sbostic 	/* adjust frequency table to weight low probs REAL low */
59*39003Sbostic 	for (i=0; i<26; i++)	{
60*39003Sbostic 		stdf[i] = log(stdf[i]) + log(26.0/100.0);
61*39003Sbostic 	}
62*39003Sbostic 
63*39003Sbostic 	/* Decode each line separately */
64*39003Sbostic 	for (;;) {
65*39003Sbostic 		for (i=0; i<=25; obs[i++]=0)
66*39003Sbostic 			;
67*39003Sbostic 
68*39003Sbostic 		/* get a sample of the text */
69*39003Sbostic 		for( i = 0; i < BUFSIZ; i++ ) {
70*39003Sbostic 			if( (c = getchar()) == EOF ) {
71*39003Sbostic 				exit(0);
72*39003Sbostic 			}
73*39003Sbostic 			inbuf[i] = c;
74*39003Sbostic 			if (c == '\n') {
75*39003Sbostic 				bufsize = i+1;
76*39003Sbostic 				break;
77*39003Sbostic 			}
78*39003Sbostic 			if (islower(c))
79*39003Sbostic 				obs[c-'a'] += 1;
80*39003Sbostic 			else if (isupper(c))
81*39003Sbostic 				obs[c-'A'] += 1;
82*39003Sbostic 		}
83*39003Sbostic 
84*39003Sbostic 		/* now "dot" the freqs with the observed letter freqs */
85*39003Sbostic 		/*	and keep track of best fit */
86*39003Sbostic 		winner = 0;
87*39003Sbostic 		for (try = 0; try<26; try+=13) {
88*39003Sbostic 			dot = 0;
89*39003Sbostic 			for ( i=0; i<26; i++ ) {
90*39003Sbostic 				dot += obs[i] * stdf[ (i+try) % 26 ];
91*39003Sbostic 				}
92*39003Sbostic 			/* initialize winning score */
93*39003Sbostic 			if( try == 0 )
94*39003Sbostic 				winnerdot = dot;
95*39003Sbostic 			if( dot > winnerdot ) {
96*39003Sbostic 				/* got a new winner! */
97*39003Sbostic 				winner = try;
98*39003Sbostic 				winnerdot = dot;
99*39003Sbostic 			}
100*39003Sbostic 		}
101*39003Sbostic 
102*39003Sbostic 		if (forced != -1000)
103*39003Sbostic 			winner = forced;
104*39003Sbostic 
105*39003Sbostic 		/* print out sample buffer */
106*39003Sbostic 		for( i = 0; i < bufsize; i++ )
107*39003Sbostic 			putchar( rotate( inbuf[i], winner ) );
108*39003Sbostic 	}
109*39003Sbostic  }
110*39003Sbostic 
111*39003Sbostic 
112*39003Sbostic static int
113*39003Sbostic rotate( c, perm )
114*39003Sbostic char c;
115*39003Sbostic int perm;
116*39003Sbostic {
117*39003Sbostic 	if (isupper(c))	{
118*39003Sbostic 		return 'A' + (c - 'A' + perm) % 26 ;
119*39003Sbostic 	}
120*39003Sbostic 	else if (islower(c)) {
121*39003Sbostic 		return 'a' + (c-'a'+perm) % 26 ;
122*39003Sbostic 	}
123*39003Sbostic 	else return c;
124*39003Sbostic }
125