【Rust】【TS】ひとまとまりの処理群のメモ

# 記載概要
言語を学ぶ上で、文法やメソッドを覚えたら、
次覚えるべきひとまとまりの処理群のめも

# 意図
処理群覚えてないようじゃプロとしては無理か、
処理群はね、覚えておかないとね、引き出し多くないとプロは
（といっても2025/4時点では著者はrust初学者）

# やったこと
一つ一つ、写経した。写経しただけで、エラー出るが、基本的なことが勉強になった

# なぜRustの勉強に至ったか。
そもそもなぜRust至の勉強に至ったかというと、処理が早い、が結局正義。いままでのプロジェクトで、速度問題にぶち当たらなかったことがなかった。結局、メモリ管理が全てを解決する。物理こそ正義。そのため、Rustの勉強を開始した。

# 初学者ではあるが、ここまでにやったこと
Rustがなぜ早いか、ガベージコレクション採用していないことのよさ、型定義で何しているか（=型定義で、使うメモリ領域のサイズ決めてる）など、Rustの意図をchatgptに聞きまくった。

# 基本で勉強になったこと
- Vec<T>の表示はprintln!("{:?}")の理由（{}はエラー）
→Vec<T>はDebugトレイトは実装アリだが、Displayトレイトは実装されていない、
- Displayトレイトは、「人間向けの表現」を提供する意図。Vecの中身は安全のためDisplayトレイトを実装していない

# ほんきじの処理群 
🔁 非同期・時間・並列処理
1. 一定時間ごとに繰り返し処理（interval）
1. 非同期タスクを直列で順に実行（await順次処理）
1. 非同期タスクを並列に実行してすべて完了を待つ（Promise.all / join_all）
1. バックグラウンド処理とUI更新を分離
1. リトライ付きAPI呼び出し（指数バックオフ付き）
1. 処理時間の計測（ベンチマーク用）

📦 ファイル/データ/入出力
1. ファイルの存在確認・作成・削除
1. ログファイルに時刻付きで書き出す
1. 巨大ファイルのストリーム処理（読み込み・書き出し）
1. CSVデータの読み込み・整形・再出力
1. JSONファイルから構造体への変換・保存
1. 設定ファイル（.envや.toml）の読み込みと反映

🔁 データ処理系（集合・変換）
1. AとBのリストの差分（追加・削除された要素）を抽出
1. 2つのマップをマージ（競合時の優先ルール付き）
1. マップの中で特定の条件を満たすものだけ抽出
1. 日付順などでグループ化する（groupBy系処理）
1. データをキー別にまとめ直す（indexBy）
1. カウント（集計）処理（要素ごとの出現回数など）

🧠 アルゴリズム系（軽めの応用）
1. バブル・挿入・マージソートなどの実装
1. 線形探索と二分探索の汎用化
1. Fibonacciや階乗などの動的計画法メモ化
1. バックトラッキング探索（例：迷路探索）
1. グラフ構造の隣接リスト構築と探索（BFS / DFS）

📈 実務系ユースケース
1. CLI引数を受け取り、処理を分岐する
1. ログレベルで出力を切り替える（debug / info / error）
1. エラーメッセージを読みやすく整形して出す
1. 構造体やオブジェクトの中身をきれいに出力（debug出力）
1. UUIDやランダムIDの生成とバリデーション
1. 簡易的なキャッシュ処理（関数結果を保存して再利用）
1. データを圧縮して保存・解凍して読み込み（zip/gzip）
1. spawn を使ったリアルなユースケース（例えば非同期ファイルIOやAPI呼び出しの並列実行）

# 中身　RustとTypescript

## 🔁 非同期・時間・並列処理

