Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added 322-dp-memo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,239 changes: 1,239 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
[package]
name= "leetcode-practice"
version = "0.1.0"
edition = "2021"
edition = "2021"

[dev-dependencies]
criterion = { version = "0.8", features = ["html_reports"] }

[[bench]]
name = "coin_change"
harness = false

[dependencies]
plotters = "0.3.7"
71 changes: 71 additions & 0 deletions benches/coin_change.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
このコードはGPT-5.1を利用して出力しました。
*/

use leetcode_practice::chart::draw_multi_line_chart;
use leetcode_practice::solutions::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let coins = vec![1, 2, 5, 186, 419, 83, 408];
let inputs = vec![10, 20, 40, 80, 160, 320, 6249];

// A vs B vs C の複数シリーズ
let mut series: Vec<(&str, Vec<(f64, f64)>)> = vec![];

let mut recursive_dfs = vec![];
for amount in &inputs {
let t = measure(|| step1a::Solution::coin_change(coins.clone(), *amount));
recursive_dfs.push((*amount as f64, t));
}
series.push(("recursive_dfs(step1a.rs)", recursive_dfs));

let mut bfs = vec![];
for amount in &inputs {
let t = measure(|| step1b_bfs::Solution::coin_change(coins.clone(), *amount));
bfs.push((*amount as f64, t));
}
series.push(("bfs(step1b_bfs.rs)", bfs));

let mut dp = vec![];
for amount in &inputs {
let t = measure(|| step1c_dp::Solution::coin_change(coins.clone(), *amount));
dp.push((*amount as f64, t));
}
series.push(("dp(step1c_dp.rs)", dp));

let mut bfs_v2 = vec![];
for amount in &inputs {
let t = measure(|| step2_bfs::Solution::coin_change(coins.clone(), *amount));
bfs_v2.push((*amount as f64, t));
}
series.push(("bfs_v2(step2_bfs.rs)", bfs_v2));

let mut dp_v2 = vec![];
for amount in &inputs {
let t = measure(|| step2a_dp::Solution::coin_change(coins.clone(), *amount));
dp_v2.push((*amount as f64, t));
}
series.push(("dp_v2(step2a_dp)", dp_v2));

// グラフ出力
draw_multi_line_chart(
"multi_line.svg",
&series,
"runtime comparison",
"amount",
"time per call [ns]",
)?;

println!("multi_line.png を出力しました!");
Ok(())
}

/// 単純な計測関数:closure を N 回実行し平均 ns を返す
fn measure<F: Fn() -> i32>(f: F) -> f64 {
let repeat = 200;
let start = std::time::Instant::now();
for _ in 0..repeat {
f();
}
start.elapsed().as_nanos() as f64 / repeat as f64
}
245 changes: 245 additions & 0 deletions multi_line.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 0 additions & 33 deletions src/bin/step1.rs

This file was deleted.

37 changes: 0 additions & 37 deletions src/bin/step2.rs

This file was deleted.

31 changes: 0 additions & 31 deletions src/bin/step3.rs

This file was deleted.

94 changes: 94 additions & 0 deletions src/chart.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
このコードはGPT-5.1を利用して出力しました。
*/
use plotters::prelude::*;

/// マルチライン折れ線グラフを SVG に出力する
///
/// `series` は以下形式:
/// [
/// ("step1", vec![(x, y), (x, y), ...]),
/// ("step1c_dp", vec![(x, y), (x, y), ...]),
/// ("step3", vec![(x, y), ...]),
/// ]
pub fn draw_multi_line_chart(
path: &str, // "multi_line.svg"
series: &[(&str, Vec<(f64, f64)>)],
title: &str,
x_label: &str,
y_label: &str,
) -> Result<(), Box<dyn std::error::Error>> {
if series.is_empty() {
return Ok(());
}

// ----------------- 軸の最小・最大を求める -----------------

let mut min_x = f64::INFINITY;
let mut max_x = f64::NEG_INFINITY;
let mut min_y = f64::INFINITY;
let mut max_y = f64::NEG_INFINITY;

for (_, pts) in series {
for (x, y) in pts {
min_x = min_x.min(*x);
max_x = max_x.max(*x);
min_y = min_y.min(*y);
max_y = max_y.max(*y);
}
}

// Plotters の都合で min==max だと描けないため少し広げる
if (min_x - max_x).abs() < f64::EPSILON {
min_x -= 1.0;
max_x += 1.0;
}
if (min_y - max_y).abs() < f64::EPSILON {
min_y -= 1.0;
max_y += 1.0;
}

// ----------------- SVG の描画領域作成 -----------------

let root = SVGBackend::new(path, (1000, 600)).into_drawing_area();
root.fill(&WHITE)?;

let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 24))
.margin(20)
.x_label_area_size(50)
.y_label_area_size(60)
.build_cartesian_2d(min_x..max_x, min_y..max_y)?;

chart
.configure_mesh()
.x_desc(x_label)
.y_desc(y_label)
.draw()?;

// ----------------- 色リスト(必要に応じて追加可能) -----------------

let colors = vec![&RED, &BLUE, &GREEN, &MAGENTA, &CYAN, &BLACK];

// ----------------- 複数シリーズの描画 -----------------

for (idx, (name, pts)) in series.iter().enumerate() {
let color = colors[idx % colors.len()];

chart
.draw_series(LineSeries::new(pts.clone(), color.stroke_width(3)))?
.label(*name)
.legend(move |(x, y)| PathElement::new([(x, y), (x + 20, y)], color.stroke_width(3)));
}

// ----------------- 凡例(レジェンド)表示 -----------------

chart
.configure_series_labels()
.border_style(&BLACK)
.background_style(&WHITE.mix(0.8))
.draw()?;

root.present()?;
Ok(())
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
// Rust-Analyzerを動作させるために空ファイルを置いています。
pub mod chart;
pub mod solutions;
5 changes: 5 additions & 0 deletions src/solutions/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod step1a;
pub mod step1b_bfs;
pub mod step1c_dp;
pub mod step2_bfs;
pub mod step2a_dp;
Loading