pipe input
This commit is contained in:
parent
7ad1f49dc8
commit
aac9ba5aff
3 changed files with 69 additions and 38 deletions
43
Cargo.lock
generated
43
Cargo.lock
generated
|
|
@ -2,6 +2,17 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
@ -19,6 +30,15 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.10"
|
version = "1.0.10"
|
||||||
|
|
@ -137,6 +157,7 @@ dependencies = [
|
||||||
name = "traktor"
|
name = "traktor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"atty",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -153,3 +174,25 @@ name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
atty = "0.2.14"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
serde = { version = "1.0.196", features = ["derive"] }
|
serde = { version = "1.0.196", features = ["derive"] }
|
||||||
serde_json = "1.0.113"
|
serde_json = "1.0.113"
|
||||||
|
|
|
||||||
63
src/main.rs
63
src/main.rs
|
|
@ -1,5 +1,5 @@
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, BufRead, BufReader};
|
use std::io::{self, BufRead, BufReader, stdin, Read};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::process;
|
use std::process;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
@ -102,51 +102,38 @@ fn create_cluster_info(cluster: &[Point]) -> ClusterGapInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the main function and subsequent calculations to work with the new structure and calculate Z-scores accordingly
|
|
||||||
|
|
||||||
|
|
||||||
fn calculate_cluster_density(cluster: &[u32]) -> f32 {
|
|
||||||
if cluster.len() < 2 { return 0.0; } // Adjust based on how you define density for single-element clusters
|
|
||||||
|
|
||||||
let &max_value = cluster.iter().max().unwrap();
|
|
||||||
let &min_value = cluster.iter().min().unwrap();
|
|
||||||
let span = (max_value - min_value) as f32;
|
|
||||||
if span == 0.0 {
|
|
||||||
return cluster.len() as f32; // Handle clusters where all points have the same value
|
|
||||||
}
|
|
||||||
cluster.len() as f32 / span
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assume distance function is defined as before
|
|
||||||
|
|
||||||
|
|
||||||
fn distance(p1: &Point, p2: &Point) -> u32 {
|
fn distance(p1: &Point, p2: &Point) -> u32 {
|
||||||
if p1.value > p2.value { p1.value - p2.value } else { p2.value - p1.value }
|
if p1.value > p2.value { p1.value - p2.value } else { p2.value - p1.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn calculate_mean_and_std_dev(densities: &[f32]) -> (f32, f32) {
|
|
||||||
let mean = densities.iter().sum::<f32>() / densities.len() as f32;
|
|
||||||
let variance = densities.iter().map(|&v| (v - mean).powi(2)).sum::<f32>() / densities.len() as f32;
|
|
||||||
(mean, variance.sqrt())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calculate_z_scores(densities: &[f32], mean: f32, std_dev: f32) -> Vec<f32> {
|
|
||||||
densities.iter().map(|&density| (density - mean) / std_dev).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
if args.len() < 4 {
|
let mut dataset: Vec<Point> = Vec::new();
|
||||||
eprintln!("Usage: {} <filename> <factor> <min_cluster_size>", args[0]);
|
|
||||||
process::exit(1);
|
// Check if data is being piped into the program
|
||||||
|
if atty::is(atty::Stream::Stdin) {
|
||||||
|
// Not receiving piped input, expect filename as argument
|
||||||
|
if args.len() < 4 {
|
||||||
|
eprintln!("Usage: {} <filename> <factor> <min_cluster_size>", args[0]);
|
||||||
|
eprintln!("Or pipe in a list of integers and provide <factor> <min_cluster_size>");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = &args[1];
|
||||||
|
dataset = load_dataset(filename)?;
|
||||||
|
} else {
|
||||||
|
// Receiving piped input, read from stdin
|
||||||
|
let stdin = io::stdin();
|
||||||
|
let reader = stdin.lock();
|
||||||
|
for line in reader.lines() {
|
||||||
|
let value: u32 = line?.trim().parse().unwrap();
|
||||||
|
dataset.push(Point::new(value));
|
||||||
|
}
|
||||||
|
dataset.sort_by_key(|p| p.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let filename = &args[1];
|
let factor: f32 = args[args.len() - 2].parse().expect("Factor must be a float");
|
||||||
let factor: f32 = args[2].parse().expect("Factor must be a float");
|
let min_cluster_size: usize = args[args.len() - 1].parse().expect("Min cluster size must be an integer");
|
||||||
let min_cluster_size: usize = args[3].parse().expect("Min cluster size must be an integer");
|
|
||||||
|
|
||||||
let dataset = load_dataset(filename)?;
|
|
||||||
|
|
||||||
let mut cluster_gap_infos = calculate_densities_and_gaps(&dataset, factor, min_cluster_size);
|
let mut cluster_gap_infos = calculate_densities_and_gaps(&dataset, factor, min_cluster_size);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue