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