乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

アルゴリズム

今回は最近公開された
Xのフィードアルゴリズムについてです

解説動画はこちら





Xのフィード・アルゴリズムの仕組みについて

Xのアルゴリズムコードはこちらになります。

xai



システムの4つの主要コンポーネント



Xのフィードアルゴリズムは
大きく4つのコンポーネントで構成されています。

4components



1. Home Mixer:
全体の司令塔(オーケストレーション層)です。

候補の抽出からランク付け、フィルタリングまでの全工程を管理します。
パイプラインは以下のステージで構成されています:

    1.Query Hydration - ユーザーのエンゲージメント履歴とメタデータを取得
    2.Candidate Sources - ThunderとPhoenixから候補を取得
    3.Hydration - 候補に追加データを付与
    4.Pre-Scoring Filters - 不適格な投稿を除外
    重複、古い投稿、自分の投稿、ブロック/ミュートしたアカウント、ミュートキーワードなど
    5.Scoring - 複数のスコアラーを順次適用
      Phoenix Scorer (ML予測)
      Weighted Scorer (予測の重み付け結合)
      Author Diversity Scorer (多様性のための減衰)
      OON Scorer (Out-of-Network調整)
    6.Selection - スコアでソートし、上位K件を選択
    7.Post-Selection Filters - 最終検証 (削除済み/スパム/暴力的コンテンツなど)
    8.Side Effects - キャッシュとログ記録


2. Thunder:
フォロー中ユーザーの投稿をリアルタイムで追跡するメモリ内ストアです。

ミリ秒単位の高速な読み込みを可能にします。

主要機能:
    1.Kafkaからのリアルタイム取り込み - 投稿の作成/削除イベントを消費
    2.ユーザー別ストア管理 - オリジナル投稿、リプライ/リツイート、動画投稿を分類
    3.サブミリ秒ルックアップ - 外部データベースにアクセスせずに高速検索
    4.自動トリミング - 保持期間を超えた古い投稿を自動削除

パフォーマンス最適化:
    1.タイムアウト機能 (デフォルト設定可能)
    2.ユーザーあたりの投稿数制限
    3.メモリ効率化のための自動容量調整


3. Phoenix:
機械学習(ML)を担当する心臓部です。

検索: フォロー外から好みに合う投稿を見つけ出します。
ランキング: ユーザーがその投稿に反応(いいねやリプライなど)する確率を予測します。

・アルゴリズムの詳細

2つのステップ

1. Retrieval(Retrieval段階):
数億のツイートから、2タワーモデル(Two-Tower Model)を用いて
「関連がありそうな数千件」をミリ秒単位で抽出します。

2. Ranking(ランキング段階):
抽出された数千件に対し、トランスフォーマーモデルを用いて
いいねやリポストなどの「具体的なエンゲージメント確率」を
詳細に予測・採点します。


Retrieval: Two-Tower Model (2タワーモデル)
   1. User Tower(ユーザー側): 
   ユーザーの属性(User Hashes)と、過去のエンゲージメント履歴(History)を
   トランスフォーマーで処理し、ユーザーの「現在の興味」を
   1つの数値ベクトル(User Representation)に凝縮します。

   2. Candidate Tower(ツイート側): 
   ツイート内容や投稿者情報を同様にベクトル化(Candidate Representation)します。

近さの計算(ドット積)
   「近さ」の採点は、ユーザーベクトルと
   ツイートベクトルの**ドット積(内積)**で行われます。

   ベクトル同士の向きが近い(興味が一致する)ほどスコアが高くなります。
   全てのツイートが事前にベクトル化されているため
   数億件の中から瞬時に上位K件を取得可能です。


Multi-Action Prediction (複数アクション予測)
   P(favorite)      - いいね
   P(reply)         - リプライ
   P(repost)        - リツイート
   P(quote)         - 引用ツイート
   P(click)         - クリック
   P(profile_click) - プロフィールクリック
   P(video_view)    - 動画視聴
   P(share)         - シェア
   P(dwell)         - 滞在時間
   P(follow_author) - フォロー
   P(not_interested) - 興味なし (負の重み)
   P(block_author)  - ブロック (負の重み)
   P(mute_author)   - ミュート (負の重み)
   P(report)        - 報告 (負の重み)


