diff --git a/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README.md b/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README.md index 1837699c..0a32050d 100644 --- a/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README.md +++ b/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README.md @@ -139,7 +139,6 @@ graph LR | 基本版(Array.from) | ~158ms | ~69MB | 可読性高、標準的 | | 最適化版(ビット演算) | 154ms | 69.54MB | ビット演算で高速化 | | 高速化版(変数キャッシング) | 158ms | 69.10MB | 更なる高速化 | -| メモリ最優先版 | 148ms | 67.10MB | メモリ効率最大化 | _\*数値は特定環境での測定例です_ @@ -338,7 +337,7 @@ const lastRow = rows - 1; 5. **空配列** ```typescript - [].snail(1, 0); // → [] (入力サイズ 0) + [].snail(0, 0); // → [] (1×1=1 ≠ 0のため空配列を返す) ``` 6. **標準ケース(偶数列)** diff --git a/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html b/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html index 561c28a3..074089ed 100644 --- a/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html +++ b/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html @@ -5,11 +5,8 @@ LeetCode: Snail Traversal - 蛇行パターンで1D→2D配列変換 - - + + @@ -23,19 +20,19 @@ @@ -251,8 +248,10 @@

戦略のポイント< TypeScript実装(最適化版)

-
declare interface Array {
-    snail(rowsCount: number, colsCount: number): T[][];
+                
declare global {
+    interface Array<T> {
+        snail(this: T[], rowsCount: number, colsCount: number): T[][];
+    }
 }
 
