diff --git a/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/README.md b/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/README.md new file mode 100644 index 00000000..5970f1ca --- /dev/null +++ b/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/README.md @@ -0,0 +1,363 @@ +# Sleep - 非同期スリープ関数の実装 + +## 目次 + +- [概要](#overview) +- [アルゴリズム要点(TL;DR)](#tldr) +- [図解](#figures) +- [正しさのスケッチ](#correctness) +- [計算量](#complexity) +- [Python実装](#impl) +- [CPython最適化ポイント](#cpython) +- [エッジケースと検証観点](#edgecases) +- [FAQ](#faq) + +--- + +

概要

+ +### 問題要約 + +正の整数 `millis` を受け取り、その時間(ミリ秒)だけ非同期にスリープする関数を実装する。 + +### 要件 + +- 入力: `1 <= millis <= 1000` の正の整数 +- 出力: `millis` ミリ秒後に完了する awaitable オブジェクト(任意の値を返してよい) +- 実際のスリープ時間が `millis` から若干ずれても許容される + +### 制約 + +- 外部ライブラリは標準ライブラリのみ(`asyncio`) +- 非同期処理の基本的な理解が必要 + +--- + +

アルゴリズム要点(TL;DR)

+ +- **戦略**: `asyncio.sleep()` を使用するか、イベントループの `call_later` で Future を解決 +- **データ構造**: Future または Task(asyncio の非同期プリミティブ) +- **時間計算量**: O(1) - 定数時間での処理開始 +- **空間計算量**: O(1) - Future/Task オブジェクト1つのみ +- **メモリ**: 最小限(非同期タスク管理のオーバーヘッドのみ) + +--- + +

図解

+ +### フローチャート + +```mermaid +flowchart TD + Start[Start sleep] --> Validate{Check millis valid} + Validate -- Invalid --> Error[Raise ValueError] + Validate -- Valid --> Convert[Convert millis to seconds] + Convert --> CreateFuture[Create Future object] + CreateFuture --> Schedule[Schedule callback via call_later] + Schedule --> Await[Await Future completion] + Await --> Callback[Callback sets result] + Callback --> Resume[Coroutine resumes] + Resume --> End[Return None] +``` + +**説明**: 入力検証後、ミリ秒を秒に変換し、イベントループに遅延コールバックをスケジュール。コールバックが Future を解決すると、await が再開される。 + +### データフロー図 + +```mermaid +graph LR + subgraph Input_Layer + A[millis int] --> B[Validate range] + end + subgraph Async_Layer + B --> C[Convert to seconds] + C --> D[Get event loop] + D --> E[Create Future] + E --> F[Schedule call_later] + end + subgraph Execution_Layer + F --> G[Event loop waits] + G --> H[Callback fires] + H --> I[Future resolved] + end + I --> J[Return to caller] +``` + +**説明**: 入力値を検証・変換し、非同期レイヤーで Future を作成してイベントループにスケジュール。実行時にコールバックが発火して Future が解決される。 + +--- + +

正しさのスケッチ

+ +### 不変条件 + +- `millis` は常に正の整数(1 以上 1000 以下) +- Future は必ず1回だけ解決される(`set_result` は1回のみ呼ばれる) +- イベントループは正しく動作している(標準の asyncio 前提) + +### 網羅性 + +- 入力範囲内のすべての `millis` 値に対して正しく動作 +- イベントループがない場合のエラーハンドリング(実装による) + +### 基底条件 + +- `millis` の最小値(1ミリ秒)でも正しく動作 +- Future が即座に解決されるケースも含む + +### 終了性 + +- `call_later` は必ず指定時間後にコールバックを呼び出す +- コールバックは Future を解決し、`await` が必ず復帰する +- イベントループが停止していない限り、必ず終了する + +--- + +

計算量

+ +### 時間計算量 + +- **O(1)**: Future の作成とコールバックのスケジューリングは定数時間 +- **実際の待機時間**: O(millis) だが、これは計算量ではなく実時間 + +### 空間計算量 + +- **O(1)**: Future オブジェクトとコールバッククロージャのみ +- スタックフレームやヒープ使用量は最小限 + +### アプローチ比較 + +| アプローチ | 実装難易度 | メモリ | コード量 | 推奨度 | +| -------------------------- | ---------- | ------ | -------- | ------------- | +| `asyncio.sleep()` 直接使用 | 低 | O(1) | 1行 | ★★★ | +| `call_later` + Future | 中 | O(1) | 5行 | ★★ | +| busy wait(ポーリング) | 低 | O(1) | 3行 | ✗(CPU 100%) | + +**推奨**: 問題の趣旨が「自分で実装」なら `call_later` + Future、実務なら `asyncio.sleep()` を使用。 + +--- + +