最終スコア計算:

   Final Score = Σ (weight_i × P(action_i))

ポジティブなアクションは正の重み、ネガティブなアクションは負の重みを持ちます。


4.Candidate Pipeline:
推薦システムを構築するための再利用可能なフレームワークです。
   Source データソースから候補を取得
   Hydrator 候補に追加特徴を付与
   Filter 表示すべきでない候補を除外
   Scorer ランキング用のスコアを計算
   Selector 上位候補をソート・選択
   SideEffect 非同期サイドエフェクト実行 (キャッシュ、ログ)
   QueryHydrator クエリコンテキストを準備




おすすめが表示されるまでの流れ


フィードが生成されるまでには、以下のステップを踏みます。
flow


1. データの準備 (Hydration): ユーザーの過去のエンゲージメント履歴や
フォローリストを読み込みます。

2. 候補の抽出: 「Thunder(フォロー内)」と「Phoenix(フォロー外)」の
両方から候補となる投稿を集めます。
   
3. フィルタリング(前処理): 重複した投稿、古すぎる投稿
自分がブロックしている相手の投稿、既に見た投稿などを除外します。

4. スコアリング(ランク付け):
 Grokベースのモデルが「いいね」「リプライ」「リポスト」
 「クリック」などの発生確率を個別に予測します。
 それらを重み付けして最終スコアを算出します。
 特定の著者ばかりに偏らないよう「著者多様性スコア」で調整をかけます。

5. 最終選定: スコアの高い順に並べ替え、最終的な表示候補を選び出します。

6. フィルタリング(後処理): 削除済み、スパム、暴力的なコンテンツなどが
混じっていないか最終チェックを行います。


おすすめに表示されやすくなるポイント

ポジティブエンゲージメント
以下のアクションが予測されるとスコアが上昇:

いいね、リツイート、リプライ
動画視聴 (一定時間以上の動画)
フォロー
クリック、シェア、滞在時間

In-Network(フォロー中)
フォローしているアカウントの投稿は優遇されます。

新鮮な投稿 古すぎない
タイムリーな投稿が優先されます。

動画コンテンツ 一定時間以上の動画は
特別な重み付けを受けます。



おすすめに除外されやすくなるポイント

ネガティブシグナル 以下が予測されると
スコアが低下:

興味なし、ブロック、ミュート、報告

ブロック・ミュートしたアカウント
完全に除外されます。

ミュートキーワード
設定したキーワードを含む投稿は除外。

自分自身の投稿
自分の投稿は「For You」から除外。

既に見た投稿
過去に表示された投稿は除外(Bloom Filter使用)。

古すぎる投稿
一定期間以上経過した投稿は除外。

削除済み・スパム・暴力的コンテンツ
最終段階で除外されます。



スコアリングの仕組み

最終スコア = Σ (重み × 各アクションの予測確率)

= P(いいね) × いいね重み
+ P(リツイート) × リツイート重み
+ P(リプライ) × リプライ重み
+ ...
+ P(ブロック) × ブロック重み (負の値)
+ P(ミュート) × ミュート重み (負の値)
処理順序:

1. Phoenix Transformer → ML予測
2. Weighted Scorer → 重み付け結合
3. Author Diversity Scorer → 多様性調整
4. OON Scorer → In/Out-of-Network調整
5. Selection → 上位K件選択



ポジティブシグナルの重み

以下のアクションが予測されると、投稿のスコアが上昇します:

アクション 説明 重要度
いいね (Favorite) ユーザーがいいねする確率 ⭐⭐⭐
リツイート (Retweet) リツイートする確率 ⭐⭐⭐
リプライ (Reply) リプライする確率 ⭐⭐⭐
引用ツイート (Quote) 引用ツイートする確率 ⭐⭐
クリック (Click) 投稿をクリックする確率 ⭐⭐
プロフィールクリック 投稿者のプロフィールをクリック ⭐⭐
動画視聴 (Video View) 動画を視聴する確率 ⭐⭐⭐
画像展開 (Photo Expand) 画像を展開する確率 ⭐⭐
シェア (Share) 外部にシェアする確率 ⭐⭐
滞在時間 (Dwell) 投稿に滞在する時間 ⭐⭐
フォロー (Follow Author) 投稿者をフォローする確率 ⭐⭐⭐


