feat: accept search limit as CLI argument
Allow users to override the default HCN search limit by passing one optional positive integer argument. Bad input now exits with status 2 and prints a clear message instead of silently using a fixed range. Keep the existing one-billion default when no argument is provided, so current usage remains unchanged. Test Plan: - cargo clippy - cargo clippy --benches - cargo clippy --tests - cargo test Refs: N/A
This commit is contained in:
+56
-4
@@ -1,6 +1,6 @@
|
||||
use std::time::Instant;
|
||||
use std::{env, process, time::Instant};
|
||||
|
||||
const SEARCH_LIMIT: u64 = 1_000_000_000;
|
||||
const DEFAULT_SEARCH_LIMIT: u64 = 1_000_000_000;
|
||||
const FIRST_PRIMES: &[u64] = &[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
@@ -108,9 +108,36 @@ fn hcn_records(limit: u64) -> Vec<Candidate> {
|
||||
records
|
||||
}
|
||||
|
||||
fn parse_search_limit(args: &[String]) -> Result<u64, String> {
|
||||
let program = args.first().map_or("hcn", String::as_str);
|
||||
|
||||
match args.len() {
|
||||
0 | 1 => Ok(DEFAULT_SEARCH_LIMIT),
|
||||
2 => {
|
||||
let raw_limit = &args[1];
|
||||
let limit = raw_limit
|
||||
.parse::<u64>()
|
||||
.map_err(|err| format!("invalid search limit {raw_limit:?}: {err}"))?;
|
||||
|
||||
if limit == 0 {
|
||||
return Err("search limit must be greater than zero".to_owned());
|
||||
}
|
||||
|
||||
Ok(limit)
|
||||
}
|
||||
_ => Err(format!("usage: {program} [SEARCH_LIMIT]")),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = env::args().collect::<Vec<_>>();
|
||||
let search_limit = parse_search_limit(&args).unwrap_or_else(|err| {
|
||||
eprintln!("{err}");
|
||||
process::exit(2);
|
||||
});
|
||||
|
||||
let start = Instant::now();
|
||||
let records = hcn_records(SEARCH_LIMIT);
|
||||
let records = hcn_records(search_limit);
|
||||
|
||||
for Candidate { nr, divisors } in records {
|
||||
println!("{nr}: {divisors} ({:?} since start)", start.elapsed());
|
||||
@@ -119,7 +146,7 @@ fn main() {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Candidate, hcn_records, max_exponent};
|
||||
use super::{Candidate, DEFAULT_SEARCH_LIMIT, hcn_records, max_exponent, parse_search_limit};
|
||||
|
||||
fn count_divisors(mut nr: u64) -> u64 {
|
||||
let mut divisor_count = 1;
|
||||
@@ -233,4 +260,29 @@ mod tests {
|
||||
fn matches_brute_force_records_up_to_ten_thousand() {
|
||||
assert_eq!(hcn_records(10_000), brute_force_hcn_records(10_000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_default_search_limit_without_arg() {
|
||||
assert_eq!(
|
||||
parse_search_limit(&["hcn".to_owned()]),
|
||||
Ok(DEFAULT_SEARCH_LIMIT)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_search_limit_arg() {
|
||||
assert_eq!(
|
||||
parse_search_limit(&["hcn".to_owned(), "42000".to_owned()]),
|
||||
Ok(42_000)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_invalid_search_limit_arg() {
|
||||
assert!(parse_search_limit(&["hcn".to_owned(), "nope".to_owned()]).is_err());
|
||||
assert!(parse_search_limit(&["hcn".to_owned(), "0".to_owned()]).is_err());
|
||||
assert!(
|
||||
parse_search_limit(&["hcn".to_owned(), "100".to_owned(), "200".to_owned()]).is_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user