Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# 承知しました。以下は、LeetCode形式に完全準拠した **Python(3.11.4)による「回文判定」関数の実装**です。
# 文字列変換を使わず、処理時間・メモリ使用量にも配慮した解法です。

# ## ✅ 問題文要約

# > 整数 `x` が与えられたとき、それが回文であるなら `True` を、そうでなければ `False` を返してください。
# > **ただし、文字列変換を使わない実装が推奨されます。**

# ## ✅ 実装:LeetCode形式(Python + 型ヒント + 最適化)

class Solution:
def isPalindrome(self, x: int) -> bool:
# 負数や末尾0(0を除く)は回文にはなり得ない
if x < 0 or (x % 10 == 0 and x != 0):
return False

reverted: int = 0
while x > reverted:
reverted = reverted * 10 + x % 10
x //= 10

# 偶数桁: x == reverted、奇数桁: x == reverted // 10
return x == reverted or x == reverted // 10

# ## ✅ 処理の説明(Follow-up 条件満たす)

# | ステップ | 説明 |
# | ------ | ----------------------------------------------------- |
# | 入力前処理 | 負数または末尾が0の数値(0は除く)は絶対に回文にならない |
# | 数値反転処理 | `x` の後半部分だけを `reverted` に反転しながら保持 |
# | 判定 | `x == reverted` または `x == reverted // 10` で中央の桁を除いた比較 |


# ## ✅ 時間計算量・メモリ使用量

# | 項目 | 内容 |
# | ---------- | ---------------------------------------- |
# | **時間計算量** | O(log₁₀x) → 桁数分だけループ(最大で10回程度) |
# | **空間計算量** | O(1) → 変数 `x`, `reverted` の2つ(定数個)しか使わない |
# | **使用メモリ例** | 約 16〜24 bytes(整数2個、内部処理含む) |


# ## ✅ 動作例(内部での動き)

# 例: `x = 1221`

# | 反転途中 | x | reverted |
# | ---- | -------------------- | -------- |
# | 1回目 | 122 | 1 |
# | 2回目 | 12 | 12 |
# | 判定 | 12 == 12 → True(偶数桁) | |


# ## ✅ メリットと特徴

# * 🚫 `str()`や`[::-1]`などの文字列操作を一切使わない
# * 🚀 速度も空間効率も非常に良い
# * 💯 LeetCodeの「Follow up」条件も完全クリア

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 以下は、TypeScript を用いて **整数が回文かどうかを判定する**プログラムです。
// `fs` を使って標準入力から値を読み取り、**整数変換なし**(文字列に変換しない)で回文を判定します。

// ---

// ### ✅ 要件まとめ

// * `fs` 使用による標準入力対応。
// * `x` を文字列に変換せずに回文か判定。
// * 計算量とメモリ量を抑えた実装。

// ---

// ### ✅ TypeScript 実装(`fs` 使用・整数のみ)

// palindrome.ts
import * as fs from 'fs';

function isPalindrome(x: number): boolean {
// 負の数や10の倍数(ただし0は除く)は回文にならない
if (x < 0 || (x % 10 === 0 && x !== 0)) return false;

let reverted = 0;
let original = x;

// 半分だけ反転させる
while (x > reverted) {
reverted = reverted * 10 + x % 10;
x = Math.floor(x / 10);
}

// xが奇数桁の時はreverted/10で中央の数字を削除
return x === reverted || x === Math.floor(reverted / 10);
}

// 標準入力から読み込む
const input = fs.readFileSync('/dev/stdin', 'utf-8').trim();
const x = parseInt(input);

console.time('exec');
const result = isPalindrome(x);
console.timeEnd('exec');

console.log(result);
// ### ✅ 使用方法(例)

// 以下のように、値を標準入力に渡して実行します:

// ```bash
// echo 121 | ts-node palindrome.ts
// # 出力: true
// ```

// ```bash
// echo -121 | ts-node palindrome.ts
// # 出力: false
// ```