Python実装

+ +### アプローチ1: asyncio.sleep() を使用(最もシンプル) + +```python +from __future__ import annotations +import asyncio + +async def sleep(millis: int) -> None: + """ + 指定されたミリ秒数だけ非同期にスリープする + + Args: + millis: スリープするミリ秒数(1-1000) + + Returns: + None + + Time: O(1) for scheduling, Space: O(1) + """ + # 入力検証(制約に基づく) + if not isinstance(millis, int) or millis < 1 or millis > 1000: + raise ValueError("millis must be an integer between 1 and 1000") + + # ミリ秒を秒に変換してスリープ + await asyncio.sleep(millis / 1000) +``` + +### アプローチ2: call_later + Future(低レベル実装) + +```python +from __future__ import annotations +import asyncio +from typing import Any + +async def sleep(millis: int) -> None: + """ + イベントループの call_later を使用した低レベル実装 + + Args: + millis: スリープするミリ秒数(1-1000) + + Returns: + None + + Time: O(1), Space: O(1) + """ + # 入力検証 + if not isinstance(millis, int) or millis < 1 or millis > 1000: + raise ValueError("millis must be an integer between 1 and 1000") + + # イベントループ取得 + loop = asyncio.get_event_loop() + + # Future 作成(コルーチンが待機するオブジェクト) + future: asyncio.Future[None] = loop.create_future() + + # コールバックをスケジュール(millis ミリ秒後に Future を解決) + loop.call_later( + millis / 1000, # 秒単位に変換 + future.set_result, # Future を解決するコールバック + None # 解決時の値(任意) + ) + + # Future が解決されるまで待機 + await future +``` + +### LeetCode形式での提出コード(最小実装) + +```python +import asyncio + +async def sleep(millis: int) -> None: + await asyncio.sleep(millis / 1000) + +# 使用例 +# let t = Date.now() +# sleep(100).then(() => console.log(Date.now() - t)) # 100 +``` + +Python での等価な使用例: + +```python +import asyncio +import time + +async def main(): + t = time.time() + await sleep(100) + print(int((time.time() - t) * 1000)) # ~100 + +# 実行 +asyncio.run(main()) +``` + +--- + +

CPython最適化ポイント

+ +### 最適化1: 直接 `asyncio.sleep()` を使用 + +- CPython の `asyncio` は C 拡張で最適化されている +- 独自実装よりも高速で安定 + +### 最適化2: 型チェックの省略(制約が保証される場合) + +```python +async def sleep(millis: int) -> None: + # LeetCode環境では入力が保証されているため検証不要 + await asyncio.sleep(millis / 1000) +``` + +### 最適化3: 除算の事前計算(大量呼び出し時) + +```python +MILLIS_TO_SECONDS = 0.001 + +async def sleep(millis: int) -> None: + await asyncio.sleep(millis * MILLIS_TO_SECONDS) # 除算より乗算が高速 +``` + +### パフォーマンスノート + +- `asyncio.sleep()` の精度はOSのタイマー精度に依存(通常1-15ミリ秒) +- 極端に短いスリープ(1-10ミリ秒)では誤差が大きくなる可能性がある +- イベントループのオーバーヘッドは無視できるレベル(マイクロ秒単位) + +--- + +

エッジケースと検証観点

+ +### エッジケース一覧 + +1. **最小値**: `millis = 1` + - 1ミリ秒のスリープが正しく動作するか + - OS のタイマー精度による誤差に注意 + +2. **最大値**: `millis = 1000` + - 1秒のスリープが正しく完了するか + +3. **境界値前後**: + - `millis = 0` → ValueError(範囲外) + - `millis = 1001` → ValueError(範囲外) + +4. **型エラー**: + - `millis = 100.5` → 型エラー(整数のみ) + - `millis = "100"` → 型エラー + +5. **並行実行**: + +```python +async def test_concurrent(): + await asyncio.gather( + sleep(100), + sleep(200), + sleep(150) + ) +``` + +- 複数の sleep が同時に正しく動作するか + +### 検証観点 + +- **精度**: 実際のスリープ時間が `millis` に近いか(±10%以内が目安) +- **非ブロッキング**: 他の非同期タスクをブロックしないか +- **リソースリーク**: Future が適切に解放されるか +- **イベントループ依存**: 異なるイベントループで動作するか + +--- + +

