たとえばSMS
と入力するつもりで左に1キーずれてたらANA
になる。
たとえばdry
と入力するつもりで左に1キーずれてたらset
になる。
こんな感じの、キーのズレを再現する関数を作ってみる。
////////
// wordに入力された文字列から、左に1文字ずつズレた文字列を返す関数。さしあたり小文字限定
// wordにq,a,z,が含まれる場合は例外を投げる。
///////
function wordShift(word){
var lineQ = "qwertyuiop";
var lineA = "asdfghjkl";
var lineZ = "zxcvbnm";
var lines = [lineQ, lineA, lineZ];
// 左端のキーは、これ以上左にズレる余地が無いのでエラーにする。
if( /[qaz]/.test(word) ){
throw "QAZ Exception";
}
var str = "";
for( var i=0; i<word.length; i++){ //1文字ずつ。
lines: //Q行、A行、Z行の順に処理するけど、Q行で見つかったらA,Z行は飛ばす。
for( j in lines ){
var re = new RegExp( word.charAt(i) );
var position = lines[j].search(re);
if(position > -1){ // 走査中の行に、i文字目があったら
str = str + lines[j].charAt(position-1); //となりの文字を格納
break lines; //ラベル付きブロックからの脱出。
}
}
}
return str;
}
たとえば、MIT's 10000-word listの中の4文字以上の単語で左にズレても単語になるものをリストアップするならこんな感じ。
wordShift(word)略
var WORDLIST = ["a","aa","aaa","aaron","ab","abandoned"...(中略)..."zu","zum","zus"];
for( var i in WORDLIST ){
// 4文字以上の単語に限定
if( WORDLIST[i].length < 4 ) continue;
/// wordShift(word)はq,a,zを含む単語で例外を投げてくるので。
try {
var shifted = wordShift( WORDLIST[i] );
if (WORDLIST.includes(shifted)){ // ズレた文字列が単語帳にあったら
console.log( [WORDLIST[i], shifted] ); // 両単語をコンソールに出力
}
} catch (err) { //例外は無視して次の単語にGo!Go!
continue;
}
}
これを試すと、["bored", "views"]
と["ford", "dies"]
の2組が返ってくる。意外と少ないのね。
何のためにこんなものを作ったのかというと、謎解きを作っていてですね。
暗号の、例を作るためなのです。