## 1. 一定時間ごと繰返処理（interval）
```rust
use tokio::time::{interval, Duration};

#[tokio::main]
async fn main() {
    let mut ticker = interval(Duration::from_secs(2));
    for _ in 0..5 {
        ticker.tick().await;
        println!("Tick at {:?}", chrono::Utc::now());
    }
}
/* 
・Duration::from_secs(2)):secから時間を表す構造体オブジェクトDurationの作成
・interval():一定間隔で「tick」を発行するストリーム（タイマー）
・.tick().await を呼ぶと、「次の tick が来るまで待つ」動作をします。
・ticker.tick().await によって、2秒ごとに待ち、
・chrono::Utc::now() で現在の時刻を取得して出力しています。
・を5回ループ
*/
```
このコードは **Tokio** ランタイムを使って、**2秒ごとに何かを繰り返す処理**を非同期で実行するシンプルな例です。

---
処理内容

- **Tokioの非同期ランタイム**を使って
- **2秒おきに現在時刻を出力**する処理を
- **5回繰り返す**
---


🧠 まとめ

| 構文                           | 意味                                             |
|------------------------------|--------------------------------------------------|
| `Duration::from_secs(2)`     | 2秒間の長さを表すオブジェクト                   |
| `interval(Duration)`         | 指定した間隔で tick を発行する非同期タイマー     |
| `ticker.tick().await`        | 次の tick まで待機                              |
| `#[tokio::main] async fn`    | Tokio の非同期エントリーポイント                |

---


TypeScript（`setInterval`）
```ts
let count = 0;
const intervalId = setInterval(() => {
  console.log("Tick at", new Date().toISOString());
  count++;
  if (count >= 5) clearInterval(intervalId);
}, 2000);
```

---

## 非同期タスクを直列で順に実行（await順次処理）

### Rust（`await` を順に）
```rust
use tokio::task;

async fn my_task_prc(n: u32) {
    println!("Start my_task_prc {}", n);
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    println!("End my_task_prc {}", n);
}

#[tokio::main]
async fn main() {
    for i in 1..=3 {
        my_task_prc(i).await;
    }
}

```

```toml:Cargo.toml
[dependencies]
tokio = { version = "1", features = ["rt-multi-thread", "macros", "time"] }
```

```toml:tokio全部入れる場合のCargo.toml
[dependencies]
tokio = { version = "1", features = ["full"] }
chrono = "0.4"
```

| feature名         | 意味                                   |
|------------------|----------------------------------------|
| `rt`             | 単スレッドのランタイム                 |
| `rt-multi-thread`| マルチスレッドのランタイム             |
| `macros`         | `#[tokio::main]` や `#[tokio::test]` 用 |
| `time`           | `sleep`, `interval` などの時間操作     |
| `spawn`          | 明示しなくても `rt` に含まれることが多い |

補足：async fn を使って複数タスクを並列で走らせる例
```rust
async fn my_task_prc(n: u32) {
    println!("Start my_task_prc {}", n);
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    println!("End my_task_prc {}", n);
}

#[tokio::main]
async fn main() {
    let handles: Vec<_> = (1..=3)
        .map(|i| tokio::spawn(my_task_prc(i)))
        .collect();

    for handle in handles {
        handle.await.unwrap();
    }
}

//実行結果
//先に同時出力
Start my_task_prc 1
Start my_task_prc 2
Start my_task_prc 3
//同時出力
End my_task_prc 3
End my_task_prc 2
End my_task_prc 1

```
解説

| 構文                         | 意味                                                               |
|----------------------------|--------------------------------------------------------------------|
| `tokio::spawn(...)`         | 非同期処理をランタイムに渡して「**同時実行**」する                   |
| `JoinHandle<T>`             | `.await` することで**完了待ち**できるオブジェクト                    |
| `handle.await.unwrap()`     | エラーがないかチェックしつつ完了を待つ                             |

---

`spawn` の特徴と注意点

| 特徴                                | 説明                                                                 |
|-----------------------------------|----------------------------------------------------------------------|
| 並列実行                           | `await` せずに進められるため、他のタスクと同時に進行できる             |
| `JoinHandle` を使わないと「投げっぱなし」| エラーハンドリングや終了を確認したい場合は、必ず `.await` するべき       |
| `Send + 'static` 制約              | spawn 内部で使う値は基本的にスレッド間で安全に共有できる `Send` 値であることが必要 |

---

🚫 `spawn` に `async fn` の戻り値をそのまま渡すとエラーの例

