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,395 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "c1a3e2d9",
"metadata": {},
"source": [
"# TypeScript Reduce関数の実装\n",
"\n",
"## 1. 問題の分析\n",
"\n",
"### 競技プログラミング視点での分析\n",
"- **実行速度**: 配列を1回走査するだけの単純な反復処理(O(n))\n",
"- **メモリ効率**: 追加のデータ構造が不要、累積値のみを保持(O(1))\n",
"- **最適化ポイント**: ループ方式の選択(for vs forEach vs for-of)\n",
"\n",
"### 業務開発視点での分析\n",
"- **型安全性**: 関数型引数とジェネリクスによる型保証が重要\n",
"- **可読性**: reduceの動作を明確に示す実装\n",
"- **エラーハンドリング**: 空配列の処理、null/undefined安全性\n",
"- **保守性**: シンプルで理解しやすいコード\n",
"\n",
"### TypeScript特有の考慮点\n",
"- **型推論**: `Fn`型の厳密な定義により、コンパイル時に型エラーを検出\n",
"- **イミュータビリティ**: 元の配列を変更しない純粋関数\n",
"- **null安全性**: strict modeでの安全な実装\n",
"\n",
"## 2. アルゴリズムアプローチ比較\n",
"\n",
"| アプローチ | 時間計算量 | 空間計算量 | TS実装コスト | 型安全性 | 可読性 | 備考 |\n",
"|---------|----------|---------|------------|---------|-------|------|\n",
"| forループ | O(n) | O(1) | 低 | 高 | 高 | 最も基本的で高速 |\n",
"| for-ofループ | O(n) | O(1) | 低 | 高 | 高 | モダンな構文、若干遅い |\n",
"| forEachメソッド | O(n) | O(1) | 低 | 高 | 中 | 関数呼び出しオーバーヘッド |\n",
"| 再帰 | O(n) | O(n) | 中 | 高 | 中 | スタックオーバーフローリスク |\n",
"\n",
"## 3. 選択したアルゴリズムと理由\n",
"\n",
"### 選択したアプローチ: **forループ**\n",
"\n",
"### 理由\n",
"1. **計算量的な優位性**\n",
" - 時間: O(n) - 配列を1回走査\n",
" - 空間: O(1) - 累積値のみを保持\n",
" - インデックスベースのアクセスで最速\n",
"\n",
"2. **TypeScript環境での型安全性**\n",
" - コンパイル時に型チェックが完全に機能\n",
" - 累積値の型が明確に推論される\n",
" - 副作用なしの純粋関数として実装可能\n",
"\n",
"3. **保守性・可読性の観点**\n",
" - reduce操作の意図が明確\n",
" - デバッグが容易\n",
" - エッジケース(空配列)の処理が明示的\n",
"\n",
"### TypeScript特有の最適化ポイント\n",
"- **型アノテーション**: 累積値の型が自動推論されるため、型注釈が最小限\n",
"- **const使用**: イミュータビリティの確保\n",
"- **早期リターン**: 空配列チェックによる不要な処理の回避\n",
"\n",
"## 4. 実装コード\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 51 ms\n",
"// Beats 31.36%\n",
"// Memory 56.13 MB\n",
"// Beats 50.75%\n",
"\n",
"type Fn = (accum: number, curr: number) => number\n",
"\n",
"/**\n",
" * 配列の各要素に対してreducer関数を順次適用し、単一の累積値を返す\n",
" * \n",
" * @param nums - 処理対象の数値配列\n",
" * @param fn - 累積値と現在値を受け取り、新しい累積値を返すreducer関数\n",
" * @param init - 初期累積値\n",
" * @returns 全要素に対してfnを適用した最終的な累積値\n",
" * @complexity Time: O(n), Space: O(1)\n",
" * \n",
" * @example\n",
" * reduce([1,2,3,4], (acc, curr) => acc + curr, 0) // returns 10\n",
" * reduce([], (acc, curr) => acc + curr, 25) // returns 25\n",
" */\n",
"function reduce(nums: number[], fn: Fn, init: number): number {\n",
" // 早期リターン: 空配列の場合は初期値をそのまま返す\n",
" if (nums.length === 0) {\n",
" return init;\n",
" }\n",
" \n",
" // 累積値を初期値で初期化\n",
" let accumulator: number = init;\n",
" \n",
" // 配列の各要素に対してreducer関数を順次適用\n",
" for (let i = 0; i < nums.length; i++) {\n",
" accumulator = fn(accumulator, nums[i]);\n",
" }\n",
" \n",
" // 最終的な累積値を返す\n",
" return accumulator;\n",
"}\n",
"```\n",
"\n",
"### 代替実装(より関数型的なアプローチ)\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 43 ms\n",
"// Beats 75.08%\n",
"// Memory 58.72 MB\n",
"// Beats 5.23%\n",
"/**\n",
" * for-ofループを使用した実装\n",
" * より読みやすいが、わずかに遅い可能性がある\n",
" */\n",
"function reduceAlternative(nums: number[], fn: Fn, init: number): number {\n",
" let accumulator: number = init;\n",
" \n",
" for (const num of nums) {\n",
" accumulator = fn(accumulator, num);\n",
" }\n",
" \n",
" return accumulator;\n",
"}\n",
"```\n",
"\n",
"## LeetCode提出用コード\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 44 ms\n",
"// Beats 70.65%\n",
"// Memory 56.58 MB\n",
"// Beats 26.43%\n",
"type Fn = (accum: number, curr: number) => number\n",
"\n",
"function reduce(nums: number[], fn: Fn, init: number): number {\n",
" let accumulator = init;\n",
" for (let i = 0; i < nums.length; i++) {\n",
" accumulator = fn(accumulator, nums[i]);\n",
" }\n",
" return accumulator;\n",
"}\n",
"```\n",
"\n",
"## 実装の特徴\n",
"\n",
"### 型安全性\n",
"- ✅ `Fn`型により、reducer関数のシグネチャが厳密に定義\n",
"- ✅ `number`型の一貫性が保証される\n",
"- ✅ コンパイル時に型エラーを検出\n",
"\n",
"### パフォーマンス\n",
"- ✅ O(n)の時間計算量 - 最適\n",
"- ✅ O(1)の空間計算量 - メモリ効率的\n",
"- ✅ ループオーバーヘッドが最小\n",
"\n",
"### エッジケース処理\n",
"- ✅ 空配列 → `init`を返す\n",
"- ✅ 単一要素 → `fn(init, nums[0])`を返す\n",
"- ✅ 制約条件(0 ≤ length ≤ 1000)を満たす\n",
"\n",
"この実装は、TypeScriptの型安全性を活かしながら、最高のパフォーマンスと可読性を実現しています。"
]
},
{
"cell_type": "markdown",
"id": "2bcb244c",
"metadata": {},
"source": [
"# パフォーマンス分析と改善提案\n",
"\n",
"## 結果の分析\n",
"\n",
"### 興味深い発見\n",
"1. **空配列チェックのオーバーヘッド**: 早期リターンを追加したことで逆に遅くなっている(51ms vs 44ms)\n",
"2. **for-ofの優位性**: 意外にもfor-ofループが最速(43ms)だが、メモリ使用量が多い\n",
"3. **トレードオフ**: 速度とメモリのバランス\n",
"\n",
"### 問題点\n",
"- 空配列チェックは制約条件(0 ≤ length ≤ 1000)では頻繁に発生しないため、分岐予測ミスのコストの方が高い\n",
"- V8エンジンの最適化において、シンプルなコードの方が効率的\n",
"\n",
"## 改善版実装\n",
"\n",
"### 最適化版1: 最小限のコード(速度重視)\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 46 ms\n",
"// Beats 59.80%\n",
"// Memory 56.44 MB\n",
"// Beats 30.85%\n",
"type Fn = (accum: number, curr: number) => number\n",
"\n",
"function reduce(nums: number[], fn: Fn, init: number): number {\n",
" let val = init;\n",
" for (let i = 0; i < nums.length; i++) {\n",
" val = fn(val, nums[i]);\n",
" }\n",
" return val;\n",
"}\n",
"```\n",
"\n",
"**改善ポイント**:\n",
"- ✅ 空配列チェックを削除(オーバーヘッド削減)\n",
"- ✅ 変数名を短縮(`accumulator` → `val`)でメモリアクセス最適化\n",
"- ✅ 極限までシンプルに\n",
Comment on lines +206 to +209

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

変数名の短縮が「メモリアクセス最適化」になるという主張は不正確です。

V8エンジンではJITコンパイル後に変数名は使用されないため、accumulatorval への変更はランタイムパフォーマンスに影響しません。可読性やコードの簡潔さとして説明するのが正確です。

🤖 Prompt for AI Agents
In `@JavaScript/2626`. Array Reduce Transformation/Claude Code Sonnet 4.5
extended/ArrayReduceTransformation_TS.ipynb around lines 206 - 209,
ドキュメントの説明が誤っているので「変数名を短縮(`accumulator` →
`val`)でメモリアクセス最適化」と書かれている箇所を修正し、`accumulator` → `val`
の変更はランタイム性能に影響しない旨に置き換えて、「可読性/簡潔さのために変数名を短縮した」などの表現に更新してください(対象となるテキストは該当ノートブック内の該当箇所で、記載されている
`accumulator` と `val` の説明行を編集してください)。

"\n",
"**予想パフォーマンス**: Runtime ~42-45ms, Memory ~55-56MB\n",
"\n",
"---\n",
"\n",
"### 最適化版2: キャッシング活用(速度最重視)\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 40 ms\n",
"// Beats 86.03%\n",
"// Memory 56.20 MB\n",
"// Beats 43.12%\n",
"type Fn = (accum: number, curr: number) => number\n",
"\n",
"function reduce(nums: number[], fn: Fn, init: number): number {\n",
" let val = init;\n",
" const len = nums.length;\n",
" for (let i = 0; i < len; i++) {\n",
" val = fn(val, nums[i]);\n",
" }\n",
" return val;\n",
"}\n",
"```\n",
"\n",
"**改善ポイント**:\n",
"- ✅ `nums.length`をキャッシュして、ループ毎のプロパティアクセスを削減\n",
"- ✅ V8の最適化を促進\n",
"\n",
"**予想パフォーマンス**: Runtime ~40-43ms, Memory ~55-56MB\n",
"\n",
"---\n",
"\n",
"### 最適化版3: アンローリング(極限の最適化)\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 47 ms\n",
"// Beats 53.17%\n",
"// Memory 56.15 MB\n",
"// Beats 50.75%\n",
"\n",
"type Fn = (accum: number, curr: number) => number\n",
"\n",
"function reduce(nums: number[], fn: Fn, init: number): number {\n",
" let val = init;\n",
" let i = 0;\n",
" const len = nums.length;\n",
" \n",
" // ループアンローリング: 4要素ずつ処理\n",
" const unrollLimit = len - (len % 4);\n",
" for (; i < unrollLimit; i += 4) {\n",
" val = fn(val, nums[i]);\n",
" val = fn(val, nums[i + 1]);\n",
" val = fn(val, nums[i + 2]);\n",
" val = fn(val, nums[i + 3]);\n",
" }\n",
" \n",
" // 残りの要素を処理\n",
" for (; i < len; i++) {\n",
" val = fn(val, nums[i]);\n",
" }\n",
" \n",
" return val;\n",
"}\n",
"```\n",
Comment on lines +243 to +275

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

ループアンローリングの結果が主張と矛盾しています。

実測値(47ms)がキャッシング版(40ms)より遅いにもかかわらず、「ブランチ予測とパイプライン効率を向上」「ループオーバーヘッドを75%削減」と記述されています。JITコンパイラが既にこの種の最適化を行うため、手動アンローリングは逆効果になることが多いです。実測結果に基づく注意書きを追加するか、予想パフォーマンスの記述を修正してください。

🤖 Prompt for AI Agents
In `@JavaScript/2626`. Array Reduce Transformation/Claude Code Sonnet 4.5
extended/ArrayReduceTransformation_TS.ipynb around lines 243 - 275, The comments
for the unrolled implementation (function reduce, unrollLimit and the
surrounding "アンローリング(極限の最適化)" block) claim improvements like
"ブランチ予測とパイプライン効率を向上" and "ループオーバーヘッドを75%削減" despite measured runtime (47 ms)
being slower than the caching version (40 ms); update the explanatory comments
to either 1) state the actual measured result and add a caution that manual loop
unrolling can be slower because modern JITs already optimize loops, or 2) remove
the optimistic performance claims and replace them with a neutral note
explaining that benefits are workload- and runtime-dependent, mentioning the
observed 47 ms vs 40 ms numbers for clarity.

"\n",
"**改善ポイント**:\n",
"- ✅ ループアンローリングでブランチ予測とパイプライン効率を向上\n",
"- ✅ 4要素ずつ処理することで、ループオーバーヘッドを75%削減\n",
"\n",
"**予想パフォーマンス**: Runtime ~38-42ms(大きな配列で効果大)\n",
"\n",
"---\n",
"\n",
"## 推奨実装\n",
"\n",
"### 🏆 ベストバランス版(推奨)\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 42 ms\n",
"// Beats 79.60%\n",
"// Memory 56.62 MB\n",
"// Beats 23.42%\n",
"type Fn = (accum: number, curr: number) => number\n",
"\n",
"function reduce(nums: number[], fn: Fn, init: number): number {\n",
" let val = init;\n",
" const len = nums.length;\n",
" for (let i = 0; i < len; i++) {\n",
" val = fn(val, nums[i]);\n",
" }\n",
" return val;\n",
"}\n",
"```\n",
"\n",
"**選択理由**:\n",
"1. **速度**: lengthキャッシングで ~5-10%高速化\n",
"2. **メモリ**: 最小限の変数使用\n",
"3. **可読性**: 十分にシンプルで理解しやすい\n",
"4. **保守性**: 過度な最適化による複雑性なし\n",
"\n",
"**期待結果**: Runtime 40-43ms (80%+), Memory 55-56MB (60%+)\n",
"\n",
"---\n",
"\n",
"## さらなる最適化のヒント\n",
"\n",
"### V8エンジン最適化のベストプラクティス\n",
"\n",
"```typescript\n",
"type Fn = (accum: number, curr: number) => number\n",
"\n",
"function reduce(nums: number[], fn: Fn, init: number): number {\n",
" // 型の一貫性を保つ(V8の隠しクラス最適化)\n",
" let val: number = init;\n",
" \n",
" // プロパティアクセスを削減\n",
" const length: number = nums.length;\n",
" \n",
" // モノモーフィックなループ(常に同じ型)\n",
" for (let i: number = 0; i < length; i++) {\n",
" val = fn(val, nums[i]);\n",
" }\n",
" \n",
" return val;\n",
"}\n",
"```\n",
"\n",
"### TypeScriptコンパイラ最適化\n",
"\n",
"tsconfig.jsonで以下を設定:\n",
"```json\n",
"{\n",
" \"compilerOptions\": {\n",
" \"target\": \"ES2022\",\n",
" \"module\": \"ES2022\",\n",
" \"strict\": true,\n",
" \"noUncheckedIndexedAccess\": false,\n",
" \"skipLibCheck\": true\n",
" }\n",
"}\n",
"```\n",
Comment on lines +340 to +353

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

noUncheckedIndexedAccess: false の推奨は型安全性の主張と矛盾します。

ノートブック前半で型安全性を重視する旨を強調していますが、noUncheckedIndexedAccess: false は配列のインデックスアクセスで undefined の可能性を無視する設定です。型安全性を最大化するなら true が推奨されます。このオプションの選択理由(LeetCode提出時の簡便さなど)を明記するか、true に変更してください。

🤖 Prompt for AI Agents
In `@JavaScript/2626`. Array Reduce Transformation/Claude Code Sonnet 4.5
extended/ArrayReduceTransformation_TS.ipynb around lines 340 - 353, The tsconfig
snippet currently sets "noUncheckedIndexedAccess": false which conflicts with
the notebook's stated emphasis on type-safety; update the tsconfig.json block in
the notebook to either set "noUncheckedIndexedAccess": true to enforce safer
array/index access across the project or add a concise justification comment
next to the tsconfig.json snippet explaining why it is intentionally false for
LeetCode/compatibility reasons; specifically edit the tsconfig.json example (the
"tsconfig.json" snippet and the "noUncheckedIndexedAccess" key) to reflect the
chosen approach so readers aren't misled about the type-safety guarantees.

"\n",
"---\n",
"\n",
"## パフォーマンス比較予測\n",
"\n",
"| 実装 | Runtime予測 | Memory予測 | 複雑度 | 推奨度 |\n",
"|------|-------------|------------|--------|--------|\n",
"| 現在のメイン実装 | 51ms (31%) | 56.13MB (51%) | 低 | ⭐⭐ |\n",
"| 最適化版1(最小限) | 42-45ms (70-80%) | 55-56MB (60%) | 低 | ⭐⭐⭐⭐ |\n",
"| 最適化版2(キャッシング) | 40-43ms (75-85%) | 55-56MB (60%) | 低 | ⭐⭐⭐⭐⭐ |\n",
"| 最適化版3(アンローリング) | 38-42ms (80-90%) | 56-57MB (50%) | 高 | ⭐⭐⭐ |\n",
"\n",
"---\n",
"\n",
"## 結論\n",
"\n",
"**最も推奨する実装は「最適化版2(キャッシング活用)」です。**\n",
"\n",
"この実装により、以下の改善が期待できます:\n",
"- ✅ Runtime: 51ms → 40-43ms(約20%改善、75-85%にランクアップ)\n",
"- ✅ Memory: ほぼ変わらず(55-56MB、60%前後)\n",
"- ✅ 可読性: 維持\n",
"- ✅ 保守性: 維持"
]
}
],
"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
}
Comment on lines +380 to +395

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

ノートブック全体がMarkdownセルのみで構成されており、実行可能なコードセルがありません。

kernelが TypeScript に設定されていますが、全セルが cell_type: "markdown" であるため、コードスニペットはノートブック内で実行できません。教育目的であれば、少なくともコアの reduce 実装を code セルとして追加し、インタラクティブに実行・検証できるようにすることを検討してください。

🤖 Prompt for AI Agents
In `@JavaScript/2626`. Array Reduce Transformation/Claude Code Sonnet 4.5
extended/ArrayReduceTransformation_TS.ipynb around lines 380 - 395, The notebook
currently contains only markdown cells while the kernel is set to TypeScript, so
add at least one executable code cell implementing and demonstrating a core
reduce example (e.g., a function named arrayReduce or reduceExample) written in
TypeScript; include sample input arrays and console.log assertions to show
expected outputs and keep the cell self-contained so readers can run and
validate the reduce behavior interactively in the notebook.

Loading