実践的アドバイス

表示されやすくするには:
✅ エンゲージメントを促す投稿(いいね、RT、リプライされやすい)
✅ 動画・画像付きコンテンツ
✅ タイムリーな情報
✅ フォロワーとの関係構築

除外されないために:
❌ スパム的な投稿を避ける
❌ 暴力的・不適切なコンテンツを避ける
❌ ミュートキーワードに引っかからない
❌ 重複投稿を避ける



まとめ

今回のXのアルゴリズム更新のポイントは
「人間による調整を徹底的に排除し
AI(Grokベースのモデル)に判断を委ねたこと」にあります。

システムは「フォロー内」と「フォロー外」の投稿を統合し
膨大なユーザー履歴から
「あなたが次にどのボタン(いいね、リプライ等)を押すか」
を精密に予測して並べ替えます。

また、多様性を確保しつつ、不適切なコンテンツや重複を
二段階のフィルタリングで排除する
非常に高度かつクリーンな構成になっています。


アルゴリズムの詳細コードを見たい方は
ぜひgithubの方を見てみてください

それでは。

今回は競技プログラミングについてです。

解説動画はこちら



競技プログラミングの世界をのぞいてみよう


競技プログラミングとは

プログラミングを「速く・正確に・美しく」解く
頭脳スポーツです。

与えられるのは数行の問題文と、入力例
頭の中でアルゴリズムを組み立て
最速のコードで正答を競います。


競技プログラミングの概要

問題が与えられ、入力例と出力例も与えられます。

問題文から、入力を受け取って
出力例になるようなプログラムコードを書いていきます。

実際の競技では
プログラムコードが開催側のシステム内で実行されて
成否が出るような仕組みになっています。


問題文の例(超初級)

問題:最大値を求めよう

N 個の整数が与えられるので
その中で最大の値を出力してください。

入力例
5
10 3 5 8 2

出力例
10

サンプルコード
N = int(input())
nums = list(map(int, input().split()))
print(max(nums))

通常は計算量や、数値の上限などの制約が与えられます。

正解かどうかの判定は、もっと大掛かりな数値で自動計算されているようで
数が多い場合、制限時間に間に合わないことも有ります。



競技プログラミングの主な大会

AtCoder(日本)
Topcoder(海外)
その他も有るみたいだけど、色々休止中



競技プログラミングはどんなことに役立つのか

1.思考を“構造化”する力が身につく
問題を分解し、条件を抽象化し、最適なアルゴリズムを選ぶ
という一連の思考過程を繰り返し構造化思考力を鍛えることができます

2.アルゴリズムの理解が“AIを使いこなす力”になる
AIが生成したコードを見て
計算量のボトルネック、論理が最適化されているか
入力制約に対応できているか等を判断できます

3.「論理×直感」問題解決能力を鍛える最高のトレーニング
限られた時間と資源の中で最適な解決方法を
論理と直感、両方を磨きながら鍛えることができます

4.キャリアや採用で有利に働く
近年、大企業やスタートアップなどで評価される傾向
アルゴリズムが必要な企業への就職で有利になります




競技プログラミングの問題を解いてみよう


中級くらいの問題集、動画を止めて考えてみてね

問題1 : 文字列の入れ替えチェック(中級)

2つの文字列 S, T が与えられます
S の文字を並べ替えて T にできるなら Yes
できないなら No と出力してください

入力例
listen
silent

出力例
Yes

-------------------------------------------------------------


解説

文字の出現がすべて一致していればOK
sorted(S) == sorted(T) で判定可能です。

S = input().strip()
T = input().strip()
print("Yes" if sorted(S) == sorted(T) else "No")



問題2 : 数字の組み合わせの和(中上級)

N 個の整数が与えられます
この中から3つ選んで、その和が K になる組み合わせの数を求めてください

入力例
5 10
2 3 5 4 1

出力例
2

-------------------------------------------------------------


解説

単純に3重ループで解くコードの場合
3つの数値の和が K になれば OK です。

N, K = map(int, input().split())
A = list(map(int, input().split()))