```rust
async fn my_task() -> String {
    "done".to_string()
}

#[tokio::main]
async fn main() {
    let handle = tokio::spawn(my_task()); // OK
    let result = handle.await.unwrap(); // result: String
    println!("Result: {}", result);
}
```

- **戻り値の型が `'static` な値（所有権が完全に移る型）である必要**がある点に注意。

---


TypeScript
```ts
async function task(n: number) {
  console.log(`Start task ${n}`);
  await new Promise(res => setTimeout(res, 1000));
  console.log(`End task ${n}`);
}

async function run() {
  for (let i = 1; i <= 3; i++) {
    await task(i);
  }
}
run();
```

---

### 非同期タスクを並列に実行してすべて完了を待つ
```rust
//Rust（`futures::future::join_all`）
use futures::future::join_all;

async fn my_task_prc(n: u32) {
    println!("Start my_task_prc {}", n);
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    println!("End my_task_prc {}", n);
}

#[tokio::main]
async fn main() {
    let handles = (1..=3).map(my_task_prc);
    join_all(handles).await;
}
```

```ts
//TypeScript（`Promise.all`）
async function task(n: number) {
  console.log(`Start task ${n}`);
  await new Promise(res => setTimeout(res, 1000));
  console.log(`End task ${n}`);
}

async function run() {
  await Promise.all([1, 2, 3].map(task));
}
run();
```

---

### 4.バックグラウンド処理とUI更新を分離（擬似的に）

```rust
//Rust（バックグラウンド処理 → メッセージ送信）
use tokio::{sync::mpsc, time::Duration};

#[tokio::main]
async fn main() {
    let (tx, mut rx) = mpsc::channel(10);

    // Background task
    tokio::spawn(async move {
        tokio::time::sleep(Duration::from_secs(2)).await;
        tx.send("Data ready").await.unwrap();
    });

    // "UI" waiting
    while let Some(msg) = rx.recv().await {
        println!("UI received: {}", msg);
    }
}
```
```ts
//TypeScript（擬似的に setTimeout と DOM 更新）
function backgroundProcess(callback: (msg: string) => void) {
  setTimeout(() => {
    callback("Data ready");
  }, 2000);
}

backgroundProcess(msg => {
  console.log("UI received:", msg);
});
```

---

### 5.リトライ付きAPI呼び出し（指数バックオフ付き）


```rust
// Rust（指数バックオフ）
use tokio::time::{sleep, Duration};

async fn fetch_with_retry() {
    let mut retries = 0;
    while retries < 5 {
        let success = rand::random::<bool>(); // ダミー
        if success {
            println!("Success on try {}", retries + 1);
            return;
        } else {
            let wait = 2u64.pow(retries);
            println!("Retrying in {}s...", wait);
            sleep(Duration::from_secs(wait)).await;
            retries += 1;
        }
    }
    println!("Failed after 5 retries");
}

#[tokio::main]
async fn main() {
    fetch_with_retry().await;
}
```
```ts
async function fetchWithRetry() {
  for (let i = 0; i < 5; i++) {
    const success = Math.random() > 0.5; // ダミー
    if (success) {
      console.log(`Success on try ${i + 1}`);
      return;
    } else {
      const delay = Math.pow(2, i) * 1000;
      console.log(`Retrying in ${delay / 1000}s...`);
      await new Promise(res => setTimeout(res, delay));
    }
  }
  console.log("Failed after 5 retries");
}

fetchWithRetry();
```

---

### 6. 処理時間の計測（ベンチマーク用）
```rust
//Rust（`std::time::Instant`）
use std::time::Instant;

fn main() {
    let start = Instant::now();
    let sum: u64 = (1..=1_000_000).sum();
    let duration = start.elapsed();
    println!("Sum = {}, elapsed = {:?}", sum, duration);
}
```
```ts
//TypeScript（`performance.now()` or `Date.now()`）
const start = performance.now();
const sum = Array.from({ length: 1_000_000 }, (_, i) => i + 1).reduce((a, b) => a + b, 0);
const end = performance.now();
console.log(`Sum = ${sum}, elapsed = ${(end - start).toFixed(2)} ms`);
```

