アルゴリズム問題ウォークスルーシリーズで次はCesar暗号化器についてです。 Leetcode のような Web サイトで「簡単な」アルゴリズムに分類されるこの問題は、技術面接でよく取り上げられるもうひとつの古典的な問題で、問題解決のスキルを磨きたいソフトウェア エンジニアにとって良い練習になります。
Background Information
最初に、シーザー暗号についていくつかのバックグラウンド情報を提供し、我々が扱っているものを理解できるようにします。シーザー暗号は暗号学の簡単な例で、Merriam-Webster では「秘密のコードまたは暗号でメッセージを暗号化および解読すること」
また「情報をコンピュータで符号化および解読すること」と定義されています。 シーザー暗号は、メッセージの意味を隠すために文字をずらすことから、シフト暗号とも呼ばれる。 シーザー暗号は、ジュリアス・シーザーとその同盟国が軍事機密を含む秘密のメッセージを送るために、この暗号の方法を使ったと言われていることから、この名前がついた(IBM Z Security)。
Caesar Cipher Encryptor
さて、シーザー暗号の背景と仕組みがわかったところで、実際のアルゴリズムの問題を見ていきましょう。 小文字からなる空でない文字列と、文字列中の各文字をアルファベットの何番目にシフトするかを指定するキー(非負の整数)が与えられたとき、我々の使命は、暗号化された文字列を返す関数を書くことである。 文字がアルファベットの周りを回るようにしたい。z
を1ヶ所ずらすとa
.
という文字が返ってくるはずだ。さて、コードに入る前にこの問題を概念的に考えてみよう。 入力文字列の各文字を系統的にある桁数だけずらす必要があることは分かっている。 各文字を一貫して表現し、また与えられたキーで各文字を簡単にシフトできるように、各文字を数字に対応させる方法を見つけるにはどうしたらよいでしょうか。 キーが整数で値がそれに対応する文字であるオブジェクトにマッピングシステムを格納して、文字から数字へのマッピングを独自に行うこともできますが、もっと簡単な方法はないでしょうか?
JavaScript には、他の多くのプログラミング言語と同様に、ある文字の Unicode 値を取得できる関数があります。 charCodeAt()
. この便利な組み込み関数により、アルファベットのマッピング システムを効率的に作成することができます。
結果を保存するための空の配列を初期化しましょう。この配列を newLetters
と呼ぶことにします。 渡された文字列を繰り返し処理し、文字列の各文字について、アルファベットの文字を Unicode 値に変換します。 次に、unicode 値にキー (文字を何回転置するかを示す数値) を追加して、新しい文字の unicode 値を取得します。 次に、JavaScriptの組み込み関数String.fromCharCode()
を使って、unicode値を文字列に変換します。 最後のステップとして、結果を newLetters 配列にプッシュし、配列の要素を 1 つの文字列に結合して最終的な答えを得ます。
Things To Keep In Mind
非常に複雑ではありませんが、いくつかの重要事項を心に留めておきたいと思います。 まず、a
のUnicode値は97で、z
のUnicode値は122であることを知っておくと役に立ちます。
文字がアルファベットの周りを回るようにするために(つまり、zを1ポジション以上シフトしたものがaです)、unicode値が122以上の場合は、modulo演算子を使用して122以下の値に強制的に変更されます。 a
は 97 に等しいので、前のステップでモジュロ演算子を使用した結果の数値を 96 に追加して、アルファベットの文字に対応する値にします。
大きな数値を得ることに対するもう一つの安全策として、キーを扱いやすい数値に強制することも可能です。 英語のアルファベットは26文字で構成されているので、26文字ずつずらしていくと、最初と全く同じ場所に来てしまい、暗号の目的が達成されないことが分かっています。 323>
Resulting Code
さて、ここまでで解法のコンセプトが見えてきましたが、実際にどのようにコード化するか、ここで少し考えてみてください。 まずは自分で試してみてください。 コードがぐちゃぐちゃで、思ったように乾いていなくても構いません。まず動作するソリューションを取得してから、コードをリファクタリングしてきれいにします。