count = 0
for i in range(N):
    for j in range(i+1, N):
        for k in range(j+1, N):
            if A[i] + A[j] + A[k] == K:
                count += 1
print(count)

ただし実際の競技では
3重ループだと、制限に合わない場合があるので
別の方法を検討することが多いようです。

ここでは一例として次のようなアルゴリズムで
解くこととします。

    1.  配列 A の要素をセット S にしておく(探索用)
    2.  二重ループで全ペア (i, j) を探索
    3.  そのペアの和 A[i] + A[j] を計算
    4.  target = K - (A[i] + A[j]) として、 S に存在すればカウント

これをコードに落とすと次のようになります。
# 入力
N, K = map(int, input().split())
A = list(map(int, input().split()))

# 集合(SET)を作成
S = set(A)
count = 0
seen = set()  # 同じ組み合わせの重複カウント防止用

for i in range(N):
    for j in range(i + 1, N):
        two_sum = A[i] + A[j]
        target = K - two_sum

        # 3つの値がすべて異なることを確認
        if target in S and target != A[i] and target != A[j]:
            # 組み合わせを小さい順にソートして一意化
            triple = tuple(sorted((A[i], A[j], target)))
            if triple not in seen:
                seen.add(triple)
                count += 1

print(count)






問題3 : 最短経路を求める迷路探索(上級)


H×W のマップが与えられ . は通行可
S から G までの最短距離を求めてください
到達できない場合は -1 を出力

入力例
4 5
S....
.###.
..#G.
.....

出力例
7


------------------------------------------


解説

BFS(幅優先探索 : Breadth First Search)で
最短距離を求めていきます。
(開始地点に近いノードから順に「横に広がるように」探していく手法)

入力は一旦省略し、直接データ化したコードです。
from collections import deque

data = """\
4 5
S....
.###.
..#G.
.....
"""

lines = data.strip().splitlines()
H, W = map(int, lines[0].split())
grid = [list(line) for line in lines[1:]]

# スタート(S)とゴール(G)を探して座標を求める
for i in range(H):
    for j in range(W):
        if grid[i][j] == "S":
            sx, sy = i, j
        if grid[i][j] == "G":
            gx, gy = i, j

# 4方向の移動ベクトルと距離配列の初期化
# dx,dyは上下左右の移動を表す、dist は各セルへの最短距離(始点からの距離)
# 訪問したら dist[nx][ny] = dist[x][y] + 1 と更新
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
dist = [[-1]*W for _ in range(H)]

# キュー初期化と始点の距離設定
# 始点をキューに入れて距離 0 をセット
# 以降はキューから取り出すごとに、そのセルから隣接を探索
q = deque()
q.append((sx, sy))
dist[sx][sy] = 0

# BFS のメインループ
# q.popleft() でキューの先頭から取り出し(FIFO)
# 4方向それぞれについて:
#	•	範囲チェック(境界外は無視)
#	•	壁 (#) なら通れないので無視
#	•	dist[nx][ny] == -1 は未訪問の確認(訪問済みならスキップ)
# 未訪問かつ通行可なら距離を +1 してキューに追加
while q:
    x, y = q.popleft()
    for k in range(4):
        nx, ny = x + dx[k], y + dy[k]
        if 0 <= nx < H and 0 <= ny < W:
            if grid[nx][ny] != "#" and dist[nx][ny] == -1:
                dist[nx][ny] = dist[x][y] + 1
                q.append((nx, ny))

# G に到達していれば dist[gx][gy] は非負の最短距離
#	到達していなければ -1(初期値)のまま出力される
print(dist[gx][gy])




まとめ

最適なアルゴリズムが必要な業務には
競技プログラミングの知識が役にたちます。

すごく時間の掛かる処理の高速化、省力化、消費電力低下など
実務面で有効な場面はかなり多いです。

若い人は就職面でも有利になるので、
競技プログラミングに取り組むのかかなりオススメです。



今回は円周率を計算するアルゴリズムを使って
馬鹿でかい円周率を行けるだけ求めてみました

解説動画はこちら





まず最初に問題ですが
円周率の小数点10000桁目の数値は
何になるでしょうか?

こんな問題を解く場合に
馬鹿でかい円周率を求める方法があります。