FAQ

+ +### Q1: なぜ `asyncio.sleep()` を使わず自分で実装する必要があるのか? + +**A**: この問題は非同期プログラミングの理解を深めるための教育的な意図があります。実務では `asyncio.sleep()` を使用すべきです。 + +### Q2: `time.sleep()` ではダメなのか? + +**A**: `time.sleep()` はブロッキング関数で、イベントループ全体を停止させます。非同期処理では必ず `asyncio.sleep()` や await 可能な実装を使用してください。 + +```python +# ❌ ダメな例(イベントループをブロック) +import time +async def bad_sleep(millis: int) -> None: + time.sleep(millis / 1000) # 他のタスクも全て停止 + +# ✅ 正しい例 +async def good_sleep(millis: int) -> None: + await asyncio.sleep(millis / 1000) # 他のタスクは継続 +``` + +### Q3: ミリ秒の精度は保証されるか? + +**A**: いいえ。OS のタイマー精度、イベントループの負荷、CPython のスケジューリングによって誤差が生じます。問題文でも「minor deviation」が許容されています。 + +### Q4: `call_later` と `asyncio.sleep()` の違いは? + +**A**: + +- `call_later`: 低レベルAPI。コールバックベース。 +- `asyncio.sleep()`: 高レベルAPI。内部で `call_later` を使用。await 可能。 + +実装は等価ですが、`asyncio.sleep()` の方がシンプルで可読性が高いです。 + +### Q5: TypeScript の `setTimeout` と Python の実装の違いは? + +**A**: + +```typescript +// TypeScript +async function sleep(millis: number): Promise { + return new Promise(resolve => setTimeout(resolve, millis)); +} + +// Python 等価実装 +async def sleep(millis: int) -> None: + loop = asyncio.get_event_loop() + future = loop.create_future() + loop.call_later(millis / 1000, future.set_result, None) + await future +``` + +両者は概念的に同じですが、Python は秒単位、TypeScript はミリ秒単位である点に注意。 diff --git a/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/README_react.html b/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/README_react.html new file mode 100644 index 00000000..8d25991b --- /dev/null +++ b/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/README_react.html @@ -0,0 +1,1706 @@ + + + + + + Sleep - 非同期スリープ関数の実装 + + + + + + + + + + + + + + + + + +
+ + + + +
+

+ アルゴリズム概要 +

+ +

問題説明

+

+ 正の整数 + millis + を受け取り、その時間(ミリ秒)だけ非同期にスリープする関数を実装します。実際のスリープ時間が + millis + から若干ずれても許容されます。 +

+ +

入出力例

+
+

例1:

+
Input: millis = 100
+Output: 100
+Explanation: 100msスリープ後に完了する
+
+ +
+

例2:

+
Input: millis = 200
+Output: 200
+Explanation: 200msスリープ後に完了する
+
+ +

制約条件

+
    +
  • + 1 ≤ millis ≤ 1000 +
  • +
  • + 戻り値は任意(通常は + void または + undefined) +
  • +
  • 実際のスリープ時間の若干のずれは許容される
  • +
+ +

戦略

+
    +
  • Promise: 非同期処理の結果を表すオブジェクトを作成
  • +
  • setTimeout: 指定時間後にコールバックを実行
  • +
  • resolve: Promiseを完了状態にする関数をsetTimeoutに渡す
  • +
  • async/await: 呼び出し側で簡潔に待機できるようにする
  • +
+ +

主要ポイント

+
+

+ 時間計算量: O(1) - + 定数時間での処理開始 +

+

+ 空間計算量: O(1) - + Promiseオブジェクト1つのみ +

+

+ 最適化手法: + 外部ライブラリ不要、標準API のみ使用 +

+
+
+ + +
+

+ ステップバイステップ解説 +

+
+
+ + +
+

+ TypeScript実装 +

+
/**
+ * 指定されたミリ秒数だけ非同期にスリープする関数
+ * @param millis - 待機するミリ秒数(1-1000)
+ * @returns void を解決するPromise
+ * @complexity Time: O(1), Space: O(1)
+ */
+async function sleep(millis: number): Promise<void> {
+    // Promiseでラップした setTimeout による非同期待機
+    return new Promise<void>((resolve) => {
+        setTimeout(resolve, millis);
+    });
+}
+
+/**
+ * 使用例
+ */
+let t = Date.now();
+sleep(100).then(() => {
+    console.log(Date.now() - t); // ~100
+});
+ +

