From 4f9509027f49cdd7be22e72cd57f03fedaf22d95 Mon Sep 17 00:00:00 2001 From: myoshizumi Date: Thu, 22 Jan 2026 10:05:23 +0900 Subject: [PATCH] feat(shell): Add comprehensive Bash solution for LeetCode 194 - Transpose File Implement multiple approaches for file transposition with detailed explanations: - Basic 2D array approach using awk (Runtime: 72ms, Memory: 7.82MB) - Optimized string concatenation method (Runtime: 59-67ms, Memory: 3.99MB) - Alternative paste command approach (Runtime: 269ms, Memory: 3.59MB) Key improvements: - Reduced memory usage by 50% using 1D array instead of 2D - Improved runtime by 18-30% through efficient string concatenation - Added detailed visual diagrams explaining the transposition algorithm - Included performance analysis and complexity comparisons Performance highlights: - Best solution: 59ms runtime (Beats 93.40%), 3.99MB memory (Beats 91.05%) - Optimized for both competitive programming and production use cases --- .../194. Transpose File/TransposeFile.ipynb | 480 ++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 Shell/Bash/Leetcode/194. Transpose File/TransposeFile.ipynb diff --git a/Shell/Bash/Leetcode/194. Transpose File/TransposeFile.ipynb b/Shell/Bash/Leetcode/194. Transpose File/TransposeFile.ipynb new file mode 100644 index 00000000..41b2285e --- /dev/null +++ b/Shell/Bash/Leetcode/194. Transpose File/TransposeFile.ipynb @@ -0,0 +1,480 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "15f669e9", + "metadata": {}, + "source": [ + "この問題をbashで解決する方法を、詳細な図解とともに説明します。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94f12d08", + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "#!/bin/bash\n", + "\n", + "# file.txtの内容を転置する\n", + "\n", + "# 方法1: awkを使用したシンプルな解法\n", + "# Analyze Complexity\n", + "# Runtime 72 ms\n", + "# Beats 29.70%\n", + "# Memory 7.82 MB\n", + "# Beats 13.13%\n", + "awk '\n", + "{\n", + " # 各フィールドを配列に格納\n", + " for (i = 1; i <= NF; i++) {\n", + " a[NR, i] = $i\n", + " }\n", + "}\n", + "NF > p { p = NF } # 最大列数を記録\n", + "END {\n", + " # 転置して出力\n", + " for (j = 1; j <= p; j++) {\n", + " str = a[1, j]\n", + " for (i = 2; i <= NR; i++) {\n", + " str = str \" \" a[i, j]\n", + " }\n", + " print str\n", + " }\n", + "}\n", + "' file.txt" + ] + }, + { + "cell_type": "markdown", + "id": "dd18435a", + "metadata": {}, + "source": [ + "## 問題の理解\n", + "\n", + "この問題は**行列の転置**と同じ操作です。元のファイルの行と列を入れ替えます。\n", + "\n", + "### 入力例の視覚化\n", + "\n", + "```\n", + "元のファイル (2列 × 3行):\n", + "┌─────────────┐\n", + "│ name age │ ← 行1\n", + "│ alice 21 │ ← 行2\n", + "│ ryan 30 │ ← 行3\n", + "└─────────────┘\n", + " ↑ ↑\n", + " 列1 列2\n", + "```\n", + "\n", + "### 出力の視覚化\n", + "\n", + "```\n", + "転置後 (3列 × 2行):\n", + "┌────────────────────┐\n", + "│ name alice ryan │ ← 元の列1が行1に\n", + "│ age 21 30 │ ← 元の列2が行2に\n", + "└────────────────────┘\n", + "```\n", + "\n", + "## 解法の詳細説明\n", + "\n", + "### **ステップ1: データの読み込みと配列への格納**\n", + "\n", + "```\n", + "awk '{\n", + " for (i = 1; i <= NF; i++) {\n", + " a[NR, i] = $i\n", + " }\n", + "}'\n", + "```\n", + "\n", + "**図解:**\n", + "\n", + "```\n", + "読み込み処理:\n", + "\n", + "NR=1: name age\n", + " ↓ ↓\n", + " a[1,1] a[1,2]\n", + " name age\n", + "\n", + "NR=2: alice 21\n", + " ↓ ↓\n", + " a[2,1] a[2,2]\n", + " alice 21\n", + "\n", + "NR=3: ryan 30\n", + " ↓ ↓\n", + " a[3,1] a[3,2]\n", + " ryan 30\n", + "\n", + "結果の2次元配列:\n", + " 列1 列2\n", + " ┌──────┬─────┐\n", + "行1 │ name │ age │\n", + " ├──────┼─────┤\n", + "行2 │alice │ 21 │\n", + " ├──────┼─────┤\n", + "行3 │ ryan │ 30 │\n", + " └──────┴─────┘\n", + "```\n", + "\n", + "**変数の説明:**\n", + "- `NR`: 現在の行番号 (Number of Records)\n", + "- `NF`: 現在の行のフィールド数 (Number of Fields)\n", + "- `$i`: i番目のフィールド\n", + "- `a[NR, i]`: 2次元配列 (行, 列)\n", + "\n", + "### **ステップ2: 最大列数の記録**\n", + "\n", + "```\n", + "NF > p { p = NF }\n", + "```\n", + "\n", + "各行のフィールド数をチェックし、最大値を`p`に保存します。\n", + "\n", + "### **ステップ3: 転置して出力**\n", + "\n", + "```\n", + "END {\n", + " for (j = 1; j <= p; j++) {\n", + " str = a[1, j]\n", + " for (i = 2; i <= NR; i++) {\n", + " str = str \" \" a[i, j]\n", + " }\n", + " print str\n", + " }\n", + "}\n", + "```\n", + "\n", + "**図解:**\n", + "\n", + "```\n", + "転置処理:\n", + "\n", + "j=1のとき (元の列1):\n", + "┌─────┐\n", + "│name │ a[1,1] → str = \"name\"\n", + "├─────┤\n", + "│alice│ a[2,1] → str = \"name alice\"\n", + "├─────┤\n", + "│ryan │ a[3,1] → str = \"name alice ryan\"\n", + "└─────┘\n", + "出力: \"name alice ryan\"\n", + "\n", + "j=2のとき (元の列2):\n", + "┌─────┐\n", + "│age │ a[1,2] → str = \"age\"\n", + "├─────┤\n", + "│21 │ a[2,2] → str = \"age 21\"\n", + "├─────┤\n", + "│30 │ a[3,2] → str = \"age 21 30\"\n", + "└─────┘\n", + "出力: \"age 21 30\"\n", + "```\n", + "\n", + "## 別解: より簡潔なワンライナー\n", + "\n", + "```bash\n", + "awk '{for(i=1;i<=NF;i++)a[i]=a[i]\" \"$i}END{for(i=1;i<=NF;i++)print substr(a[i],2)}' file.txt\n", + "```\n", + "\n", + "この方法では、各列のデータを文字列として連結していきます。\n", + "\n", + "## 実行方法\n", + "\n", + "```bash\n", + "# スクリプトを実行権限付きで保存\n", + "chmod +x transpose.sh\n", + "\n", + "# 実行\n", + "./transpose.sh\n", + "\n", + "# または直接awkコマンドを実行\n", + "awk '{for(i=1;i<=NF;i++)a[NR,i]=$i}NF>p{p=NF}END{for(j=1;j<=p;j++){str=a[1,j];for(i=2;i<=NR;i++)str=str\" \"a[i,j];print str}}' file.txt\n", + "```\n", + "\n", + "## まとめ\n", + "\n", + "この解法のポイント:\n", + "1. **2次元配列**を使ってデータを格納\n", + "2. **外側ループ**で列を、**内側ループ**で行を処理\n", + "3. 行と列のインデックスを入れ替えることで転置を実現\n", + "\n", + "この手法は任意のサイズの行列に対応できます!" + ] + }, + { + "cell_type": "markdown", + "id": "8aa3d805", + "metadata": {}, + "source": [ + "現在の解法は機能的には正しいですが、パフォーマンスとメモリ使用量に改善の余地があります。より効率的な解法を提案します。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "887feb30", + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "#!/bin/bash\n", + "\n", + "# 最適化版: 文字列連結を使用してメモリ効率を改善\n", + "# Analyze Complexity\n", + "# Runtime 59 ms\n", + "# Beats 93.40%\n", + "# Memory 3.99 MB\n", + "# Beats 91.05%\n", + "\n", + "awk '\n", + "{\n", + " for (i = 1; i <= NF; i++) {\n", + " if (NR == 1) {\n", + " # 最初の行: 配列を初期化\n", + " a[i] = $i\n", + " } else {\n", + " # 2行目以降: スペース区切りで連結\n", + " a[i] = a[i] \" \" $i\n", + " }\n", + " }\n", + "}\n", + "END {\n", + " for (i = 1; i <= NF; i++) {\n", + " print a[i]\n", + " }\n", + "}\n", + "' file.txt" + ] + }, + { + "cell_type": "markdown", + "id": "7dc5ff1d", + "metadata": {}, + "source": [ + "## パフォーマンス比較と改善点\n", + "\n", + "### **元の解法の問題点**\n", + "\n", + "```\n", + "問題1: 2次元配列の使用\n", + "┌─────────────────────┐\n", + "│ a[1,1] a[1,2] │ メモリ使用量: O(行数 × 列数)\n", + "│ a[2,1] a[2,2] │ 各セルを個別に保存\n", + "│ a[3,1] a[3,2] │ アクセスオーバーヘッドが大きい\n", + "└─────────────────────┘\n", + "\n", + "問題2: 二重ループでの文字列連結\n", + "END {\n", + " for (j = 1; j <= p; j++) {\n", + " str = a[1, j] ← 毎回新しい文字列を作成\n", + " for (i = 2; i <= NR; i++) {\n", + " str = str \" \" a[i, j] ← 文字列を何度も再構築\n", + " }\n", + " print str\n", + " }\n", + "}\n", + "```\n", + "\n", + "### **改善版の利点**\n", + "\n", + "```\n", + "改善1: 1次元配列 + 文字列連結\n", + "┌──────────────────────┐\n", + "│ a[1] = \"name alice ryan\" │ メモリ: O(列数)のみ\n", + "│ a[2] = \"age 21 30\" │ 各列を1つの文字列として保存\n", + "└──────────────────────────┘\n", + "\n", + "改善2: 処理中に連結\n", + "{\n", + " for (i = 1; i <= NF; i++) {\n", + " a[i] = a[i] \" \" $i ← 読み込みながら連結\n", + " }\n", + "}\n", + "END {\n", + " for (i = 1; i <= NF; i++) {\n", + " print a[i] ← 単純な出力のみ\n", + " }\n", + "}\n", + "```\n", + "\n", + "## さらなる最適化オプション\n", + "\n", + "### **オプション1: rs コマンド (最速)**\n", + "\n", + "```bash\n", + "# rsコマンドを使用 (利用可能な場合)\n", + "rs -T < file.txt\n", + "```\n", + "\n", + "**特徴:**\n", + "- C言語で実装された専用ツール\n", + "- 最も高速\n", + "- ただし、一部のシステムでは利用不可\n", + "\n", + "### **オプション2: 改良版awkスクリプト**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8fb82fee", + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "#!/bin/bash\n", + "\n", + "# 方法1: 最適化版 (推奨) - メモリ効率が良い\n", + "# Analyze Complexity\n", + "# Runtime 63 ms\n", + "# Beats 77.60%\n", + "# Memory 3.99 MB\n", + "# Beats 91.05%\n", + "\n", + "awk '{for(i=1;i<=NF;i++)a[i]=a[i](NR>1?\" \":\"\")$i}END{for(i=1;i<=NF;i++)print a[i]}' file.txt\n", + "\n", + "# 方法2: 可読性重視版\n", + "# Analyze Complexity\n", + "# Runtime 67 ms\n", + "# Beats 53.43%\n", + "# Memory 3.98 MB\n", + "# Beats 91.05%\n", + "\n", + "awk '\n", + "{\n", + " for (i = 1; i <= NF; i++) {\n", + " a[i] = a[i] (NR > 1 ? \" \" : \"\") $i\n", + " }\n", + "}\n", + "END {\n", + " for (i = 1; i <= NF; i++) {\n", + " print a[i]\n", + " }\n", + "}\n", + "' file.txt\n", + "\n", + "# 方法3: pasteコマンド利用 (Bash純正アプローチ)\n", + "# Analyze Complexity\n", + "# Runtime 269 ms\n", + "# Beats 5.64%\n", + "# Memory 3.59 MB\n", + "# Beats 100.00%\n", + "\n", + "cols=$(head -1 file.txt | wc -w)\n", + "for i in $(seq 1 $cols); do\n", + " cut -d' ' -f$i file.txt | paste -sd' '\n", + "done" + ] + }, + { + "cell_type": "markdown", + "id": "fe45a9c8", + "metadata": {}, + "source": [ + "## パフォーマンス分析\n", + "\n", + "### **時間計算量の比較**\n", + "\n", + "```\n", + "元の解法:\n", + "- 読み込み: O(行数 × 列数)\n", + "- 出力: O(行数 × 列数)\n", + "- 合計: O(2 × 行数 × 列数)\n", + "\n", + "改善版:\n", + "- 読み込み+連結: O(行数 × 列数)\n", + "- 出力: O(列数)\n", + "- 合計: O(行数 × 列数 + 列数)\n", + "```\n", + "\n", + "### **メモリ使用量の比較**\n", + "\n", + "```\n", + "元の解法:\n", + "┌──────────────────────────────┐\n", + "│ 2次元配列: 行数 × 列数 個の要素 │\n", + "│ 一時文字列: 列数 個 │\n", + "│ 合計: O(行数 × 列数) │\n", + "└──────────────────────────────┘\n", + "\n", + "改善版:\n", + "┌──────────────────────────────┐\n", + "│ 1次元配列: 列数 個の文字列 │\n", + "│ 各文字列長: 行数 × 平均単語長 │\n", + "│ 合計: O(列数 × 行数) だが │\n", + "│ 実装が効率的 │\n", + "└──────────────────────────────┘\n", + "```\n", + "\n", + "### **実行例の詳細図解**\n", + "\n", + "```\n", + "入力: file.txt\n", + "┌─────────────┐\n", + "│ name age │\n", + "│ alice 21 │\n", + "│ ryan 30 │\n", + "└─────────────┘\n", + "\n", + "処理フロー:\n", + "\n", + "NR=1: name age\n", + " ↓ ↓\n", + " a[1]=\"name\"\n", + " a[2]=\"age\"\n", + "\n", + "NR=2: alice 21\n", + " ↓ ↓\n", + " a[1]=\"name alice\" ← スペース追加して連結\n", + " a[2]=\"age 21\"\n", + "\n", + "NR=3: ryan 30\n", + " ↓ ↓\n", + " a[1]=\"name alice ryan\"\n", + " a[2]=\"age 21 30\"\n", + "\n", + "END処理:\n", + " print a[1] → \"name alice ryan\"\n", + " print a[2] → \"age 21 30\"\n", + "```\n", + "\n", + "## ベンチマーク予想\n", + "\n", + "改善版の期待値:\n", + "- **Runtime**: 40-50ms (約40-50%改善)\n", + "- **Memory**: 4-5MB (約35-40%改善)\n", + "\n", + "### **主な改善要因**\n", + "\n", + "1. **配列アクセスの削減**: 2次元→1次元\n", + "2. **ループネストの削減**: 二重ループ→単一ループ\n", + "3. **文字列操作の最適化**: 逐次連結→直接連結\n", + "4. **条件分岐の最適化**: 三項演算子の使用\n", + "\n", + "この最適化により、上位50-70%のパフォーマンスが期待できます!" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}