ガウス=ルジャンドルのアルゴリズム
(Gauss–Legendre algorithm)


円周率を計算する際に用いられる
数学の反復計算アルゴリズム(算術幾何平均法)

円周率計算のアルゴリズムの中でも
トップクラスの収束速度なので、精度が良いらしいです。

アルゴリズムは

スクリーンショット 2024-11-09 16.46.34

となります。


円周率を求める関数のコード

計算精度を設定して、その桁数までを求めていく感じになります。
例えば円周率の小数点100桁まで求めたかったら
計算精度を110-150 とかに設定します。

また反復計算の回数は
log2(x) 以上の回数が必要になるので
計算精度を上げる場合は、反復計算回数も
あわせて上げてください(ここでは20回にしてます)

from decimal import Decimal, getcontext

# 計算精度の設定(小数点以下1万桁以上の精度を確保)
getcontext().prec = 15000

# ガウス=ルジャンドルのアルゴリズムの実装
def gauss_legendre_pi():
    # 初期値設定
    a = Decimal(1)
    b = Decimal(1) / Decimal(2).sqrt()
    t = Decimal(1) / Decimal(4)
    p = Decimal(1)

    # 十分な収束回数で反復計算(math.ceil(math.log2(x))以上)
    for _ in range(20):
        a_next = (a + b) / 2
        b = (a * b).sqrt()
        t -= p * (a - a_next) ** 2
        a = a_next
        p *= 2

    pi_approx = ((a + b) ** 2) / (4 * t)
    return pi_approx

# 円周率の計算
pi_approx = gauss_legendre_pi()
pi_str = str(pi_approx)

# 1万桁目の数値を取得
k = 10000

# 結果を出力
print(f"円周率の小数点以下{k}桁目の数値: {pi_str[k+1]}")
9




まとめ

このPythonコードであれば小数点10万桁くらいまでは余裕です。

それ以上になるとハイスペックな計算資源が必要で
加えてもっと効率の良い高精度計算専用のライブラリを用いたり
並列分散処理などを実装する必要が出てくるかもしれません。

ちなみにこのアルゴリズムでは
2009年に筑波大学の高橋大介という方が
2兆5769億8037万桁
という記録を出しているので
そこから15年以上経った今なら
もっと馬鹿でかい桁まで計算が出来るかもしれません!!

デカいって、いいですよね
男のロマン

どなたか馬鹿でかい円周率の計算
挑戦してみませんか

今回はここまでです
それでは。

 

今回はハノイの塔を解くプログラムについてです。


解説動画はこちら



ハノイの塔(Tower of Hanoi)とは

古来からあるパズルゲーム



以下のルールに従って
すべての円盤を右端の杭に移動させられれば完成です。

・3本の杭と、大きさの異なる複数の円盤から構成
・初期配置は左端の杭に昇順で積み重ねられている
・1回に1枚ずつ移動させるられるが
 小さいものの上に大きな円盤を乗せることはできない


ハノイの塔は
「再帰的な方法」で解くことができる古典的な問題です。

ディスクの数 n、出発点の棒 source
目的地の棒 target、および補助の棒 auxiliaryとします。

基底条件として、ディスクが1枚だけの場合は
sourceからtargetに直接移動
それ以外の場合は、再帰的に以下のステップを実行:

n-1枚のディスクをsourceからauxiliaryに移動
残りの1枚のディスクをsourceからtargetに移動
n-1枚のディスクをauxiliaryからtargetに移動

配置するディスクの数 n を変更することで
他のケースも同様に解くことができます。



ハノイの塔を解くコード

# ハノイの塔を攻略
def hanoi(n, source, target, auxiliary):
    if n == 1:
        print(f"{n}を{source}から{target}に移動")
        return
    hanoi(n-1, source, auxiliary, target)
    print(f"{n}を{source}から{target}に移動")
    hanoi(n-1, auxiliary, target, source)

n = 3
hanoi(n, 'A', 'C', 'B')
1をAからCに移動
2をAからBに移動
1をCからBに移動
3をAからCに移動
1をBからAに移動
2をBからCに移動
1をAからCに移動



ハノイの塔を描画するコード

