diff --git a/Shell/Bash/Leetcode/193. Valid Phone Numbers/ValidPhoneNumbers.ipynb b/Shell/Bash/Leetcode/193. Valid Phone Numbers/ValidPhoneNumbers.ipynb new file mode 100644 index 00000000..a5d8da92 --- /dev/null +++ b/Shell/Bash/Leetcode/193. Valid Phone Numbers/ValidPhoneNumbers.ipynb @@ -0,0 +1,245 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e7bafc2d", + "metadata": {}, + "source": [ + "# 電話番号フィルタリング問題の解説\n", + "\n", + "この問題を段階的に解説し、bash one-linerで解決します。\n", + "\n", + "## 問題の理解\n", + "\n", + "**有効な電話番号の形式:**\n", + "1. `(xxx) xxx-xxxx` - カッコ付き形式\n", + "2. `xxx-xxx-xxxx` - ハイフン形式\n", + "\n", + "ここで `x` は数字(0-9)を表します。\n", + "\n", + "## 解決策" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39aacb70", + "metadata": { + "vscode": { + "languageId": "powershell" + } + }, + "outputs": [], + "source": [ + "#!/bin/bash\n", + "\n", + "# Solution 1: Using grep with extended regex\n", + "# Analyze Complexity\n", + "# Runtime 63 ms\n", + "# Beats 58.79%\n", + "# Memory 3.47 MB\n", + "# Beats 84.10%\n", + "\n", + "grep -E '^([0-9]{3}-[0-9]{3}-[0-9]{4}|\\([0-9]{3}\\) [0-9]{3}-[0-9]{4})$' file.txt\n", + "\n", + "# Solution 2: Using sed (alternative)\n", + "# Analyze Complexity\n", + "# Runtime 65 ms\n", + "# Beats 45.95%\n", + "# Memory 3.42 MB\n", + "# Beats 84.10%\n", + "\n", + "sed -n -E '/^([0-9]{3}-[0-9]{3}-[0-9]{4}|\\([0-9]{3}\\) [0-9]{3}-[0-9]{4})$/p' file.txt\n", + "\n", + "# Solution 3: Using awk (alternative)\n", + "# Analyze Complexity\n", + "# Runtime 71 ms\n", + "# Beats 15.78%\n", + "# Memory 3.84 MB\n", + "# Beats 3.13%\n", + "\n", + "awk '/^([0-9]{3}-[0-9]{3}-[0-9]{4}|\\([0-9]{3}\\) [0-9]{3}-[0-9]{4})$/' file.txt" + ] + }, + { + "cell_type": "markdown", + "id": "e5ef6417", + "metadata": {}, + "source": [ + "## 最もシンプルな解答\n", + "\n", + "```bash\n", + "grep -E '^([0-9]{3}-[0-9]{3}-[0-9]{4}|\\([0-9]{3}\\) [0-9]{3}-[0-9]{4})$' file.txt\n", + "```\n", + "\n", + "---\n", + "\n", + "## 詳細な図解による解説\n", + "\n", + "### 1. 正規表現パターンの構造\n", + "\n", + "```\n", + "^([0-9]{3}-[0-9]{3}-[0-9]{4}|\\([0-9]{3}\\) [0-9]{3}-[0-9]{4})$\n", + "```\n", + "\n", + "この正規表現を分解して理解しましょう:\n", + "\n", + "#### **全体構造**\n", + "```\n", + " ^ $\n", + " | |\n", + " 行頭 OR演算子 行末\n", + " ┌──────────────────┴──────────────────┐\n", + " | |\n", + " パターン1 パターン2\n", + " xxx-xxx-xxxx (xxx) xxx-xxxx\n", + "```\n", + "\n", + "#### **パターン1: `[0-9]{3}-[0-9]{3}-[0-9]{4}`**\n", + "\n", + "```\n", + " [0-9]{3} - [0-9]{3} - [0-9]{4}\n", + " │ │ │ │ │\n", + " 3桁の数字 ハイフン 3桁の数字 ハイフン 4桁の数字\n", + " │ │ │\n", + " 987 123 4567\n", + "\n", + "例: 987-123-4567\n", + "```\n", + "\n", + "#### **パターン2: `\\([0-9]{3}\\) [0-9]{3}-[0-9]{4}`**\n", + "\n", + "```\n", + " \\( [0-9]{3} \\) スペース [0-9]{3} - [0-9]{4}\n", + " │ │ │ │ │ │ │\n", + " 左カッコ 3桁 右カッコ 空白 3桁 ハイフン 4桁\n", + " │ │ │ │ │\n", + " ( 123 ) 456 7890\n", + "\n", + "例: (123) 456-7890\n", + "```\n", + "\n", + "**重要ポイント:** `\\(` と `\\)` はエスケープが必要です(カッコ自体を表すため)\n", + "\n", + "---\n", + "\n", + "### 2. grep コマンドの動作フロー\n", + "\n", + "```\n", + "┌─────────────────────────────────────────────────┐\n", + "│ file.txt の内容 │\n", + "├─────────────────────────────────────────────────┤\n", + "│ 行1: 987-123-4567 │\n", + "│ 行2: 123 456 7890 │\n", + "│ 行3: (123) 456-7890 │\n", + "├─────────────────────────────────────────────────┤\n", + " ↓ grep -E で各行をチェック\n", + "├─────────────────────────────────────────────────┤\n", + "│ パターンマッチング │\n", + "├─────────────────────────────────────────────────┤\n", + "│ 行1: 987-123-4567 │\n", + "│ ✓ パターン1にマッチ → 出力 │\n", + "│ │\n", + "│ 行2: 123 456 7890 │\n", + "│ ✗ どちらのパターンにもマッチしない │\n", + "│ (スペースがハイフンではない) │\n", + "│ │\n", + "│ 行3: (123) 456-7890 │\n", + "│ ✓ パターン2にマッチ → 出力 │\n", + "├─────────────────────────────────────────────────┤\n", + " ↓ 結果出力\n", + "├─────────────────────────────────────────────────┤\n", + "│ 987-123-4567 │\n", + "│ (123) 456-7890 │\n", + "└─────────────────────────────────────────────────┘\n", + "```\n", + "\n", + "---\n", + "\n", + "### 3. オプションの説明\n", + "\n", + "```bash\n", + "grep -E '^pattern$' file.txt\n", + " │ │ └─ 入力ファイル\n", + " │ └─ 正規表現パターン\n", + " └─ Extended Regular Expression (拡張正規表現)\n", + "```\n", + "\n", + "- **`-E`**: 拡張正規表現を使用(+, ?, |, () などが使える)\n", + "- **`^`**: 行頭にマッチ(余分な文字がないことを保証)\n", + "- **`$`**: 行末にマッチ(余分な文字がないことを保証)\n", + "\n", + "---\n", + "\n", + "### 4. テストケースの検証\n", + "\n", + "#### **有効な番号**\n", + "```\n", + "✓ 987-123-4567\n", + " [0-9]{3}-[0-9]{3}-[0-9]{4} にマッチ\n", + " \n", + "✓ (123) 456-7890\n", + " \\([0-9]{3}\\) [0-9]{3}-[0-9]{4} にマッチ\n", + "```\n", + "\n", + "#### **無効な番号**\n", + "```\n", + "✗ 123 456 7890\n", + " 理由: ハイフンではなくスペースで区切られている\n", + " \n", + "✗ 1234567890\n", + " 理由: 区切り文字がない\n", + " \n", + "✗ (123)456-7890\n", + " 理由: カッコの後にスペースがない\n", + " \n", + "✗ 12-345-6789\n", + " 理由: 最初のグループが2桁(3桁が必要)\n", + "```\n", + "\n", + "---\n", + "\n", + "### 5. 実行例\n", + "\n", + "```bash\n", + "# file.txtを作成\n", + "$ cat > file.txt << EOF\n", + "987-123-4567\n", + "123 456 7890\n", + "(123) 456-7890\n", + "EOF\n", + "\n", + "# スクリプトを実行\n", + "$ grep -E '^([0-9]{3}-[0-9]{3}-[0-9]{4}|\\([0-9]{3}\\) [0-9]{3}-[0-9]{4})$' file.txt\n", + "\n", + "# 出力\n", + "987-123-4567\n", + "(123) 456-7890\n", + "```\n", + "\n", + "---\n", + "\n", + "## まとめ\n", + "\n", + "**最適解:**\n", + "```bash\n", + "grep -E '^([0-9]{3}-[0-9]{3}-[0-9]{4}|\\([0-9]{3}\\) [0-9]{3}-[0-9]{4})$' file.txt\n", + "```\n", + "\n", + "この一行で:\n", + "- 2つの有効な形式を検出\n", + "- 行頭と行末の厳密なマッチング\n", + "- シンプルで効率的な実装\n", + "\n", + "が実現できます!" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}