 /**
@@ -1297,18 +1296,20 @@ 

実装方法の比較<

Snail Traversalパターン:

- {visual.result2d[0].map((_, colIdx) => { - const isEvenCol = colIdx % 2 === 0; - const colValues = isEvenCol - ? visual.result2d.map(r => r[colIdx]) - : [...visual.result2d].reverse().map(r => r[colIdx]); - - return ( -
  • - • 列{colIdx}: {isEvenCol ? '上から下' : '下から上'} [{colValues.join(', ')}] -
  • - ); - })} +
      + {visual.result2d[0].map((_, colIdx) => { + const isEvenCol = colIdx % 2 === 0; + const colValues = isEvenCol + ? visual.result2d.map(r => r[colIdx]) + : [...visual.result2d].reverse().map(r => r[colIdx]); + + return ( +
    • + • 列{colIdx}: {isEvenCol ? '上から下' : '下から上'} [{colValues.join(', ')}] +
    • + ); + })} +
    )} @@ -1619,10 +1620,5 @@

    const root = ReactDOM.createRoot(document.getElementById('react-root')); root.render(); - - - - - diff --git a/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/Snail_Traversal_TS.ipynb b/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/Snail_Traversal_TS.ipynb index 020a7b49..480c550e 100644 --- a/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/Snail_Traversal_TS.ipynb +++ b/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/Snail_Traversal_TS.ipynb @@ -1,364 +1,129 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "d407fbea", - "metadata": {}, - "source": [ - "# TypeScript コーディング問題:Snail Traversal 配列変換\n", - "\n", - "## 1. 問題の分析\n", - "\n", - "### 競技プログラミング視点での分析\n", - "- **実行速度最優先**: 配列の1回のループで解決可能(O(n))\n", - "- **メモリ最小化**: 結果配列のみを保持、インデックス計算で実現\n", - "- **最適化ポイント**: 不要な中間配列の生成を避ける、ループ内の条件分岐を最小化\n", - "\n", - "### 業務開発視点での分析\n", - "- **型安全性**: prototypeの拡張における型定義の正確性\n", - "- **エラーハンドリング**: 無効な入力の早期検出とバリデーション\n", - "- **保守性**: コードの意図が明確で、変更に強い設計\n", - "- **副作用**: thisの参照は読み取りのみ、純粋な変換処理\n", - "\n", - "### TypeScript特有の考慮点\n", - "- **型推論**: `this`の型が`T[]`として推論される\n", - "- **ジェネリクス**: `Array`のTを維持しながら`number[][]`を返す\n", - "- **null安全性**: prototypeメソッドでは`this`が常に存在\n", - "- **readonly考慮**: 元配列を変更せず、新しい配列を生成\n", - "\n", - "## 2. アルゴリズムアプローチ比較\n", - "\n", - "| アプローチ | 時間計算量 | 空間計算量 | TS実装コスト | 型安全性 | 可読性 | 備考 |\n", - "|---------|----------|-----------|------------|---------|-------|------|\n", - "| 数学的インデックス計算 | O(n) | O(n) | 低 | 高 | 高 | 推奨:最も効率的 |\n", - "| 列ごとの配列構築 | O(n) | O(n) | 中 | 高 | 中 | 中間配列が増える |\n", - "| 2段階走査 | O(n) | O(n) | 高 | 中 | 低 | 不要な複雑性 |\n", - "\n", - "## 3. 選択したアルゴリズムと理由\n", - "\n", - "### 選択したアプローチ\n", - "**数学的インデックス計算による1パス実装**\n", - "\n", - "### 理由\n", - "- **計算量的優位性**: O(n)の時間計算量、O(n)の空間計算量(結果配列のみ)\n", - "- **TypeScript環境での型安全性**: \n", - " - インデックス計算は全て型安全な数値演算\n", - " - 配列アクセスは境界チェックが明確\n", - "- **保守性・可読性**: \n", - " - ロジックが単一ループで完結\n", - " - 列が奇数/偶数で方向が変わるパターンが明確\n", - "\n", - "### TypeScript特有の最適化ポイント\n", - "- **コンパイル時型チェック**: 配列操作の安全性を保証\n", - "- **型推論活用**: 不要な型注釈を省略し、コードを簡潔に\n", - "- **strict mode**: 潜在的なundefinedアクセスを防止\n", - "\n", - "## 4. 実装コード\n", - "\n", - "```typescript\n", - "declare global {\n", - " interface Array {\n", - " snail(rowsCount: number, colsCount: number): T[][];\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * 1D配列をSnail traversal patternで2D配列に変換\n", - " * \n", - " * @param rowsCount - 結果の行数\n", - " * @param colsCount - 結果の列数\n", - " * @returns 2D配列(Snail pattern)、無効な入力の場合は空配列\n", - " * @complexity Time: O(n), Space: O(n) where n = this.length\n", - " * \n", - " * @description\n", - " * Snail traversal: 最初の列を上から下、次の列を下から上、という形で\n", - " * 列ごとに方向を交互に変えながら配列を配置する\n", - " * \n", - " * @example\n", - " * [1,2,3,4,5,6].snail(2, 3) \n", - " * // [[1,4,5], [2,3,6]]\n", - " * // 列0: [1,2](下向き), 列1: [3,4](上向き), 列2: [5,6](下向き)\n", - " */\n", - "Array.prototype.snail = function(this: T[], rowsCount: number, colsCount: number): T[][] {\n", - " // 入力バリデーション(早期リターン)\n", - " if (rowsCount * colsCount !== this.length) {\n", - " return [];\n", - " }\n", - " \n", - " \n", - " // 結果配列の初期化(型安全な2D配列)\n", - " const result: T[][] = Array.from(\n", - " { length: rowsCount }, \n", - " () => new Array(colsCount)\n", - " );\n", - " \n", - " // Snail traversal pattern実装\n", - " for (let i = 0; i < this.length; i++) {\n", - " // 現在の要素がどの列に属するかを計算\n", - " const col = Math.floor(i / rowsCount);\n", - " \n", - " // 列内での位置(0-indexed)\n", - " const positionInCol = i % rowsCount;\n", - " \n", - " // 列が偶数: 上から下(順方向)\n", - " // 列が奇数: 下から上(逆方向)\n", - " const row = col % 2 === 0 \n", - " ? positionInCol \n", - " : rowsCount - 1 - positionInCol;\n", - " \n", - " // 型安全な代入(this[i]はT型として推論される)\n", - " result[row]![col] = this[i];\n", - " }\n", - " \n", - " return result;\n", - "};\n", - "\n", - "/**\n", - " * 使用例:\n", - " * const arr = [1,2,3,4];\n", - " * arr.snail(1,4); // [[1,2,3,4]]\n", - " * \n", - " * const arr2 = [19,10,3,7,9,8,5,2,1,17,16,14,12,18,6,13,11,20,4,15];\n", - " * arr2.snail(5,4);\n", - " * // [\n", - " * // [19,17,16,15],\n", - " * // [10,1,14,4],\n", - " * // [3,2,12,20],\n", - " * // [7,5,18,11],\n", - " * // [9,8,6,13]\n", - " * // ]\n", - " */\n", - "\n", - "// Analyze Complexity\n", - "// Runtime 158 ms\n", - "// Beats 60.90%\n", - "// Memory 69.73 MB\n", - "// Beats 66.03%\n", - "\n", - "```\n", - "\n", - "## TypeScript固有の最適化観点\n", - "\n", - "### 型安全性の活用\n", - "\n", - "1. **Prototype拡張の型定義**\n", - " - `declare global`で型定義を拡張\n", - " - `Array`インターフェースへの安全な追加\n", - " - 戻り値型`T[][]`を明示的に定義\n", - "\n", - "2. **型推論の活用**\n", - " - `this`が自動的に`T[]`として推論される\n", - " - `Array.from`のジェネリクス推論\n", - " - ループ内の変数型が自動推論される\n", - "\n", - "3. **null安全性**\n", - " - `result[row]![col]`で非null assertion(配列境界は数学的に保証済み)\n", - " - `this[i]`でLeetCode形式の型変換\n", - "\n", - "### コンパイル時最適化\n", - "\n", - "1. **効率的な配列初期化**\n", - " - `Array.from`によるメモリ効率的な2D配列生成\n", - " - 事前にサイズが確定しているため再割り当て不要\n", - "\n", - "2. **インライン計算**\n", - " - 列と行のインデックス計算が単純な算術演算\n", - " - JITコンパイラーによる最適化が期待できる\n", - "\n", - "3. **不要な中間配列の排除**\n", - " - 1回のループで直接結果配列に書き込み\n", - " - メモリコピーを最小化\n", - "\n", - "### 開発効率と保守性\n", - "\n", - "- **明確な変数名**: `col`, `positionInCol`, `row`で意図が明確\n", - "- **コメントによる説明**: アルゴリズムの各ステップを文書化\n", - "- **エッジケースの明示的処理**: 無効入力と空配列の早期リターン\n", - "- **数学的正確性**: モジュロ演算による方向切り替えロジックが明確\n", - "\n", - "優秀な結果です!上位60-66%は十分高パフォーマンスですが、さらなる最適化の余地があります。以下の改善版を提案します。\n", - "\n", - "## 改善ポイントの分析\n", - "\n", - "### 現在のボトルネック\n", - "1. **Array.from + new Array**: 2段階の配列生成でオーバーヘッド\n", - "2. **非null assertion (!)**: 微小な実行時チェック\n", - "3. **型キャスト (as number)**: 不要なランタイムコスト\n", - "4. **Math.floor**: 整数除算で代替可能\n", - "\n", - "## 最適化版実装\n", - "\n", - "```typescript\n", - "declare global {\n", - " interface Array {\n", - " snail(rowsCount: number, colsCount: number): T[][];\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * 1D配列をSnail traversal patternで2D配列に変換(最適化版)\n", - " * \n", - " * @param rowsCount - 結果の行数\n", - " * @param colsCount - 結果の列数\n", - " * @returns 2D配列(Snail pattern)、無効な入力の場合は空配列\n", - " * @complexity Time: O(n), Space: O(n)\n", - " */\n", - "Array.prototype.snail = function(this: T[], rowsCount: number, colsCount: number): T[][] {\n", - " // 早期リターン最適化\n", - " const n = this.length;\n", - " if (rowsCount * colsCount !== n) return [];\n", - " \n", - " // 1段階での配列初期化(メモリ効率向上)\n", - " const result: T[][] = [];\n", - " for (let i = 0; i < rowsCount; i++) {\n", - " result[i] = [];\n", - " }\n", - " \n", - " // ビット演算での偶奇判定 + 整数除算\n", - " for (let i = 0; i < n; i++) {\n", - " const col = (i / rowsCount) | 0; // Math.floorより高速\n", - " const pos = i % rowsCount;\n", - " const row = (col & 1) ? rowsCount - 1 - pos : pos; // col % 2の最適化\n", - " \n", - " result[row][col] = this[i];\n", - " }\n", - " \n", - " return result;\n", - "};\n", - "\n", - "// Analyze Complexity\n", - "// Runtime 154 ms\n", - "// Beats 69.87%\n", - "// Memory 69.54 MB\n", - "// Beats 71.79%\n", - "\n", - "```\n", - "\n", - "## さらなる高速化版(Top 10%目標)\n", - "\n", - "```typescript\n", - "declare global {\n", - " interface Array {\n", - " snail(rowsCount: number, colsCount: number): T[][];\n", - " }\n", - "}\n", - "\n", - "Array.prototype.snail = function(this: T[], rowsCount: number, colsCount: number): T[][] {\n", - " const n = this.length;\n", - " \n", - " // バリデーション統合\n", - " if (rowsCount * colsCount !== n) return [];\n", - " \n", - " // 事前割り当て(キャッシュ効率向上)\n", - " const result: T[][] = new Array(rowsCount);\n", - " \n", - " // 行の事前生成をループ外で\n", - " let i = rowsCount;\n", - " while (i--) result[i] = new Array(colsCount);\n", - " \n", - " // メインループ:変数キャッシング\n", - " const rows = rowsCount;\n", - " const lastRow = rows - 1;\n", - " \n", - " for (i = 0; i < n; i++) {\n", - " const col = (i / rows) | 0;\n", - " const pos = i - col * rows; // モジュロ演算を減算に変換\n", - " const row = col & 1 ? lastRow - pos : pos;\n", - " \n", - " result[row][col] = this[i];\n", - " }\n", - " \n", - " return result;\n", - "};\n", - "\n", - "// Analyze Complexity\n", - "// Runtime 158 ms\n", - "// Beats 60.90%\n", - "// Memory 69.10 MB\n", - "// Beats 87.82%\n", - "\n", - "```\n", - "\n", - "## 主要な最適化テクニック\n", - "\n", - "### 1. **ビット演算の活用**\n", - "```typescript\n", - "// 前: col % 2 === 0\n", - "// 後: col & 1 (偶奇判定が約2倍高速)\n", - "```\n", - "\n", - "### 2. **整数除算の最適化**\n", - "```typescript\n", - "// 前: Math.floor(i / rowsCount)\n", - "// 後: (i / rowsCount) | 0 (ビットOR演算で整数化、約30%高速)\n", - "```\n", - "\n", - "### 3. **モジュロ演算の削減**\n", - "```typescript\n", - "// 前: i % rowsCount\n", - "// 後: i - col * rowsCount (既に計算済みのcolを再利用)\n", - "```\n", - "\n", - "### 4. **配列初期化の最適化**\n", - "```typescript\n", - "// 前: Array.from({ length: rowsCount }, () => new Array(colsCount))\n", - "// 後: while (i--) result[i] = new Array(colsCount)\n", - "// デクリメントループは最適化されやすい\n", - "```\n", - "\n", - "### 5. **変数のキャッシング**\n", - "```typescript\n", - "const rows = rowsCount;\n", - "const lastRow = rows - 1;\n", - "// ループ内での繰り返し計算を回避\n", - "```\n", - "\n", - "## 期待される改善結果\n", - "\n", - "| 項目 | 現在 | 最適化版 | 高速化版 |\n", - "|-----|------|---------|---------|\n", - "| Runtime | 158ms (60%) | 154ms | 158ms |\n", - "| Memory | 69.73MB (66%) | 69.54MB | 69.10MB |\n", - "\n", - "## メモリ最優先版(Memory Beats 90%+目標)\n", - "\n", - "```typescript\n", - "Array.prototype.snail = function(this: T[], rowsCount: number, colsCount: number): T[][] {\n", - " if (rowsCount * colsCount !== this.length) return [];\n", - " \n", - " const result: T[][] = Array(rowsCount);\n", - " \n", - " for (let r = 0; r < rowsCount; r++) {\n", - " result[r] = Array(colsCount);\n", - " }\n", - " \n", - " for (let i = 0, n = this.length; i < n; i++) {\n", - " const c = (i / rowsCount) | 0;\n", - " const pos = i - c * rowsCount;\n", - " const row = (c & 1) ? rowsCount - 1 - pos : pos;\n", - " result[row][c] = this[i];\n", - " }\n", - " \n", - " return result;\n", - "};\n", - "\n", - "// Analyze Complexity\n", - "// Runtime 148 ms\n", - "// Beats 91.67%\n", - "// Memory 67.10 MB\n", - "// Beats 100.00%\n", - "\n", - "```\n", - "\n", - "**推奨**: まずは**最適化版**を試してください。可読性とパフォーマンスのバランスが最良です。Top 10%を目指す場合は**高速化版**をお試しください。" - ] - } - ], - "metadata": { - "language_info": { - "name": "typescript" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file + "cells": [ + { + "cell_type": "markdown", + "id": "1e8e2d4d", + "metadata": {}, + "source": [ + "# Array Snail Traversal (TypeScript)\n", + "\n", + "## 概要\n", + "\n", + "1次元配列を「Snail Traversal(蛇行)」パターンで2次元配列に変換する `snail` メソッドを `Array.prototype` に拡張します。\n", + "\n", + "- 入力: `rowsCount` (行数), `colsCount` (列数)\n", + "- 制約: `rowsCount * colsCount === nums.length` でなければ空配列 `[]` を返す\n", + "- アルゴリズム: 数学的インデックス計算によるO(n)変換\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5d03a11", + "metadata": {}, + "outputs": [], + "source": [ + "// 型定義の拡張\n", + "declare global {\n", + " interface Array {\n", + " snail(rowsCount: number, colsCount: number): T[][];\n", + " }\n", + "}\n", + "\n", + "// 実装\n", + "Array.prototype.snail = function (rowsCount: number, colsCount: number): T[][] {\n", + " // 入力バリデーション\n", + " if (rowsCount * colsCount !== this.length) {\n", + " return [];\n", + " }\n", + "\n", + " // 結果配列の初期化\n", + " const result: T[][] = [];\n", + " for (let i = 0; i < rowsCount; i++) {\n", + " result[i] = [];\n", + " }\n", + "\n", + " // Snail traversal pattern\n", + " for (let i = 0; i < this.length; i++) {\n", + " // 列番号: インデックスを行数で割った商\n", + " const col = Math.floor(i / rowsCount);\n", + " \n", + " // 列内での位置: インデックスを行数で割った余り\n", + " const positionInCol = i % rowsCount;\n", + " \n", + " // 行番号の決定ルール:\n", + " // 偶数列(0, 2, 4...): 上から下へ (row = positionInCol)\n", + " // 奇数列(1, 3, 5...): 下から上へ (row = rowsCount - 1 - positionInCol)\n", + " const row = col % 2 === 0 ? positionInCol : rowsCount - 1 - positionInCol;\n", + " \n", + " result[row][col] = this[i];\n", + " }\n", + "\n", + " return result;\n", + "};" + ] + }, + { + "cell_type": "markdown", + "id": "c92a9b3e", + "metadata": {}, + "source": [ + "## 動作確認\n", + "\n", + "### ケース1: 基本的な例\n", + "```typescript\n", + "const nums = [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15];\n", + "const result = nums.snail(5, 4);\n", + "console.log(result);\n", + "```\n", + "期待される出力:\n", + "```\n", + "[\n", + " [19,17,16,15],\n", + " [10,1,14,4],\n", + " [3,2,12,20],\n", + " [7,5,18,11],\n", + " [9,8,6,13]\n", + "]\n", + "```\n", + "\n", + "### ケース2: サイズ不一致\n", + "```typescript\n", + "[1,2,3].snail(1, 2); // -> []\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "e4f5a6b7", + "metadata": {}, + "source": [ + "## 実装の詳細解説\n", + "\n", + "1. **型拡張**: `declare global` ブロック内で `Array` インターフェースを拡張し、`snail` メソッドを追加します。\n", + " - `T[][]`を返す: 要素の型 `T` を維持した2次元配列\n", + "\n", + "2. **バリデーション**: `rowsCount * colsCount !== this.length` の場合、直ちに空配列を返します。\n", + "\n", + "3. **インデックス計算**: 各要素 `this[i]` が配置される `(row, col)` を計算します。\n", + " - `col`: `Math.floor(i / rowsCount)`\n", + " - `row`: 列が偶数なら `i % rowsCount`、奇数なら `rowsCount - 1 - (i % rowsCount)`" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "TypeScript", + "language": "typescript", + "name": "typescript" + }, + "language_info": { + "file_extension": ".ts", + "mimetype": "text/typescript", + "name": "typescript", + "version": "5.3.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Mathematics/Number Theory/HuckerRank/Easy/Constructing_a_Number.ipynb b/Mathematics/Number Theory/HackerRank/Easy/Constructing_a_Number.ipynb similarity index 100% rename from Mathematics/Number Theory/HuckerRank/Easy/Constructing_a_Number.ipynb rename to Mathematics/Number Theory/HackerRank/Easy/Constructing_a_Number.ipynb diff --git a/Mathematics/Number Theory/HuckerRank/Easy/Primitive_Problem.html b/Mathematics/Number Theory/HackerRank/Easy/Primitive_Problem.html similarity index 98% rename from Mathematics/Number Theory/HuckerRank/Easy/Primitive_Problem.html rename to Mathematics/Number Theory/HackerRank/Easy/Primitive_Problem.html index 1a6f3f46..43653483 100644 --- a/Mathematics/Number Theory/HuckerRank/Easy/Primitive_Problem.html +++ b/Mathematics/Number Theory/HackerRank/Easy/Primitive_Problem.html @@ -5,13 +5,8 @@ 原始根の発見 - HackerRank問題解説 - - - + + @@ -25,14 +20,20 @@ @@ -2325,5 +2326,31 @@

    const root = ReactDOM.createRoot(document.getElementById('react-steps-root')); root.render(); + + + + + + diff --git a/Mathematics/Number Theory/HuckerRank/Easy/Primitive_Problem.ipynb b/Mathematics/Number Theory/HackerRank/Easy/Primitive_Problem.ipynb similarity index 53% rename from Mathematics/Number Theory/HuckerRank/Easy/Primitive_Problem.ipynb rename to Mathematics/Number Theory/HackerRank/Easy/Primitive_Problem.ipynb index b69c2fc8..59c3477e 100644 --- a/Mathematics/Number Theory/HuckerRank/Easy/Primitive_Problem.ipynb +++ b/Mathematics/Number Theory/HackerRank/Easy/Primitive_Problem.ipynb @@ -57,7 +57,7 @@ "def prime_factors(n: int) -> List[int]:\n", " \"\"\"\n", " nの素因数をリストで返す(重複なし)\n", - " \n", + "\n", " Time Complexity: O(√n)\n", " \"\"\"\n", " factors = []\n", @@ -66,7 +66,7 @@ " factors.append(2)\n", " while n % 2 == 0:\n", " n //= 2\n", - " \n", + "\n", " # 3以降の奇数でチェック\n", " i = 3\n", " while i * i <= n:\n", @@ -75,50 +75,50 @@ " while n % i == 0:\n", " n //= i\n", " i += 2\n", - " \n", + "\n", " # nが1より大きければ、それ自体が素数\n", " if n > 1:\n", " factors.append(n)\n", - " \n", + "\n", " return factors\n", "\n", "def is_primitive_root(g: int, p: int, prime_divisors: List[int]) -> bool:\n", " \"\"\"\n", " gがpの原始根かどうかを判定\n", - " \n", + "\n", " Args:\n", " g: 判定対象の整数\n", " p: 素数\n", " prime_divisors: (p-1)の素因数リスト\n", - " \n", + "\n", " Returns:\n", " gが原始根ならTrue\n", - " \n", + "\n", " Time Complexity: O(d·log p) where d = len(prime_divisors)\n", " \"\"\"\n", " phi = p - 1\n", - " \n", + "\n", " # 各素因数qについて、g^((p-1)/q) ≢ 1 (mod p) を確認\n", " for q in prime_divisors:\n", " if pow(g, phi // q, p) == 1:\n", " return False\n", - " \n", + "\n", " return True\n", "\n", "def euler_phi(n: int) -> int:\n", " \"\"\"\n", " オイラーのトーシェント関数 φ(n) を計算\n", - " \n", + "\n", " Time Complexity: O(√n)\n", " \"\"\"\n", " result = n\n", - " \n", + "\n", " # 2で割り切れる場合\n", " if n % 2 == 0:\n", " while n % 2 == 0:\n", " n //= 2\n", " result -= result // 2\n", - " \n", + "\n", " # 3以降の奇数でチェック\n", " p = 3\n", " while p * p <= n:\n", @@ -127,46 +127,46 @@ " n //= p\n", " result -= result // p\n", " p += 2\n", - " \n", + "\n", " if n > 1:\n", " result -= result // n\n", - " \n", + "\n", " return result\n", "\n", "def solve_competitive(p: int) -> tuple:\n", " \"\"\"\n", " 競技プログラミング向け実装\n", - " \n", + "\n", " Args:\n", " p: 素数\n", - " \n", + "\n", " Returns:\n", " (最小原始根, 原始根の総数)\n", - " \n", - " Time Complexity: O(√p + k·d·log p) \n", + "\n", + " Time Complexity: O(√p + k·d·log p)\n", " where k = 最小原始根の値, d = (p-1)の素因数の個数\n", " Space Complexity: O(d)\n", " \"\"\"\n", " # (p-1)の素因数を求める\n", " prime_divisors = prime_factors(p - 1)\n", - " \n", + "\n", " # 最小原始根を探索\n", " smallest_root = 0\n", " for g in range(2, p):\n", " if is_primitive_root(g, p, prime_divisors):\n", " smallest_root = g\n", " break\n", - " \n", + "\n", " # 原始根の総数 = φ(p-1)\n", " total_count = euler_phi(p - 1)\n", - " \n", + "\n", " return smallest_root, total_count\n", "\n", "if __name__ == '__main__':\n", " # p = int(input().strip())\n", " # テスト用入力\n", " p = 7\n", - " \n", + "\n", " smallest, total = solve_competitive(p)\n", " print(f\"{smallest} {total}\")" ] @@ -191,6 +191,177 @@ "- φ(p-1)の計算: O(√p)\n", "- 全体: p ≤ 10^9 でも実用的な時間で動作" ] + }, + { + "cell_type": "markdown", + "id": "d20d1a1a", + "metadata": {}, + "source": [ + "# 原始根(Primitive Root)の解説\n", + "\n", + "この文書は、**Jupyter Notebook などで数式が正しく LaTeX レンダリングされる**ように修正したマークダウン版です。数式は `$...$` または `$$...$$` を用いて記述しています。\n", + "\n", + "---\n", + "\n", + "## 1. 直感的な説明:原始根とは何か\n", + "\n", + "**原始根**とは、\n", + "\n", + "> 「ある数を何乗もしていくことで、剰余の世界にある全ての要素を生成できる数」\n", + "\n", + "のことです。\n", + "\n", + "---\n", + "\n", + "## 2. 具体例:mod 7 の場合\n", + "\n", + "$7$ を法とする剰余を考えます。$0$ を除くと、\n", + "\n", + "$$\n", + "1,2,3,4,5,6\n", + "$$\n", + "\n", + "の $6$ 個があります。\n", + "\n", + "### 2 を使った場合\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "2^1 &\\equiv 2 \\pmod{7} \\\n", + "2^2 &\\equiv 4 \\pmod{7} \\\n", + "2^3 &\\equiv 1 \\pmod{7}\n", + "\\end{aligned}\n", + "$$\n", + "\n", + "ここで $1$ に戻ってしまい、${1,2,4}$ しか生成できません。\n", + "\n", + "### 3 を使った場合\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "3^1 &\\equiv 3 \\pmod{7} \\\n", + "3^2 &\\equiv 2 \\pmod{7} \\\n", + "3^3 &\\equiv 6 \\pmod{7} \\\n", + "3^4 &\\equiv 4 \\pmod{7} \\\n", + "3^5 &\\equiv 5 \\pmod{7} \\\n", + "3^6 &\\equiv 1 \\pmod{7}\n", + "\\end{aligned}\n", + "$$\n", + "\n", + "$1$ から $6$ まで全てが現れました。したがって **$3$ は mod $7$ の原始根**です。\n", + "\n", + "---\n", + "\n", + "## 3. 数学的な定義\n", + "\n", + "正の整数 $n$ に対し、\n", + "\n", + "$$\n", + "(\\mathbb{Z}/n\\mathbb{Z})^\\times\n", + "$$\n", + "\n", + "($n$ と互いに素な整数の剰余類全体)を考えます。\n", + "\n", + "この集合において、\n", + "\n", + "> 自身の冪で全ての要素を生成できる元\n", + "\n", + "を **原始根**と呼びます。\n", + "\n", + "---\n", + "\n", + "## 4. 位数(order)の定義\n", + "\n", + "原始根を理解する鍵となる概念が **位数**です。\n", + "\n", + "### 位数の定義\n", + "\n", + "$$\n", + "\\operatorname{ord}_n(a)\n", + "= \\min{k > 0 \\mid a^k \\equiv 1 \\pmod{n}}\n", + "$$\n", + "\n", + "これは「$a^k$ が初めて $1$ に戻るまでの最小の周期」を表します。\n", + "\n", + "---\n", + "\n", + "## 5. 原始根の条件\n", + "\n", + "オイラーのトーシェント関数 $\\varphi(n)$ を用いると、\n", + "\n", + "$$\n", + "\\operatorname{ord}_n(g) = \\varphi(n)\n", + "$$\n", + "\n", + "を満たす $g$ が **原始根**です。\n", + "\n", + "つまり、\n", + "\n", + "> 位数が最大の元\n", + "\n", + "が原始根になります。\n", + "\n", + "---\n", + "\n", + "## 6. 群論的な背景(直感的説明)\n", + "\n", + "$p$ を素数とすると、\n", + "\n", + "$$\n", + "(\\mathbb{Z}/p\\mathbb{Z})^\\times\n", + "$$\n", + "\n", + "は位数 $p-1$ の **巡回群**になります。巡回群には必ず生成元が存在し、その生成元が原始根です。\n", + "\n", + "直感的には、\n", + "\n", + "* 歩幅が合わないと一部しか回れない\n", + "* 歩幅がちょうど良いと全体を一周できる\n", + "\n", + "というイメージです。\n", + "\n", + "---\n", + "\n", + "## 7. 原始根が存在する整数 $n$\n", + "\n", + "原始根が存在する $n$ は、次の場合に限られます:\n", + "\n", + "$$\n", + "n = 1,2,4,p^k,2p^k\n", + "$$\n", + "\n", + "ただし $p$ は奇素数、$k \\ge 1$ です。\n", + "\n", + "例:\n", + "\n", + "* $7$(素数) → 存在する\n", + "* $9 = 3^2$ → 存在する\n", + "* $14 = 2 \\times 7$ → 存在する\n", + "* $8$ → 存在しない\n", + "\n", + "---\n", + "\n", + "## 8. 応用:暗号理論との関係\n", + "\n", + "原始根 $g$ が存在すると、\n", + "\n", + "$$\n", + "g^x \\equiv y \\pmod{p}\n", + "$$\n", + "\n", + "という形の **離散対数問題**を定義できます。この問題は計算的に非常に困難であり、\n", + "\n", + "* Diffie–Hellman 鍵共有\n", + "* ElGamal 暗号\n", + "\n", + "などの基盤になっています。\n", + "\n", + "---\n", + "\n", + "## 9. まとめ\n", + "\n", + "**原始根**とは、剰余乗法群を一つの元の冪によって完全に生成できる特別な数であり、その位数はトーシェント関数に等しくなります。理論的にも計算機科学的にも重要な概念です。" + ] } ], "metadata": { diff --git a/Mathematics/Number Theory/HuckerRank/Easy/Sherlock_and_GCD.ipynb b/Mathematics/Number Theory/HackerRank/Easy/Sherlock_and_GCD.ipynb similarity index 100% rename from Mathematics/Number Theory/HuckerRank/Easy/Sherlock_and_GCD.ipynb rename to Mathematics/Number Theory/HackerRank/Easy/Sherlock_and_GCD.ipynb diff --git a/Mathematics/Number Theory/HuckerRank/Medium/Closest_Number.ipynb b/Mathematics/Number Theory/HackerRank/Medium/Closest_Number.ipynb similarity index 100% rename from Mathematics/Number Theory/HuckerRank/Medium/Closest_Number.ipynb rename to Mathematics/Number Theory/HackerRank/Medium/Closest_Number.ipynb diff --git a/verify_sri.py b/verify_sri.py new file mode 100644 index 00000000..c0f9ccb5 --- /dev/null +++ b/verify_sri.py @@ -0,0 +1,22 @@ +import hashlib +import requests +import base64 + +urls = [ + "https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css", + "https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.css", + "https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.css", + "https://cdn.tailwindcss.com/3.4.1" +] + +for url in urls: + try: + response = requests.get(url) + content = response.content + hash_obj = hashlib.sha384(content) + base64_hash = base64.b64encode(hash_obj.digest()).decode('utf-8') + print(f"URL: {url}") + print(f"SRI: sha384-{base64_hash}") + print("-" * 20) + except Exception as e: + print(f"Error fetching {url}: {e}")