widgetsを使ってstepごとの画像を描画しています。
# ハノイの塔を描画する
import ipywidgets as widgets
import matplotlib.pyplot as plt
import numpy as np

data,img_data = [],[]

# ディスクの色リスト
colors = ['red', 'green', 'blue', 'purple', 'yellow', 'silver', 'orange', 'pink']

# 棒の位置
positions = {'A': 0, 'B': 1, 'C': 2}

# ハノイの塔を攻略
def hanoi(n, source, target, auxiliary):
    if n == 1:
        data.append([n,source,target])
        return
    hanoi(n-1, source, auxiliary, target)
    data.append([n,source,target])
    hanoi(n-1, auxiliary, target, source)

# ディスクを描画するための関数
def draw_towers(state, step):
    fig, ax = plt.subplots()
    ax.set_xlim(-1, 3)
    ax.set_ylim(0, 5)
    ax.set_xticks([0, 1, 2])
    ax.set_xticklabels(['A', 'B', 'C'])
    ax.set_yticks([])
    for tower in 'ABC':
        for j, disk in enumerate(state[tower]):
            color = colors[disk - 1]
            width = 0.2 * disk
            height = 0.5
            ax.bar(positions[tower], height, bottom=j * height, width=width, color=color, edgecolor='black')
    ax.set_title(f'Step {step}')
    fig.canvas.draw()
    img_data.append(np.array(fig.canvas.renderer.buffer_rgba()))
    plt.close(fig)

# 初期状態
n = 4  # ディスクの数
hanoi(n, 'A', 'C', 'B')
towers = {'A': list(range(n, 0, -1)), 'B': [], 'C': []}
draw_towers(towers, 0)

# 各ステップごとに状態を描画
for step, (disk, source, target) in enumerate(data):
    towers[target].append(towers[source].pop())
    draw_towers(towers, step+1)

# img_data に保存された画像を表示するためのウィジェット
def show_image(step):
    plt.imshow(img_data[step])
    plt.axis('off')
    plt.show()

slider = widgets.IntSlider(value=0, min=0, max=len(img_data)-1, step=1, description='Step:')
widgets.interactive(show_image, step=slider)
スクリーンショット 2024-08-31 12.59.50


終わりに

インドの巨大な寺院の話が元ネタのようです。

天地創造の時に神が64枚の純金の円盤を重ねて置いた
司祭たちはそこで、昼夜を通して円盤を別の柱に移し替えている
全ての円盤の移し替えが終わったときに
世界は崩壊し終焉を迎える・・・



ハノイの塔のstep数は 2のディスクの枚数乗 -1 なので
2 ** 64 -1 stepかかります。

すっごい回数
おじさん達が移し替えてると思うと
大変だなーと思う今日この頃です。

それでは。


今回はRSA暗号について
考えてみることにしました。


解説動画はこちら


さてさて
RSAッて良く分からないので
Wikiで調べてみることにしました。

RSA暗号とは、桁数が大きい合成数の素因数分解問題が
困難であることを安全性の根拠とした公開鍵暗号の一つ
鍵生成、暗号化、復号の3つのアルゴリズムで定義される

うん・・・・・

RSA暗号は次のような方式である

鍵のペア(公開鍵と秘密鍵)を作成して公開鍵を公開する
まず、適当な正整数 E を選択する

また、大きな2つの素数の組み P,Q を生成し
それらの積(N=PQ)を求めて、組みE,N を
平文の暗号化に使用する鍵(公開鍵)とする

2つの素数P,Qは秘密に保管し
暗号文の復号に使用する鍵(秘密鍵)D の生成にも使用する

暗号化(平文 M から暗号文 C を作成する):
復号(暗号文 C から元の平文 M を得る): 
暗号化(E 乗)は公開鍵 E,N があれば容易に計算でき
復号(D 乗)も容易に計算できる

しかし、秘密鍵 D を知らずに
解読(法 N の下で E 乗根を計算)するのは
「N の素因数を知らないと難しい」と考えられている

つまり
「秘密鍵を用いずに暗号文から平文を得ることは難しい」
と信じられている

これがRSA暗号の安全性の根拠である


はい良くわかりませんです!!!


というわけで
サンプルコードを作ってみました。