---

## 📦 ファイル/データ/入出力
---

### 1. ファイルの存在確認・作成・削除

```rust
use std::fs;
use std::path::Path;

fn main() {
    let path = "example.txt";

    if Path::new(path).exists() {
        println!("ファイルは存在します");
        fs::remove_file(path).expect("削除失敗");
    } else {
        fs::write(path, "初期内容").expect("作成失敗");
        println!("ファイルを作成しました");
    }
}
```


```ts
import { existsSync, writeFileSync, unlinkSync } from 'fs';

const path = 'example.txt';

if (existsSync(path)) {
  console.log('ファイルは存在します');
  unlinkSync(path);
} else {
  writeFileSync(path, '初期内容');
  console.log('ファイルを作成しました');
}
```

---

### 2. ログファイルに時刻付きで書き出す


```rust
use std::fs::OpenOptions;
use std::io::Write;
use chrono::Local;

fn main() {
    let now = Local::now();
    let log = format!("[{}] アクション発生\n", now.format("%Y-%m-%d %H:%M:%S"));
    
    let mut file = OpenOptions::new()
        .append(true)
        .create(true)
        .open("log.txt")
        .expect("ログファイルオープン失敗");
    
    file.write_all(log.as_bytes()).expect("書き込み失敗");
}
```

```ts
import { appendFileSync } from 'fs';

const now = new Date().toISOString();
const log = `[${now}] アクション発生\n`;

appendFileSync('log.txt', log);
```

---

### 3. 巨大ファイルのストリーム処理（読み込み・書き出し）

```rust
//Rust（1行ずつ読む）
use std::fs::File;
use std::io::{BufReader, BufWriter, BufRead};

fn main() -> std::io::Result<()> {
    let input = File::open("big_input.txt")?;
    let output = File::create("big_output.txt")?;
    let reader = BufReader::new(input);
    let mut writer = BufWriter::new(output);

    for line in reader.lines() {
        let line = line?;
        writeln!(writer, "{}", line.to_uppercase())?;
    }

    Ok(())
}
```

```ts
//TypeScript（Node.jsストリーム）
import { createReadStream, createWriteStream } from 'fs';
import * as readline from 'readline';

const input = createReadStream('big_input.txt');
const output = createWriteStream('big_output.txt');
const rl = readline.createInterface({ input });

rl.on('line', line => {
  output.write(line.toUpperCase() + '\n');
});
rl.on('close', () => {
  output.end();
});
```

---

### 4. CSVデータの読み込み・整形・再出力


```toml
// Rust（`csv` crate使用）
# Cargo.toml
[dependencies]
csv = "1.2"
serde = { version = "1.0", features = ["derive"] }
```

```rust
use serde::{Deserialize, Serialize};
use std::error::Error;

#[derive(Debug, Deserialize, Serialize)]
struct Record {
    name: String,
    age: u32,
}

fn main() -> Result<(), Box<dyn Error>> {
    let mut rdr = csv::Reader::from_path("input.csv")?;
    let mut wtr = csv::Writer::from_path("output.csv")?;

    for result in rdr.deserialize() {
        let mut record: Record = result?;
        record.age += 1;
        wtr.serialize(record)?;
    }
    wtr.flush()?;
    Ok(())
}
```

```ts
//TypeScript（`csv-parser` & `fs`）
import fs from 'fs';
import csv from 'csv-parser';

const results: { name: string; age: number }[] = [];

fs.createReadStream('input.csv')
  .pipe(csv())
  .on('data', (data) => results.push({ ...data, age: Number(data.age) + 1 }))
  .on('end', () => {
    const output = results.map(r => `${r.name},${r.age}`).join('\n');
    fs.writeFileSync('output.csv', output);
  });
```

---

### 5. JSONファイルから構造体への変換・保存