+ エラーハンドリング付き実装 +

+
async function sleep(millis: number): Promise<void> {
+    // 型ガード: 数値チェック
+    if (typeof millis !== 'number' || Number.isNaN(millis)) {
+        throw new TypeError('millis must be a valid number');
+    }
+
+    // 範囲チェック(制約条件: 1 <= millis <= 1000)
+    if (millis < 1 || millis > 1000) {
+        throw new RangeError('millis must be between 1 and 1000');
+    }
+
+    // 整数チェック(正の整数要件)
+    if (!Number.isInteger(millis)) {
+        throw new RangeError('millis must be an integer');
+    }
+
+    // Promise でラップした setTimeout による非同期待機
+    return new Promise<void>((resolve) => {
+        setTimeout(resolve, millis);
+    });
+}
+
+ + +
+

+ フローチャート +

+
+
+ + +
+

+ 計算量分析 +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ 項目 + + 計算量 + + 説明 +
+ 時間計算量 + + O(1) + + Promise作成とsetTimeoutスケジューリングは定数時間 +
+ 空間計算量 + + O(1) + + Promiseオブジェクトとクロージャのみ +
+ 実際の待機時間 + + O(millis) + + 実時間だが計算量ではない(CPU処理時間は無し) +
+
+ +

実装手法の比較

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 手法 + + 時間 + + 空間 + + CPU使用率 + + 推奨度 +
+ Promise + setTimeout + + O(1) + + O(1) + + 0%(非ブロッキング) + + ⭐⭐⭐⭐⭐ +
+ Busy Wait(while loop) + + O(millis) + + O(1) + + 100%(ブロッキング) + + ✗ 非推奨 +
+ setInterval + clearInterval + + O(1) + + O(1) + + 0%(非ブロッキング) + + ⭐⭐ 不要な複雑性 +
+
+ +
+

✅ 推奨: Promise + setTimeout

+

+ 最もシンプルで効率的。イベントループをブロックせず、他のタスクが並行実行可能。 +