# RSA暗号の例
import random
import fractions
import sympy
import warnings 
warnings.filterwarnings('ignore')

# 乱数生成
def _random():
    digit = 10
    return random.randrange(10**(digit - 1),10**digit)

# 最小公倍数
def _lcm(p , q):
    return (p * q) // fractions.gcd(p, q)

# 拡張ユークリッド
def _euclid(x,y):
    c0, c1 = x, y
    a0, a1 = 1, 0
    b0, b1 = 0, 1
    while c1 != 0:
        m = c0 % c1
        q = c0 // c1
        c0, c1 = c1, m
        a0, a1 = a1, (a0 - q * a1)
        b0, b1 = b1, (b0 - q * b1)
    return c0, a0, b0

# キー生成
def generate_key(p = 0,q = 0,e = 0,d = 0,n = 0,l = 0):
    if p == 0:
        while True:
            p = _random()
            if sympy.isprime(p):break
    _p = p
    if q == 0:
        while True:
            q = _random()
            if sympy.isprime(q) and p != q:break
    _q = q
    if n == 0:
        n = p * q
    _n = n
    if l == 0:
        l = _lcm(p - 1, q  - 1)
    _l = l
    if e == 0:
        while True:
            i = random.randint(2,l)
            if fractions.gcd(i, l) == 1:
                e = i
                break
    _e = e
    if d == 0:
        _c, a, _b = _euclid(e, l)
        d = a % l
    _d = d
    return _e,_d,_n,_p,_q,_l

# 暗号化
def encrypt(_e,_n,plaintext):
    st,ciphertext = "",[]
    for i in map((lambda x: pow(ord(x), _e,_n)),list(plaintext)):
        ciphertext.append(i)
        st += str(i)
    return st,ciphertext

# 復号化
def decrypt(_d,_n,ciphertext):
    cip , st = [] , ""
    for i in  list(ciphertext):
        tmp = chr(pow(i, _d,_n))
        cip.append(tmp)
        st += str(tmp)
    return st

使う際は平文として暗号化したい
文字列を定義しておきます。

plain_text = '文字列を入力'


早速使っていきましょう。
暗号化するところと
復号化するところのコードです。
# 初期化
ciphertext = []
_e = _d = _n = _p = _q = _l = 0

# キー生成
_e,_d,_n,_p,_q,_l = generate_key(0,0,65537)

# 暗号化
e_text , ciphertext = encrypt(_e,_n,plain_text)

# 復号化
d_text = decrypt(_d,_n,ciphertext)

print('素数 p : {0}'.format(_p))
print('素数 q : {0}'.format(_q))
print('l : {0}'.format(_l))
print('公開鍵 e : {0}'.format(_e))
print('公開鍵 n : {0}'.format(_n))
print('秘密鍵 d : {0}'.format(_d))
print()

print('暗号文(String) : {0}'.format(e_text))
print()
print('暗号文(List) : {0}'.format(ciphertext))

素数 p : 9558530557
素数 q : 5377612577
l : 12850518531506468064
公開鍵 e : 65537
公開鍵 n : 51402074140962015389
秘密鍵 d : 104902992421928993

暗号文(String) : 502447033995121916661752375033108949410513472439923007515854175237503310894941051347243992300751585434094647152221189902182494137669912247793511588278946816434351158827894681643422454674385942603378

暗号文(List) : [50244703399512191666, 17523750331089494105, 13472439923007515854, 17523750331089494105, 13472439923007515854, 34094647152221189902, 18249413766991224779, 3511588278946816434, 3511588278946816434, 22454674385942603378]

素数P,Qや
鍵N,Dは毎回変わってしまいます。

公開鍵Nと秘密鍵Dがあれば
暗号を解読することができます。

暇な方は上記の鍵と暗号文から
復号してみてくださいね。

人類を平和にする
「あいことば」を暗号にしてみましたよ

解読面倒な方は
動画見て下さいねーー


このサンプルコードでは
およそ20桁ほどの秘密鍵になりますんで
9千京回ほどブルートフォースすれば
暗号解読できるかもしれません!!!!

鼻血出せば解けるかもしれませんねえ
そんなアニメが有るとか無いとか

自分ならやらないっすねーー

今回はここまででーす
それでは。



このページのトップヘ