// ```bash
// echo 10 | ts-node palindrome.ts
// # 出力: false
// ```

// ---

// ### ✅ 計算量・メモリ使用量

// * 時間計算量:O(log₁₀(x))(最大で10桁程度)
// * 空間計算量:O(1)(定数変数のみ使用)

// ---

// ### ✅ 解法ポイント(Follow up 対応)

// * **文字列変換を避ける**ため、整数の下位桁から数を逆に構築。
// * 逆数が元の数と一致すれば回文。
// * 途中で反転数が元の数を超えたら、中央を跨いだので比較可能。
129 changes: 129 additions & 0 deletions Algorithm/Palindrome/leetcode/9. Palindrome Number/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
TypeScriptでの「整数が回文かどうか判定する処理」について、**各ステップを図解付きで具体的に解説**します。
今回は文字列変換をせず、整数のまま判定するアルゴリズムに基づきます。

---

## 🔢 処理の流れ

### Step 1: 入力の前処理(負数や10の倍数チェック)

```ts
if (x < 0 || (x % 10 === 0 && x !== 0)) return false;
```

#### 📘 理由:

* **負数**(例: `-121`)は、符号があるため回文にはならない。
* **末尾0の数**(例: `10`)は、反転すると `01` になり、回文でない。

#### 📊 イメージ:

```
x = -121 → NG("-" がつく)

x = 10
-> 10 を反転 → 01(≠10) → NG
```

---

### Step 2: 反転した下半分の数 `reverted` を構築

```ts
let reverted = 0;
while (x > reverted) {
reverted = reverted * 10 + x % 10;
x = Math.floor(x / 10);
}
```

#### 🔁 数字を半分反転(下位から1桁ずつ)

**例:x = 1221**

| ループ | x | reverted | 処理内容 |
| ---- | ---- | -------- | ------------------------------- |
| 初期 | 1221 | 0 | |
| ① | 122 | 1 | reverted = 0×10 + 1 |
| ② | 12 | 12 | reverted = 1×10 + 2 |
| (終了) | | | x (=12) ≯ reverted (=12) → stop |

#### 🖼️ 図解:

```
1221 の右半分 "21" を左側に反転して構築

x = 12 ← 元の左半分
reverted = 12 ← 右側の反転結果

x === reverted → 回文!
```

---

### Step 3: 偶数・奇数桁の調整と比較

```ts
return x === reverted || x === Math.floor(reverted / 10);
```

#### ✅ 比較内容:

* 偶数桁: `x == reverted`
* 奇数桁: `x == Math.floor(reverted / 10)`

#### 例①:x = 1221(偶数桁)

```
→ x = 12, reverted = 12
→ 12 === 12 → ✅ 回文
```

#### 例②:x = 12321(奇数桁)

| 最後 | x = 123 | reverted = 123 |
| ----------------- | ------- | -------------- |
| 最後の桁が中央の3 → 1桁落とす | | |

```
→ x = 12, Math.floor(123 / 10) = 12
→ 12 === 12 → ✅ 回文
```

---

## 🧠 なぜ半分だけ反転するのか?

文字列にせず、**後ろ半分の数字だけ反転して前半と比較**することで:

* **オーバーフロー回避**
* **時間・メモリの効率化**

---

## 💡 全体フローチャート

```plaintext
入力整数 x を受け取る
x が負数 または 末尾0(かつ0でない)なら false
reverted = 0
while x > reverted:
reverted = reverted * 10 + x % 10
x = Math.floor(x / 10)
x == reverted または x == Math.floor(reverted / 10)
Yes → true No → false
```

---

## 📦 補足:メモリ&処理量の工夫点

* メモリ使用:O(1)(整数3つのみ使用)
* 時間計算量:O(log₁₀(x))(最大で10回のループ)

---
127 changes: 127 additions & 0 deletions Algorithm/RSA encryption/ASCII code expansion/ASCIICodeExpansion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// 以下は、**RSA復号処理 + ASCIIコード展開(28ビット → 7ビット×4分割)** を行うJavaScriptコードです。
// `fs` モジュールで標準入力から値を取得し、**実行時間・メモリの消費を抑えた実装**になっています。