```rust
use serde::{Deserialize, Serialize};
use std::fs;

#[derive(Debug, Serialize, Deserialize)]
struct Config {
    username: String,
    age: u32,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let json = fs::read_to_string("config.json")?;
    let mut config: Config = serde_json::from_str(&json)?;

    config.age += 1;

    let updated = serde_json::to_string_pretty(&config)?;
    fs::write("config_updated.json", updated)?;
    Ok(())
}
```
```ts
import fs from 'fs';

type Config = { username: string; age: number };

const json = fs.readFileSync('config.json', 'utf-8');
const config: Config = JSON.parse(json);

config.age += 1;

fs.writeFileSync('config_updated.json', JSON.stringify(config, null, 2));
```

---

### 6. 設定ファイル（.envや.toml）の読み込みと反映

```toml
# Cargo.toml
[dependencies]
dotenv = "0.15"
config = "0.13"
serde = { version = "1.0", features = ["derive"] }
```

```rust
//Rust（`.env` or `.toml`）
use dotenv::dotenv;
use std::env;
use config::{Config, File};
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Settings {
    api_key: String,
}

fn main() {
    dotenv().ok();
    println!("ENV from .env: {}", env::var("API_KEY").unwrap_or_default());

    let settings: Settings = Config::builder()
        .add_source(File::with_name("Settings"))
        .build()
        .unwrap()
        .try_deserialize()
        .unwrap();

    println!("TOML設定: {:?}", settings);
}
```

`.env`
```
API_KEY=secret123
```

`Settings.toml`
```toml
api_key = "abc123"
```

---

```ts
//dotenv
import dotenv from 'dotenv';
dotenv.config();

console.log("API_KEY:", process.env.API_KEY);
```

`.env`
```
API_KEY=secret123
```

---
## 🔁 データ処理系（集合・変換）

### 1. AとBのリストの差分（追加・削除された要素）

```rust
use std::collections::HashSet;

fn main() {
    let a: HashSet<_> = vec!["apple", "banana", "cherry"].into_iter().collect();
    let b: HashSet<_> = vec!["banana", "dragonfruit"].into_iter().collect();

    let added: Vec<_> = b.difference(&a).cloned().collect();
    let removed: Vec<_> = a.difference(&b).cloned().collect();

    println!("追加された: {:?}", added);
    println!("削除された: {:?}", removed);
}
```

```ts
const a = ["apple", "banana", "cherry"];
const b = ["banana", "dragonfruit"];

const added = b.filter(x => !a.includes(x));
const removed = a.filter(x => !b.includes(x));

console.log("追加された:", added);
console.log("削除された:", removed);
```

---

### 2. 2つのマップをマージ（競合時の優先ルール付き）

```rust
use std::collections::HashMap;

fn main() {
    let mut map1 = HashMap::from([("a", 1), ("b", 2)]);
    let map2 = HashMap::from([("b", 99), ("c", 3)]);

    for (k, v) in map2 {
        map1.entry(k).or_insert(v); // map1の値が優先される
    }

    println!("{:?}", map1); // => {"a":1, "b":2, "c":3}
}
```

```ts
const map1 = { a: 1, b: 2 };
const map2 = { b: 99, c: 3 };

const merged = { ...map2, ...map1 }; // map1の値が優先

console.log(merged); // { b: 2, c: 3, a: 1 }
```

---

### 3. マップの中で特定の条件を満たすものだけ抽出

```rust
use std::collections::HashMap;

fn main() {
    let map = HashMap::from([("apple", 3), ("banana", 1), ("cherry", 5)]);
    let filtered: HashMap<_, _> = map
        .into_iter()
        .filter(|(_, v)| *v >= 3)
        .collect();

    println!("{:?}", filtered); // {"apple": 3, "cherry": 5}
}
```

```ts
const map = { apple: 3, banana: 1, cherry: 5 };
const filtered = Object.fromEntries(
  Object.entries(map).filter(([_, v]) => v >= 3)
);

console.log(filtered); // { apple: 3, cherry: 5 }
```

---

### 4. 日付順などでグループ化する（groupBy）

