Pythonでシーザー暗号を実装する方法:文字列をk文字シフトするアルゴリズム解説
シーザー暗号は、古典的な暗号方式の一つで、各文字をアルファベット上で一定数だけずらして変換します。本記事では、小文字のアルファベット文字列 s とオフセット値 k を受け取り、s 内のすべての文字をアルファベット順に k 文字分後ろへずらした文字列を生成する方法を、Pythonのコード例とともに解説します。
シーザー暗号の仕組み
例えば、入力が "hello"、k = 3 の場合、各文字が3つずつ後ろにずらされるため、出力は "khoor" になります。
ここで注意すべき点は、文字が z を超えて溢れた場合(あるいは逆方向にシフトして a より前になった場合)には、アルファベットの反対側に折り返す(ラップアラウンドさせる)必要があるということです。例えば k = 3 のとき、x は a に変換されます。
解決の手順
この問題を解くためには、以下の手順に従います。
- 1文字を受け取ってシフト後の文字を返す関数
shift()を定義します。 - 文字
cのASCIIコードから'a'のASCIIコードを引いて、0〜25のインデックスiを求めます。 iにkを加算します。iを26で割った余りを求めることで、折り返し処理を実現します。'a'のASCIIコードにiを加え、そのASCIIコードに対応する文字を返します。- メインの処理では、文字列
sの各文字に対してshift(c)を呼び出し、結果を連結して返します。
実装例
以下が実際のPythonコードです。組み込み関数 ord()(文字→ASCIIコード)と chr()(ASCIIコード→文字)を活用しています。
class Solution:
def solve(self, s, k):
def shift(c):
i = ord(c) - ord('a')
i += k
i %= 26
return chr(ord('a') + i)
return "".join(map(shift, s))
ob = Solution()
print(ob.solve("hello", 3))入力
"hello", 3
出力
khoor
コードのポイント
- モジュロ演算による折り返し:
i %= 26の処理により、zを超えた文字が自動的にアルファベットの先頭に戻ります。負のオフセット(復号)にも対応できます。 - map関数の活用:
map(shift, s)によって文字列の各文字に関数を適用し、join()で一つの文字列にまとめています。リスト内包表記"".join([shift(c) for c in s])でも同様の結果が得られます。 - 計算量: 文字列の長さを n とすると、時間計算量は O(n)、空間計算量も O(n) となります。
このように、ASCIIコードとモジュロ演算を組み合わせることで、シーザー暗号はわずか数行のコードで簡潔に実装できます。大文字への対応や、復号処理(k を負の値にする)への拡張も容易に行えるので、ぜひ試してみてください。
-
【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説
はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが
-
Rubyで学ぶ!シーザー暗号エンコーダーの自作方法
シーザー暗号(Caesar cipher)をご存知ですか? これは、ユリウス・カエサルが敵に知られないよう秘密のメッセージを隠すために実際に使った暗号化手法です。 シーザー暗号は、最も原始的な暗号技術の一つとされています。 その仕組みの核心は、アルファベットの文字をx個分だけずらす(ローテートする)というシンプルなアイデアにあります。 例えば x = 1 の場合、「A」は「B」に、「C」は「D」に変換されます。以下同様です。 では、これをコードで実装するにはどうすればよいのでしょうか? 答えは意外と簡単です。文字は数値(ASCIIコード)として表現できるという事実を利用すれば、文字の回転処理