From: Jeff Hemminger Date: Fri, 12 Sep 2025 15:49:41 +0000 (+0900) Subject: working on interview scheduling X-Git-Url: http://gitweb.hemminger.haus/?a=commitdiff_plain;h=e2a1aef07e4c4032e6e6c65333b4400c9595295d;p=algorithms.git working on interview scheduling --- diff --git a/src/algorithms/interview_scheduling/earliest_completion.rs b/src/algorithms/interview_scheduling/earliest_completion.rs new file mode 100644 index 0000000..3ecda6a --- /dev/null +++ b/src/algorithms/interview_scheduling/earliest_completion.rs @@ -0,0 +1,60 @@ +// Time representation - could be generic over different time types +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Time(pub T) +where + T: Ord + Copy; + + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Interview +where + T: Ord + Copy, // ← Add this constraint +{ + pub start: Time, + pub end: Time, + pub id: usize, +} + +impl Interview +where + T: Ord + Copy, // ← Also add here for impl blocks +{ + pub fn new(id: usize, start: T, end: T) -> Self { + Self { + id, + start: Time(start), + end: Time(end), + } + } + + pub fn duration(&self) -> T { + // Implementation depends on what operations T supports + // This is a placeholder + self.end.0 + } +} + + +#[cfg(test)] +mod tests { + + use crate::interview_scheduling::test_data::*; + + #[test] + fn test_with_generated_data() { + let config = InterviewGenConfig { + count: 5, + min_start: 0, + max_start: 50, + min_duration: 5, + max_duration: 15, + seed: Some(42), + }; + + let interviews = generate_random_interviews(&config); + assert_eq!(interviews.len(), 5); + + // Test your algorithm with this data + // let result = your_scheduling_algorithm(&interviews); + } +} diff --git a/src/algorithms/interview_scheduling/mod.rs b/src/algorithms/interview_scheduling/mod.rs new file mode 100644 index 0000000..0016163 --- /dev/null +++ b/src/algorithms/interview_scheduling/mod.rs @@ -0,0 +1,6 @@ + +pub mod earliest_completion; +pub mod test_data; + +pub use earliest_completion::*; +pub use test_data::*; diff --git a/src/algorithms/interview_scheduling/test_data.rs b/src/algorithms/interview_scheduling/test_data.rs new file mode 100644 index 0000000..09fe2f0 --- /dev/null +++ b/src/algorithms/interview_scheduling/test_data.rs @@ -0,0 +1,123 @@ +//! Test data generation for Interview scheduling algorithms + +use super::Interview; + +/// Configuration for generating test interview data +#[derive(Debug, Clone)] +pub struct InterviewGenConfig { + /// Number of interviews to generate + pub count: usize, + /// Minimum start time + pub min_start: u64, + /// Maximum start time + pub max_start: u64, + /// Minimum duration + pub min_duration: u64, + /// Maximum duration + pub max_duration: u64, + /// Random seed for reproducible tests + pub seed: Option, +} + +impl Default for InterviewGenConfig { + fn default() -> Self { + Self { + count: 10, + min_start: 0, + max_start: 100, + min_duration: 5, + max_duration: 20, + seed: None, + } + } +} + +/// Generate a set of random interviews for testing +pub fn generate_random_interviews(config: &InterviewGenConfig) -> Vec> { + let mut rng = SimpleRng::new(config.seed.unwrap_or(42)); + + (0..config.count) + .map(|id| { + let start = rng.gen_range(config.min_start, config.max_start); + let duration = rng.gen_range(config.min_duration, config.max_duration); + let end = start + duration; + + Interview::new(id, start, end) + }) + .collect() +} + +/// Generate a set of interviews with known optimal solution for testing +pub fn generate_known_optimal_interviews() -> (Vec>, usize) { + let interviews = vec![ + Interview::new(0, 0, 5), // Non-overlapping - should be selected + Interview::new(1, 6, 10), // Non-overlapping - should be selected + Interview::new(2, 11, 15), // Non-overlapping - should be selected + Interview::new(3, 16, 20), // Non-overlapping - should be selected + Interview::new(4, 2, 8), // Overlaps with 0 and 1 + Interview::new(5, 12, 18), // Overlaps with 2 and 3 + Interview::new(6, 1, 19), // Overlaps with all + ]; + + (interviews, 4) // Optimal solution has 4 interviews +} + +/// Generate worst-case scenario: all interviews overlap +pub fn generate_all_overlapping_interviews(count: usize) -> Vec> { + (0..count) + .map(|id| Interview::new(id, 10, 20)) + .collect() +} + +/// Generate best-case scenario: no interviews overlap +pub fn generate_no_overlapping_interviews(count: usize) -> Vec> { + (0..count) + .map(|id| { + let start = id as u64 * 10; + let end = start + 5; + Interview::new(id, start, end) + }) + .collect() +} + +// Simple deterministic random number generator for testing +struct SimpleRng { + state: u64, +} + +impl SimpleRng { + fn new(seed: u64) -> Self { + Self { state: seed } + } + + fn next(&mut self) -> u64 { + self.state = self.state.wrapping_mul(1103515245).wrapping_add(12345); + self.state + } + + fn gen_range(&mut self, min: u64, max: u64) -> u64 { + if min >= max { + return min; + } + min + (self.next() % (max - min)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_random_generation() { + let config = InterviewGenConfig::default(); + let interviews = generate_random_interviews(&config); + assert_eq!(interviews.len(), 10); + } + + #[test] + fn test_known_optimal() { + let (interviews, optimal_count) = generate_known_optimal_interviews(); + assert_eq!(optimal_count, 4); + assert_eq!(interviews.len(), 7); + } +} diff --git a/src/algorithms/mod.rs b/src/algorithms/mod.rs index 8b1fb91..bffaca0 100644 --- a/src/algorithms/mod.rs +++ b/src/algorithms/mod.rs @@ -1,7 +1,9 @@ //! Core algorithm implementations organized by problem type. pub mod stable_matching; +pub mod interview_scheduling; // Re-export all algorithm modules for easier access pub use stable_matching::*; +pub use interview_scheduling::*; diff --git a/src/main.rs b/src/main.rs index 56547ee..1e9610a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,12 @@ //use algorithms::stable_matching::*; -use algorithms::algorithms::stable_matching::*; +use algorithms::interview_scheduling::*; fn main() { // Example usage of different algorithms println!("Running algorithm examples..."); - + // Use stable matching - // Use interval scheduling - // etc. + let config = InterviewGenConfig::default(); + let interviews = generate_random_interviews(&config); + println!("Generated {} interviews", interviews.len()); }