```rust
//Rust（カスタム groupBy）
use std::collections::HashMap;

#[derive(Debug)]
struct Task {
    date: &'static str,
    title: &'static str,
}

fn main() {
    let tasks = vec![
        Task { date: "2024-01-01", title: "A" },
        Task { date: "2024-01-02", title: "B" },
        Task { date: "2024-01-01", title: "C" },
    ];

    let mut grouped: HashMap<&str, Vec<&Task>> = HashMap::new();
    for task in &tasks {
        grouped.entry(task.date).or_default().push(task);
    }

    println!("{:#?}", grouped);
}
```
```ts
type Task = { date: string; title: string };

const tasks: Task[] = [
  { date: "2024-01-01", title: "A" },
  { date: "2024-01-02", title: "B" },
  { date: "2024-01-01", title: "C" },
];

const grouped = tasks.reduce((acc, task) => {
  (acc[task.date] ||= []).push(task);
  return acc;
}, {} as Record<string, Task[]>);

console.log(grouped);
```

---

### 5. データをキー別にまとめ直す（indexBy）
```rust
use std::collections::HashMap;

#[derive(Debug)]
struct User {
    id: u32,
    name: &'static str,
}

fn main() {
    let users = vec![
        User { id: 1, name: "Alice" },
        User { id: 2, name: "Bob" },
    ];

    let indexed: HashMap<u32, &User> = users.iter().map(|u| (u.id, u)).collect();
    println!("{:#?}", indexed);
}
```
```ts
type User = { id: number; name: string };

const users: User[] = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
];

const indexed = Object.fromEntries(users.map(user => [user.id, user]));

console.log(indexed);
```

---

### 6. カウント（要素ごとの出現回数など）

```rust
use std::collections::HashMap;

fn main() {
    let fruits = vec!["apple", "banana", "apple", "orange", "banana"];
    let mut count = HashMap::new();

    for fruit in fruits {
        *count.entry(fruit).or_insert(0) += 1;
    }

    println!("{:?}", count); // {"apple": 2, "banana": 2, "orange": 1}
}
```
```ts
const fruits = ["apple", "banana", "apple", "orange", "banana"];
const count: Record<string, number> = {};

for (const fruit of fruits) {
  count[fruit] = (count[fruit] || 0) + 1;
}

console.log(count); // { apple: 2, banana: 2, orange: 1 }
```
---
### 以下rustのみ

## ✅ アルゴリズム系

### 1. バブル・挿入・マージソート
```rust
// バブルソート
fn bubble_sort(arr: &mut [i32]) {
    let len = arr.len();
    for i in 0..len {
        for j in 0..len - i - 1 {
            if arr[j] > arr[j + 1] {
                arr.swap(j, j + 1);
            }
        }
    }
}

// 挿入ソート
fn insertion_sort(arr: &mut [i32]) {
    for i in 1..arr.len() {
        let key = arr[i];
        let mut j = i;
        while j > 0 && arr[j - 1] > key {
            arr[j] = arr[j - 1];
            j -= 1;
        }
        arr[j] = key;
    }
}

// マージソート（再帰）
fn merge_sort(arr: &mut [i32]) {
    let mid = arr.len() / 2;
    if mid == 0 { return; }

    let mut left = arr[..mid].to_vec();
    let mut right = arr[mid..].to_vec();
    merge_sort(&mut left);
    merge_sort(&mut right);

    let mut i = 0;
    while !left.is_empty() && !right.is_empty() {
        if left[0] < right[0] {
            arr[i] = left.remove(0);
        } else {
            arr[i] = right.remove(0);
        }
        i += 1;
    }
    for x in left.into_iter().chain(right) {
        arr[i] = x;
        i += 1;
    }
}
```

---

### 2. 線形探索と二分探索（汎用）
```rust
fn linear_search<T: PartialEq>(arr: &[T], target: T) -> Option<usize> {
    arr.iter().position(|x| *x == target)
}

fn binary_search<T: Ord>(arr: &[T], target: T) -> Option<usize> {
    let mut low = 0;
    let mut high = arr.len();
    while low < high {
        let mid = (low + high) / 2;
        if arr[mid] == target {
            return Some(mid);
        } else if arr[mid] < target {
            low = mid + 1;
        } else {
            high = mid;
        }
    }
    None
}
```

