RUPC A, AOJ-2281: スワップ暗号 (Swap Cipher)

問題概要

長さL(<100)の文字列(全て小文字)が与えられる。次の操作をN(<100)回繰り返して文章を暗号化する。暗号文が与えられるので平文を復元する問題。

  • 暗号化の手順
  1. a, b(0<=a
  2. b-aだけスワップさせた文字を逆方向にrotする。

考えたこと

  • 後ろからシミュレーションするだけ。
  • 何かサンプルの最後が合わない…。
  • アスキー記号だと後ろに大文字があるからオーバーフローは起きないはずなんだけどなあ。
  • charを%dで出力したら負になってる…。
  • アスキーコード表をググってみたら小文字が後ろだ。こりゃオーバーフローするわ。
  • charをunsigned charにしたらコンパイラにおこられた。
  • 素直にintを使って実装。無事通った。

本番で通ったコード

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_L = 100;
const int MAX_N = 100;

int N;
char str[MAX_L + 1];
int as[MAX_N], bs[MAX_N];

void solve(){
	const int L = strlen(str);
	for(int i=N-1; i>=0; i--){
		const int diff = abs(as[i] - bs[i]) % 26;
		int a = str[as[i]];
		int b = str[bs[i]];
		a += diff;
		if(a > 'z') a -= 26;
		b += diff;
		if(b > 'z') b -= 26;

		str[as[i]] = b;
		str[bs[i]] = a;
	}

	puts(str);
}

int main(){

	while(scanf("%d ",&N), N){
		scanf("%[^\n]%*c", str);
		for(int i=0; i<N; i++){
			scanf("%d%d ", as+i, bs+i);
			as[i]--; bs[i]--;
		}

		solve();
	}

	return 0;
}