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

char g_table[25];	// 暗号表
int g_reverse[26];	// 逆変換テーブル

char get_table(int x, int y)
{
	if (x >= 5) x -= 5;
	if (y >= 5) y -= 5;
	return g_table[y * 5 + x];
}

int main()
{
	char keyword[] = "Playfair";
	char message[] = "Abandon hope, all ye who enter here.";
	char alphabet[] = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
	char plaintext[100];	// 平文
	char *p, c, c1, c2;
	int i, pos, x1, y1, x2, y2;

	// 暗号表の作成
	pos = 0;
	for (p = keyword; c = toupper(*p); p++) {
		for (i = 0; i < pos; i++) {
			if (g_table[i] == c) break;
		}
		if (i == pos) g_table[pos++] = c;
	}
	for (p = alphabet; c = *p; p++) {
		for (i = 0; i < pos; i++) {
			if (g_table[i] == c) break;
		}
		if (i == pos) g_table[pos++] = c;
	}

	// 暗号表の表示
	for (i = 0; i < 25; i++) {
		printf("%c%c", g_table[i], ((i+1)%5) ? ' ' : '\n');
	}

	// 逆変換テーブルの作成
	for (i = 0; i < 25; i++) {
		c = g_table[i] - 'A';
		g_reverse[c] = i;
	}
	g_reverse[9] = g_reverse[8];	// J <- I

	// 逆変換テーブルの表示
	for (i = 0; i < 26; i++) {
//		printf("%c:%d\n", 'A'+i, g_reverse[i]);
	}

	// メッセージを加工
	pos = 0;
	for (p = message; c = *p; p++) {
		if (!isalpha(c)) continue;
		if (pos > 0 && plaintext[pos-1] == c) {
			plaintext[pos++] = 'x';
		}
		plaintext[pos++] = c;
	}
	if (pos & 1) plaintext[pos++] = 'x';
	plaintext[pos] = '\0';

	printf("[%s]\n", plaintext);

	// 暗号化
	for (p = plaintext; *p; ) {
		pos = g_reverse[toupper(*p++) - 'A'];
		x1 = pos % 5;
		y1 = pos / 5;
		pos = g_reverse[toupper(*p++) - 'A'];
		x2 = pos % 5;
		y2 = pos / 5;
		if (x1 == x2) {
			// 同じ列の場合
			c1 = get_table(x1, y1 + 1);
			c2 = get_table(x2, y2 + 1);
		} else if (y1 == y2) {
			// 同じ行の場合
			c1 = get_table(x1 + 1, y1);
			c2 = get_table(x2 + 1, y2);
		} else {
			// 行も列も違う場合
			c1 = get_table(x2, y1);
			c2 = get_table(x1, y2);
		}
		printf("%c%c ", c1, c2);
	}
	printf("\n");

	return 0;
}