---

### 3. Fibonacci / 階乗（メモ化付き動的計画法）
```rust
use std::collections::HashMap;

fn fib(n: u32, memo: &mut HashMap<u32, u64>) -> u64 {
    if n <= 1 { return n as u64; }
    if let Some(&v) = memo.get(&n) {
        return v;
    }
    let v = fib(n - 1, memo) + fib(n - 2, memo);
    memo.insert(n, v);
    v
}
```

---

### 4. バックトラッキング（迷路探索）
```rust
fn dfs(maze: &[Vec<char>], x: usize, y: usize, visited: &mut Vec<Vec<bool>>) -> bool {
    if maze[y][x] == 'G' { return true; }
    visited[y][x] = true;

    let dirs = [(0,1), (1,0), (0,-1), (-1,0)];
    for (dx, dy) in dirs.iter() {
        let nx = x as isize + dx;
        let ny = y as isize + dy;
        if nx >= 0 && ny >= 0 && ny < maze.len() as isize && nx < maze[0].len() as isize {
            let (nx, ny) = (nx as usize, ny as usize);
            if maze[ny][nx] != '#' && !visited[ny][nx] {
                if dfs(maze, nx, ny, visited) {
                    return true;
                }
            }
        }
    }
    false
}
```

---

### 5. グラフ探索（BFS / DFS）
```rust
use std::collections::{HashMap, VecDeque};

fn bfs(graph: &HashMap<&str, Vec<&str>>, start: &str) {
    let mut visited = HashMap::new();
    let mut queue = VecDeque::new();
    queue.push_back(start);

    while let Some(node) = queue.pop_front() {
        if visited.get(node).is_some() { continue; }
        visited.insert(node, true);
        println!("Visited {}", node);
        if let Some(neighbors) = graph.get(node) {
            for &n in neighbors {
                queue.push_back(n);
            }
        }
    }
}
```

---

## ✅ 実用系ユーティリティ

### 6. CLI引数を受け取り、処理を分岐
```rust
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    match args.get(1).map(|s| s.as_str()) {
        Some("hello") => println!("Hello mode"),
        Some("debug") => println!("Debug mode"),
        _ => println!("Usage: program [hello|debug]"),
    }
}
```

---

### 7. ログレベルで出力を切り替える
```rust
use log::{info, debug, error};

fn main() {
    env_logger::init();
    info!("This is info");
    debug!("This is debug");
    error!("This is error");
}
```

---

### 8. エラーの整形出力
```rust
fn might_fail(x: i32) -> Result<i32, String> {
    if x == 0 { Err("Zero not allowed".into()) } else { Ok(100 / x) }
}

fn main() {
    match might_fail(0) {
        Ok(v) => println!("Success: {}", v),
        Err(e) => eprintln!("Error occurred: {}", e),
    }
}
```

---

### 9. 構造体のデバッグ出力
```rust
#[derive(Debug)]
struct User {
    name: String,
    age: u32,
}

fn main() {
    let user = User { name: "Alice".into(), age: 30 };
    println!("{:#?}", user); // pretty print
}
```

---

### 10. UUID生成・バリデーション
```toml
# Cargo.toml
uuid = { version = "1", features = ["v4"] }
```

```rust
use uuid::Uuid;

fn main() {
    let id = Uuid::new_v4();
    println!("Generated UUID: {}", id);
}
```

---

### 11. 関数結果の簡易キャッシュ（クロージャ＋HashMap）
```rust
use std::collections::HashMap;

fn memoized_square() -> impl FnMut(i32) -> i32 {
    let mut cache = HashMap::new();
    move |x| {
        *cache.entry(x).or_insert_with(|| {
            println!("Computing for {}", x);
            x * x
        })
    }
}

fn main() {
    let mut square = memoized_square();
    println!("{}", square(4));
    println!("{}", square(4)); // キャッシュ使用
}
```

---

### 12. zip/gzip 圧縮と解凍

#### zip圧縮
```toml
zip = "0.6"
```

