Compare commits

...

2 Commits

22 changed files with 199 additions and 352 deletions

View File

@@ -45,6 +45,8 @@ chmod +x utils/leetcode_helper.sh
# 範例
./utils/leetcode_helper.sh problem 1 two-sum Easy
./utils/leetcode_helper.sh problem 3000 maximum-area-rectangle Medium
# 顯示說明:
./utils/leetcode_helper.sh --help
```
建立完成後的結構(示意):
@@ -62,10 +64,7 @@ problems/NNNN-name/
├── SolutionTests.cs # xUnit 測試
├── TestProject.csproj
├── main_test.go # Go testing
── input1.txt / output1.txt
├── input2.txt / output2.txt
├── edge_cases.md
└── run_tests.sh # 一鍵執行 C# 與 Go 測試
── edge_cases.md
```
- 建立月度日誌(依模板生成 `logs/YYYY-MM.md`
@@ -99,8 +98,16 @@ go run main.go
- 執行該題的測試(同時跑 C# 與 Go
```
cd problems/NNNN-name/test
./run_tests.sh
./utils/run_tests.sh NNNN-name [all|csharp|go]
# 也可只給題號:
./utils/run_tests.sh 3025
# 僅跑 C# 或 Go
./utils/run_tests.sh 3025 csharp
./utils/run_tests.sh 3025 go
# 顯示說明:
./utils/run_tests.sh --help
# 列出目前可用題目:
./utils/run_tests.sh --list
```
或分別執行:
@@ -118,7 +125,7 @@ go test -v
- problem根據輸入的題號、名稱與難度建立一個完整題目骨架
- 產生題目 `README.md`(含題目資訊、思路、測試與筆記段落)
- 建立 `csharp/``go/` 目錄及基本程式碼
- 建立 `test/` 目錄,內含 xUnit、Go 測試模板`run_tests.sh`
- 建立 `test/` 目錄,內含 xUnit、Go 測試模板(統一用 `utils/run_tests.sh` 執行)
- 初始化 Go module`go.mod`
- readme掃描 `problems/` 題目數量,輸出簡單統計到終端(可再擴充寫回本檔)
- log`templates/logs-template.md.tmpl` 生成月誌雛形,方便每日記錄與月度回顧
@@ -236,6 +243,28 @@ func TestFindClosest(t *testing.T) {
- 月誌:`templates/logs-template.md.tmpl`
不需修改腳本本身即可客製化模板。
## 工具清單
- `utils/leetcode_helper.sh`: 管理題目與月誌
- 功能:
- `problem <題號> <題目名稱-kebab> <難度>`:建立新題目(產生 `README.md``csharp/``go/``test/` 骨架)
- `log [YYYY-MM]`:建立月度學習日誌(預設本月)
- `readme`:顯示題目數量統計
- `-h|--help`:顯示說明
- 範例:
- `./utils/leetcode_helper.sh problem 3025 find-the-number-of-ways-to-place-people-i Medium`
- `./utils/leetcode_helper.sh log 2025-09`
- `./utils/leetcode_helper.sh --help`
- `utils/run_tests.sh`: 執行指定題目的測試
- 語法:`./utils/run_tests.sh <problem> [all|csharp|go]`
- <problem> 可為:題號(如 `3025`/ 目錄名(如 `3025-find-…`/ 完整路徑(如 `problems/3025-…`
- 參數:`--help` 顯示說明、`--list` 列出現有題目
- 範例:
- `./utils/run_tests.sh 3025`(同時跑 C# 與 Go
- `./utils/run_tests.sh 3025 csharp`(只跑 C#
- `./utils/run_tests.sh --list`
## 未來可擴充方向
- 主 README 自動彙整各題狀態(難度、語言、連結、完成度)

View File

@@ -1,91 +0,0 @@
# [42] Answer To Everything
## 題目資訊
- **難度**: Easy
- **標籤**:
- **題目連結**: https://leetcode.com/problems/answer-to-everything/
- **練習日期**: 2025-09-12
- **目標複雜度**: 時間 O(?)、空間 O(?)
## 題目描述
> 在這裡貼上題目的完整描述(或重點)
## 先備條件與限制
- 輸入限制n ∈ [?, ?]、值域 ∈ [?, ?]
- 回傳/輸出格式:...
- 其他:是否允許排序/就地修改
## 解題思路
### 初步分析
- 類型:雙指針 / 滑動視窗 / 排序 / DP / 貪心 / 圖論 ...
- 關鍵觀察:
- 複雜度目標理由:
### 解法比較
1. 解法A基準/暴力):
- 思路:
- 正確性:
- 複雜度O(?) / O(?)
2. 解法B優化
- 思路:
- 正確性:
- 複雜度O(?) / O(?)
### 乾跑Dry Run
- 範例:...
## 實作細節與 API 設計
### C# 方法簽名(示意)
```csharp
public class Solution {
// TODO: 根據題意調整簽名
public int Solve(int[] nums) {
return 0;
}
}
```
### Go 方法簽名(示意)
```go
func solve(nums []int) int {
return 0
}
```
### 常見陷阱
- 邊界:空/單一/極值/全相等
- 去重:排序後跳重複、集合
- 溢位:使用 64-bit
## 測試案例
### 範例輸入輸出
```
Input: ...
Output: ...
Explanation: ...
```
### 邊界清單
- [ ] 空陣列/空字串
- [ ] 單一元素 / 全相同
- [ ] 含負數/0/大數
- [ ] 去重
- [ ] 大資料壓力
## 複雜度分析
- 最壞:時間 O(?)、空間 O(?)
## 相關題目 / Follow-up
-
## 學習筆記
- 今天學到:
- 卡住與修正:
- 待優化:
---
**總結**:這題的核心在於 ______,適合練習 ______

View File

@@ -1,24 +0,0 @@
// LeetCode 42: Answer To Everything
// 難度: Easy
// 日期: 2025-09-12
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
// TODO: 根據題意調整簽名
public int Solve(int[] nums) {
// 實作解法
return 0;
}
}
public class Program {
public static void Main() {
var s = new Solution();
// TODO: 可加入簡單輸入/輸出測試
Console.WriteLine("Hello LeetCode 42!");
}
}

View File

@@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -1,18 +0,0 @@
// LeetCode 42: Answer To Everything
// 難度: Easy
// 日期: 2025-09-12
package main
import "fmt"
// TODO: 根據題意調整簽名
func solve(nums []int) int {
return 0
}
func main() {
fmt.Printf("Hello LeetCode 42!\n")
// TODO: 可加入簡單測試
}

View File

@@ -1,24 +0,0 @@
// LeetCode 42 單元測試xUnit
using Xunit;
public class SolutionTests {
private readonly Solution _s = new Solution();
[Fact]
public void Example1() {
// TODO: Arrange
// var input = new int[] { };
// var expected = 0;
// Act
// var got = _s.Solve(input);
// Assert.Equal(expected, got);
Assert.True(true);
}
[Fact]
public void EdgeCases() {
Assert.True(true);
}
}

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,20 +0,0 @@
# 邊界情況清單42 Answer To Everything
## 需要測試的邊界
- [ ] 空輸入 / 單一元素
- [ ] 重複元素 / 全相同
- [ ] 極值(最小/最大)
- [ ] 含負數 / 0 / 大數
- [ ] 大資料量(接近上限)
## 額外案例
### 案例 1
- 輸入:
- 預期:
- 說明:
### 案例 2
- 輸入:
- 預期:
- 說明:

View File

@@ -1,2 +0,0 @@
# 測試案例 1 輸入42 Answer To Everything

View File

@@ -1,2 +0,0 @@
# 測試案例 2 輸入42 Answer To Everything

View File

@@ -1,12 +0,0 @@
// LeetCode 42 單元測試Go testing
package main
import "testing"
func TestExample(t *testing.T) {
// TODO: input := []int{}
// got := solve(input)
// want := 0
// if got != want { t.Fatalf("want %v got %v", want, got) }
}

View File

@@ -1,2 +0,0 @@
# 測試案例 1 期望輸出42 Answer To Everything

View File

@@ -1,2 +0,0 @@
# 測試案例 2 期望輸出42 Answer To Everything

View File

@@ -1,36 +0,0 @@
#!/bin/bash
set -e
echo "🧪 執行測試: 0042-answer-to-everything"
echo "=========================="
pushd "$(dirname "$0")" >/dev/null
echo "📋 C# 測試結果:"
if (cd ../csharp && dotnet build >/dev/null 2>&1); then
if dotnet test --logger "console;verbosity=minimal" >/dev/null 2>&1; then
echo "✅ C# 測試通過"
else
echo "❌ C# 測試失敗"
fi
else
echo "❌ C# 編譯失敗"
fi
echo ""
echo "📋 Go 測試結果:"
if (cd ../go && go build >/dev/null 2>&1); then
if go test -v >/dev/null 2>&1; then
echo "✅ Go 測試通過"
else
echo "❌ Go 測試失敗(顯示詳細)"
go test -v
fi
else
echo "❌ Go 編譯失敗"
fi
popd >/dev/null
echo ""
echo "📊 測試完成!"

View File

@@ -1,21 +0,0 @@
#!/bin/bash
echo "🧪 執行 LeetCode 題目測試"
echo "=========================="
# 執行 C# 測試
echo "📋 C# 測試結果:"
cd ../csharp
if dotnet build > /dev/null 2>&1; then
cd ../test
if dotnet test --logger "console;verbosity=minimal" 2>/dev/null; then
echo "✅ C# 測試通過"
else
echo "❌ C# 測試失敗"
fi
else
echo "❌ C# 編譯失敗"
fi
echo ""
echo "📊 測試完成!"

View File

@@ -1,2 +0,0 @@
# 測試案例 1 輸入({{NUMBER}} {{NAME_TITLE}}

View File

@@ -1,2 +0,0 @@
# 測試案例 2 輸入({{NUMBER}} {{NAME_TITLE}}

View File

@@ -1,2 +0,0 @@
# 測試案例 1 期望輸出({{NUMBER}} {{NAME_TITLE}}

View File

@@ -1,2 +0,0 @@
# 測試案例 2 期望輸出({{NUMBER}} {{NAME_TITLE}}

View File

@@ -1,36 +0,0 @@
#!/bin/bash
set -e
echo "🧪 執行測試: {{NUMBER_PAD}}-{{NAME_SLUG}}"
echo "=========================="
pushd "$(dirname "$0")" >/dev/null
echo "📋 C# 測試結果:"
if (cd ../csharp && dotnet build >/dev/null 2>&1); then
if dotnet test --logger "console;verbosity=minimal" >/dev/null 2>&1; then
echo "✅ C# 測試通過"
else
echo "❌ C# 測試失敗"
fi
else
echo "❌ C# 編譯失敗"
fi
echo ""
echo "📋 Go 測試結果:"
if (cd ../go && go build >/dev/null 2>&1); then
if go test -v >/dev/null 2>&1; then
echo "✅ Go 測試通過"
else
echo "❌ Go 測試失敗(顯示詳細)"
go test -v
fi
else
echo "❌ Go 編譯失敗"
fi
popd >/dev/null
echo ""
echo "📊 測試完成!"

View File

@@ -47,6 +47,34 @@ render_template() {
"$src" > "$dest"
}
# 顯示說明
show_help() {
cat << EOF
LeetCode Practice Helper
用法:
$0 problem <題號> <題目名稱-kebab> <難度>
$0 log [YYYY-MM]
$0 readme
$0 -h | --help
說明:
problem 建立新題目(會建立 C#/Go 骨架、測試模板與 README
log 建立月度學習日誌(預設為本月,或指定 YYYY-MM
readme 顯示題目數量統計(可擴充為寫回 README
範例:
$0 problem 1 two-sum Easy
$0 problem 3025 find-the-number-of-ways-to-place-people-i Medium
$0 log 2025-09
$0 readme
測試:
建議使用 utils/run_tests.sh 執行,例:
utils/run_tests.sh 3025 [all|csharp|go]
EOF
}
# 建立測試檔案(來自 templates/problem/test/*
create_test_files() {
local problem_dir="$1"; local number="$2"; local name_slug="$3"; local difficulty="$4"
@@ -71,19 +99,7 @@ create_test_files() {
"$problem_dir/test/edge_cases.md" \
"$number" "$number_pad" "$name_slug" "$name_title" "$difficulty" "$today" "$year_month"
render_template "$TEMPLATES_DIR/problem/test/input1.txt.tmpl" "$problem_dir/test/input1.txt" \
"$number" "$number_pad" "$name_slug" "$name_title" "$difficulty" "$today" "$year_month"
render_template "$TEMPLATES_DIR/problem/test/output1.txt.tmpl" "$problem_dir/test/output1.txt" \
"$number" "$number_pad" "$name_slug" "$name_title" "$difficulty" "$today" "$year_month"
render_template "$TEMPLATES_DIR/problem/test/input2.txt.tmpl" "$problem_dir/test/input2.txt" \
"$number" "$number_pad" "$name_slug" "$name_title" "$difficulty" "$today" "$year_month"
render_template "$TEMPLATES_DIR/problem/test/output2.txt.tmpl" "$problem_dir/test/output2.txt" \
"$number" "$number_pad" "$name_slug" "$name_title" "$difficulty" "$today" "$year_month"
render_template "$TEMPLATES_DIR/problem/test/run_tests.sh.tmpl" \
"$problem_dir/test/run_tests.sh" \
"$number" "$number_pad" "$name_slug" "$name_title" "$difficulty" "$today" "$year_month"
chmod +x "$problem_dir/test/run_tests.sh"
# 不再產生每題的 run_tests.sh請改用 utils/run_tests.sh
}
# 建立新題目
@@ -127,7 +143,7 @@ create_problem() {
echo "✅ 已建立題目: $problem_dir"
echo "C#: cd problems/${folder_name}/csharp && dotnet run"
echo "Go: cd problems/${folder_name}/go && go run main.go"
echo "測試: cd problems/${folder_name}/test && ./run_tests.sh"
echo "測試: utils/run_tests.sh ${number_pad}-${name_slug} [all|csharp|go]"
}
# 更新主 README目前僅統計列印
@@ -152,6 +168,13 @@ create_monthly_log() {
}
# 入口
# --help
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
show_help
exit 0
fi
case "${1:-}" in
problem)
create_problem "${2:-}" "${3:-}" "${4:-}" ;;
@@ -160,10 +183,6 @@ case "${1:-}" in
log)
create_monthly_log "${2:-}" ;;
*)
echo "LeetCode Practice Helper"
echo "使用:"
echo " $0 problem <題號> <題目名稱-kebab> <難度>"
echo " $0 readme"
echo " $0 log [YYYY-MM]"
show_help
;;
esac

125
utils/run_tests.sh Executable file
View File

@@ -0,0 +1,125 @@
#!/bin/bash
set -euo pipefail
# Usage:
# utils/run_tests.sh <problem> [all|csharp|go]
# Examples:
# utils/run_tests.sh 3025
# utils/run_tests.sh 3025 csharp
# utils/run_tests.sh problems/3025-find-the-number-of-ways-to-place-people-i go
# utils/run_tests.sh 3516-find-closest-person all
# Help:
# utils/run_tests.sh -h | --help
# List:
# utils/run_tests.sh --list
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
ROOT_DIR=$(cd "$SCRIPT_DIR/.." && pwd)
show_help() {
cat << EOF
Run tests for a problem folder.
Usage:
$0 <problem> [all|csharp|go]
$0 --list
Where <problem> can be:
- A number (e.g., 3025)
- A 4-digit + slug folder name (e.g., 3025-find-the-number-of-ways-to-place-people-i)
- A relative path under problems/ (e.g., problems/3025-find-the-number-of-ways-to-place-people-i)
Examples:
$0 3025 # run both C# and Go tests
$0 3025 csharp # only C#
$0 3516 go # only Go
$0 3516-find-closest-person all
$0 problems/3516-find-closest-person all
$0 --list # list available problems
EOF
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
show_help
exit 0
fi
if [[ "${1:-}" == "--list" ]]; then
echo "Available problems (from problems/):"
# List directories matching 4-digit prefix
find "$ROOT_DIR/problems" -maxdepth 1 -mindepth 1 -type d -printf "%f\n" \
| sort \
| awk 'BEGIN{printf("%-8s %s\n","Number","Slug"); printf("%-8s %s\n","------","----");}
{num=substr($0,1,4); slug=substr($0,6); printf("%-8s %s\n", num, $0)}'
exit 0
fi
problem_arg="${1:-}"
lang="${2:-all}"
if [[ -z "$problem_arg" ]]; then
show_help >&2
exit 1
fi
resolve_problem_dir() {
local arg="$1"
if [[ -d "$ROOT_DIR/$arg" ]]; then
echo "$ROOT_DIR/$arg"
return 0
fi
if [[ "$arg" =~ ^[0-9]+$ ]]; then
local num=$(printf "%04d" "$arg")
local match
match=$(find "$ROOT_DIR/problems" -maxdepth 1 -type d -name "${num}-*" | head -n 1 || true)
if [[ -n "$match" ]]; then
echo "$match"; return 0
fi
fi
# try exact name under problems
if [[ -d "$ROOT_DIR/problems/$arg" ]]; then
echo "$ROOT_DIR/problems/$arg"; return 0
fi
echo "Cannot resolve problem directory from '$arg'" >&2
exit 1
}
PROB_DIR=$(resolve_problem_dir "$problem_arg")
TEST_DIR="$PROB_DIR/test"
CS_DIR="$PROB_DIR/csharp"
GO_DIR="$PROB_DIR/go"
run_csharp() {
if [[ ! -d "$CS_DIR" || ! -d "$TEST_DIR" ]]; then
echo "[C#] Skipped (missing csharp or test folder)"; return 0
fi
echo "📋 C# 測試結果:"
if (cd "$CS_DIR" && dotnet build >/dev/null 2>&1); then
(cd "$TEST_DIR" && dotnet test --logger "console;verbosity=minimal") || { echo "❌ C# 測試失敗"; return 1; }
echo "✅ C# 測試通過"
else
echo "❌ C# 編譯失敗"; return 1
fi
}
run_go() {
if [[ ! -d "$GO_DIR" || ! -d "$TEST_DIR" ]]; then
echo "[Go] Skipped (missing go or test folder)"; return 0
fi
echo "📋 Go 測試結果:"
if (cd "$GO_DIR" && go build >/dev/null 2>&1); then
(cd "$TEST_DIR" && go test -v) || { echo "❌ Go 測試失敗"; return 1; }
echo "✅ Go 測試通過"
else
echo "❌ Go 編譯失敗"; return 1
fi
}
case "$lang" in
all) run_csharp; run_go ;;
csharp) run_csharp ;;
go) run_go ;;
*) echo "Unknown lang '$lang' (use all|csharp|go)" >&2; exit 1 ;;
esac
echo "📊 測試完成: $PROB_DIR"