// ---

// ## ✅ 処理概要

// 1. 入力:`n`, `e`, `E`
// 2. φ(n) を求めるために、`n` を素因数分解 → `p`, `q` を得る
// 3. `φ(n) = (p-1)(q-1)` を計算
// 4. `d = e⁻¹ mod φ(n)` を求める(拡張ユークリッド)
// 5. `M = E^d mod n`(繰り返し二乗法)
// 6. `M` を28ビットで見て、7ビットごとに区切って文字列化

// ---

// ## ✅ コード(Node.js)

const fs = require('fs');

// 入力取得
const input = fs.readFileSync(0, 'utf8').trim();
const [nRaw, eRaw, Eraw] = input.split(' ').map(BigInt);

const n = nRaw;
const e = eRaw;
const E = Eraw;

// 素因数分解(p, q)
// n は 10^10 以下なので √n まで試せば良い
function findFactors(n) {
const sqrtN = BigInt(Math.floor(Math.sqrt(Number(n))));
for (let i = 2n; i <= sqrtN; i++) {
if (n % i === 0n) {
return [i, n / i];
}
}
return [1n, n]; // fallback
}

// 拡張ユークリッド互除法で逆元を求める
function modInv(a, m) {
let m0 = m, x0 = 0n, x1 = 1n;
while (a > 1n) {
const q = a / m;
[a, m] = [m, a % m];
[x0, x1] = [x1 - q * x0, x0];
}
return x1 < 0n ? x1 + m0 : x1;
}

// 繰り返し二乗法で a^b % m を高速計算
function modPow(base, exp, mod) {
let result = 1n;
base = base % mod;
while (exp > 0n) {
if (exp % 2n === 1n) {
result = (result * base) % mod;
}
base = (base * base) % mod;
exp = exp / 2n;
}
return result;
}

// 1. 素因数分解
const [p, q] = findFactors(n);

// 2. φ(n) = (p-1)(q-1)
const phi = (p - 1n) * (q - 1n);

// 3. 秘密鍵 d = e^-1 mod φ(n)
const d = modInv(e, phi);

// 4. 復号処理 M = E^d mod n
const M = modPow(E, d, n);

// 5. 28ビットを 7ビット × 4 に分割し ASCII 変換
const chars = [];
let temp = M;
for (let i = 0; i < 4; i++) {
const charCode = Number(temp & 0b1111111n); // 下位7ビット
if (charCode !== 0) {
chars.unshift(String.fromCharCode(charCode));
}
temp >>= 7n;
}

// 出力
console.log(chars.join(''));

// ## ✅ 実行例

// ### 入力:

// ```
// 3995747143 3007 602607029
// ```

// ### 出力:

// ```
// PAIZ
// ```

// ---

// ## ✅ 実行時間・メモリ分析

// | ステップ | 時間計算量 | 備考 |
// | --------------- | ----------- | ------------------------- |
// | 素因数分解 | O(√n) | n ≤ 10^10 なので最大 10^5 回ループ |
// | 逆元計算(modInv) | O(log φ(n)) | log(10^10) ≈ 33 回以下 |
// | 繰り返し二乗法(modPow) | O(log d) | 非常に高速 |
// | ビット操作&変換 | O(1) | 最大4文字分 |
// | **総メモリ使用量** | 数百 KB 程度 | BigInt 計算のために多少のオーバーヘッドあり |

// ---

// ## ✅ 補足

// * 暗号文(`E`)が 28 ビットの復号文 `M` を生成する前提です。
// * `M` は ASCII コードの7ビット(0〜127)範囲の文字しか使わない設計です。

// ---

// ご希望があれば、RSAの暗号化側(E = M^e mod n)コードや、多文字列対応の拡張版なども提供可能です。お気軽にどうぞ!
Loading