```rust
use std::fs::File;
use zip::write::FileOptions;
use std::io::{Write, Seek};

fn main() {
    let path = "example.zip";
    let file = File::create(path).unwrap();
    let mut zip = zip::ZipWriter::new(file);

    let options = FileOptions::default().compression_method(zip::CompressionMethod::Stored);
    zip.start_file("hello.txt", options).unwrap();
    zip.write_all(b"Hello, world!").unwrap();
    zip.finish().unwrap();
}
```
### 13.spawn を使ったリアルなユースケース（例えば非同期ファイルIOやAPI呼び出しの並列実行）

- ✅ API呼び出しの並列実行
- ✅ 非同期ファイルI/O（読み込み処理）
- ✅ CPU負荷の高い処理との併用（`spawn_blocking`）

---

#### ✅ ユースケース①：API呼び出しを並列で行う（`reqwest`）

複数のURLに同時アクセスして、レスポンスを収集する例：

```toml:Cargo.toml
[dependencies]
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.11", features = ["json"] }
```

```rust
use tokio::task;
use reqwest::Client;

#[tokio::main]
async fn main() {
    let urls = vec![
        "https://jsonplaceholder.typicode.com/posts/1",
        "https://jsonplaceholder.typicode.com/posts/2",
        "https://jsonplaceholder.typicode.com/posts/3",
    ];

    let client = Client::new();

    let mut handles = vec![];

    for url in urls {
        let client = client.clone();
        let url = url.to_string();
        let handle = task::spawn(async move {
            let res = client.get(&url).send().await.unwrap();
            let body = res.text().await.unwrap();
            println!("Got response from {}: {} chars", url, body.len());
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.await.unwrap();
    }
}
```

#### 解説

- `client.clone()` を使って `reqwest::Client` をスレッド間共有
- 各 `spawn` で独立して API 呼び出し
- `.await.unwrap()` で全てのレスポンス待機

---

#### ✅ ユースケース②：非同期ファイル読み込み（`tokio::fs`）

```toml
[dependencies]
tokio = { version = "1", features = ["full"] }
```

```rust
use tokio::fs;
use tokio::task;

#[tokio::main]
async fn main() {
    let files = vec!["file1.txt", "file2.txt", "file3.txt"];
    let mut handles = vec![];

    for file in files {
        let path = file.to_string();
        let handle = task::spawn(async move {
            match fs::read_to_string(&path).await {
                Ok(content) => println!("{}: {} bytes", path, content.len()),
                Err(e) => println!("{}: failed to read: {}", path, e),
            }
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.await.unwrap();
    }
}
```

#### 解説

- 各ファイル読み込みを `spawn` で並列化
- `tokio::fs::read_to_string()` で非同期読み取り
- 読み込みが重くても並列で進むので高速化できる

---

#### ✅ ユースケース③：重い処理を `spawn_blocking` で逃がす

```rust
use tokio::task;

#[tokio::main]
async fn main() {
    let handle = task::spawn_blocking(|| {
        // ブロッキングな重い処理（例：ファイル変換や圧縮）
        std::thread::sleep(std::time::Duration::from_secs(2));
        println!("Heavy processing done!");
    });

    println!("Non-blocking logic continues...");
    handle.await.unwrap();
}
```

#### 解説

- `spawn_blocking` は CPUバウンド or ブロッキングIO 向け
- メインスレッドを止めずに処理できる

---

#### 🧠 総まとめ：spawn のユースケース早見表

| ユースケース例                 | メリット                                        |
|-----------------------------|-----------------------------------------------|
| 複数API呼び出し             | まとめて非同期実行 → 応答時間の短縮             |
| 複数ファイル非同期読み込み   | 並列で読み込み → 合計待ち時間を減らせる         |
| 圧縮・変換などの重処理       | `spawn_blocking` → メイン処理の遅延を防げる     |

---

他にも、例えば：

- 並列スクレイピング
- 並列DBクエリ
- 並列画像変換やサムネ生成

など、**非同期性やCPU負荷の分離**が必要な場面では `spawn` が威力を発揮します。

---