/*
WORKS :)
Automatically solves Caeser and Affine ciphers
Written by James Hallam, http://web.jameshallam.info
with some help from Jeanne-Kamikaze
If you're not me, you're not even allowed to LOOK at this code :P
Applies basic english-checking... could do with some improvement
*/

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define MAXSIZE 10000

char ciphertext[MAXSIZE];
char worktext[MAXSIZE];

int main(int argc, char *argv[])
{
	char ch;
	int i;
	int offset,multiplier,winningoffset,winningmultiplier;
	int pointcount[26][26];
	
	for(i=0;(ch=getchar()) != EOF;i++)
	{
		ciphertext[i] = toupper(ch);
	}
	
	winningmultiplier = 1; //Multiplying by 0 would be silly
	winningoffset = 0;
	
	for(multiplier=0;multiplier<=25;multiplier++)
	{
		for(offset=0;offset<=25;offset++)
		{
			pointcount[multiplier][offset] = 0; // Clear/initialise point db
		}
	}
	
	for(multiplier=1;multiplier<=25;multiplier=(multiplier + 2))
	{
		for(offset=0;offset<=25;offset++)
		{
			decipher(multiplier, offset);
		
			if((strstr(worktext, "THE")) != NULL)
			{ pointcount[multiplier][offset] = (pointcount[multiplier][offset] + 3);}
		
			if((strstr(worktext, "YOU")) != NULL)
			{ pointcount[multiplier][offset] = (pointcount[multiplier][offset] + 3);}
		
			if((strstr(worktext, "AND")) != NULL)
			{ pointcount[multiplier][offset] = (pointcount[multiplier][offset] + 3);}
		
			if((strstr(worktext, "THAT")) != NULL)
			{ pointcount[multiplier][offset] = (pointcount[multiplier][offset] + 4);}
		
			if((strstr(worktext, "HAVE")) != NULL)
			{ pointcount[multiplier][offset] = (pointcount[multiplier][offset] + 4);}
		
			if((strstr(worktext, "THIS")) != NULL)
			{ pointcount[multiplier][offset] = (pointcount[multiplier][offset] + 4);}
		
			if((strstr(worktext, "FROM")) != NULL)
			{ pointcount[multiplier][offset] = (pointcount[multiplier][offset] + 4);}
		
			//printf("Multiplier: %i, Offset %i: %i points\n", multiplier, offset, pointcount[multiplier][offset]);
			if(pointcount[multiplier][offset] > pointcount[winningmultiplier][winningoffset])
			{
				winningoffset = offset;
				winningmultiplier = multiplier;
			}
		}
	}
	
	//printf("Won: %i,%i\n", winningmultiplier, winningoffset);
	decipher(winningmultiplier, winningoffset); //Set worktext to the one most likely to be english
	for(i=0;i < strlen(worktext); i++) { printf("%c", tolower(worktext[i])); } //Output the final variation as lower-case plaintext

return 0;
}

int decipher(int multiplier, int offset)
{
	int i=0; // CipherText character counter
	int j=0; // WorkText character counter
	for(i=0;i < strlen(ciphertext); i++)
	{
		if (ciphertext[i] >= 'A' && ciphertext[i] <= 'Z') //Make sure it's a valid letter
		{
			worktext[j] = (ciphertext[i] - 'A'); //Convert to number between 0 and 25
			worktext[j] = (((worktext[j] * multiplier) + offset) % 26); //Do the actual shifting
			worktext[j] = (worktext[j] + 'A'); //Convert back to ASCII again
			j++
		}
		else
		{					// If the character isn't a letter:
			//worktext[i] = ciphertext[i];	// just copy it directly
			//worktext[i] = ' ';		// replace it with a blank space
							// leave it out of the result entirely, and don't increment j
		}
	}
return 0;
}