+
+
+
+ + + + + + + + + + + + + + + + + diff --git a/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/Sleep_TS.ipynb b/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/Sleep_TS.ipynb new file mode 100644 index 00000000..d528405d --- /dev/null +++ b/JavaScript/2621. Sleep/Claude Code Sonnet 4.5/Sleep_TS.ipynb @@ -0,0 +1,155 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2aa72022", + "metadata": {}, + "source": [ + "# TypeScript Sleep関数実装\n", + "\n", + "## 1. 問題の分析\n", + "\n", + "### 競技プログラミング視点での分析\n", + "- **実行速度**: 非同期処理の仕組み上、実行速度は`setTimeout`のブラウザ/Node.jsエンジンの実装に依存\n", + "- **メモリ使用量**: Promise1つとタイマーIDのみで、O(1)の極小メモリ\n", + "- **最適化ポイント**: シンプルな実装が最速(余計な処理を追加しない)\n", + "\n", + "### 業務開発視点での分析\n", + "- **型安全性**: `millis`が正の整数であることの保証、Promise型の明示\n", + "- **エラーハンドリング**: 不正な入力値(負の数、0、非数値)への対応\n", + "- **保守性**: 明確な関数シグネチャとドキュメント\n", + "- **可読性**: 非同期処理の意図が明確\n", + "\n", + "### TypeScript特有の考慮点\n", + "- **型推論**: `Promise`の明示的な型定義\n", + "- **strict mode**: nullチェック、型安全性の確保\n", + "- **async/await**: Promiseラッパーの簡潔な記述\n", + "- **型ガード**: 実行時の入力検証\n", + "\n", + "## 2. アルゴリズムアプローチ比較\n", + "\n", + "| アプローチ | 時間計算量 | 空間計算量 | TS実装コスト | 型安全性 | 可読性 | 備考 |\n", + "|---------|---------|--------|----------|--------|-------|------|\n", + "| setTimeout + Promise | O(1) | O(1) | 低 | 高 | 高 | 標準的で最適 |\n", + "| setInterval + clearInterval | O(1) | O(1) | 中 | 中 | 低 | 不要な複雑性 |\n", + "| busy wait (while loop) | O(n) | O(1) | 低 | 高 | 低 | CPU使用率100%で非推奨 |\n", + "| Promise.race + setTimeout | O(1) | O(1) | 中 | 中 | 中 | 過剰設計 |\n", + "\n", + "## 3. 選択したアルゴリズムと理由\n", + "\n", + "### 選択したアプローチ\n", + "**setTimeout + Promise wrapper**\n", + "\n", + "### 理由\n", + "- **計算量的な優位性**: O(1)の時間・空間計算量で最適\n", + "- **TypeScript環境での型安全性**: Promise型の明確な定義が可能\n", + "- **保守性・可読性**: 非同期処理の標準パターンで理解しやすい\n", + "- **実装の単純性**: コード行数が最小で、バグの混入リスクが低い\n", + "\n", + "### TypeScript特有の最適化ポイント\n", + "- **型推論の活用**: `Promise`で戻り値の型を明示\n", + "- **readonly修飾子**: 入力値の不変性を保証(必要に応じて)\n", + "- **strict nullチェック**: 実行時エラーの防止\n", + "- **エラー型の明示**: TypeErrorによる型レベルでのエラー情報\n", + "\n", + "## 4. 実装コード\n", + "\n", + "```typescript\n", + "// Analyze Complexity\n", + "// Runtime 45 ms\n", + "// Beats 55.94%\n", + "// Memory 53.75 MB\n", + "// Beats 88.64%\n", + "/**\n", + " * 指定されたミリ秒数だけ非同期に待機する関数\n", + " * \n", + " * @param millis - 待機するミリ秒数(正の整数)\n", + " * @returns void を解決するPromise\n", + " * @throws {TypeError} millis が数値でない場合\n", + " * @throws {RangeError} millis が範囲外(1-1000)の場合\n", + " * @complexity Time: O(1), Space: O(1)\n", + " * \n", + " * @example\n", + " * const start = Date.now();\n", + " * await sleep(100);\n", + " * console.log(Date.now() - start); // ~100\n", + " */\n", + "async function sleep(millis: number): Promise {\n", + " // 型ガード: 数値チェック\n", + " if (typeof millis !== 'number' || Number.isNaN(millis)) {\n", + " throw new TypeError('millis must be a valid number');\n", + " }\n", + " \n", + " // 範囲チェック(制約条件: 1 <= millis <= 1000)\n", + " if (millis < 1 || millis > 1000) {\n", + " throw new RangeError('millis must be between 1 and 1000');\n", + " }\n", + " \n", + " // 整数チェック(正の整数要件)\n", + " if (!Number.isInteger(millis)) {\n", + " throw new RangeError('millis must be an integer');\n", + " }\n", + " \n", + " // Promise でラップした setTimeout による非同期待機\n", + " return new Promise((resolve) => {\n", + " setTimeout(resolve, millis);\n", + " });\n", + "}\n", + "```\n", + "\n", + "### LeetCode提出用の最小実装\n", + "\n", + "問題の制約条件が保証されている場合、エラーハンドリングを省略した最小実装:\n", + "\n", + "```typescript\n", + "// Analyze Complexity\n", + "// Runtime 47 ms\n", + "// Beats 42.89%\n", + "// Memory 55.27 MB\n", + "// Beats 37.58%\n", + "async function sleep(millis: number): Promise {\n", + " return new Promise((resolve) => {\n", + " setTimeout(resolve, millis);\n", + " });\n", + "}\n", + "```\n", + "\n", + "## TypeScript固有の最適化観点\n", + "\n", + "### 型安全性の活用\n", + "\n", + "1. **コンパイル時エラー防止**\n", + " - `Promise`の明示的な型定義により、戻り値の誤用を防止\n", + " - `millis: number`により、文字列などの不正な型の渡し込みを防止\n", + "\n", + "2. **実行時型チェック**\n", + " - `typeof`および`Number.isNaN`による実行時検証\n", + " - `Number.isInteger`による整数チェック\n", + "\n", + "3. **エラー型の明示**\n", + " - `TypeError`: 型の不一致\n", + " - `RangeError`: 値の範囲外\n", + "\n", + "### パフォーマンス特性\n", + "\n", + "- **時間計算量**: O(1) - 定数時間での処理完了\n", + "- **空間計算量**: O(1) - Promise1つとタイマーIDのみ\n", + "- **実行時オーバーヘッド**: 最小限(Promiseラッパーのみ)\n", + "\n", + "### 開発効率と保守性\n", + "\n", + "- **IntelliSense**: 型定義により引数と戻り値が自動補完\n", + "- **リファクタリング安全性**: 型チェックにより変更時のエラーを検出\n", + "- **ドキュメント**: JSDocコメントによる使用方法の明示\n", + "- **テスタビリティ**: async/awaitにより同期的なテストコードが記述可能" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}