|
| 1 | +#![allow(unused)] |
| 2 | + |
| 3 | +use std::collections::HashMap; |
| 4 | + |
| 5 | +struct UndergroundSystem { |
| 6 | + station_times: HashMap<(String, String), (f64, i32)>, |
| 7 | + current_passengers: HashMap<i32, (String, i32)>, |
| 8 | +} |
| 9 | + |
| 10 | +/** |
| 11 | + * `&self` means the method takes an immutable reference. |
| 12 | + * If you need a mutable reference, change it to `&mut self` instead. |
| 13 | + */ |
| 14 | +impl UndergroundSystem { |
| 15 | + fn new() -> Self { |
| 16 | + return Self { |
| 17 | + station_times: HashMap::new(), |
| 18 | + current_passengers: HashMap::new(), |
| 19 | + }; |
| 20 | + } |
| 21 | + |
| 22 | + // O(1) |
| 23 | + fn check_in(&mut self, id: i32, station_name: String, t: i32) { |
| 24 | + self.current_passengers.insert(id, (station_name, t)); |
| 25 | + } |
| 26 | + |
| 27 | + // O(1) |
| 28 | + fn check_out(&mut self, id: i32, station_name: String, t: i32) { |
| 29 | + if let Some((entry_station, entry_time)) = self.current_passengers.get(&id) { |
| 30 | + let (ave_time, samples) = self |
| 31 | + .station_times |
| 32 | + .entry((entry_station.to_string(), station_name)) |
| 33 | + .or_default(); |
| 34 | + |
| 35 | + // Calculate rolling average |
| 36 | + |
| 37 | + // prev_ave * samples |
| 38 | + let curr_ave = *ave_time * (*samples as f64); |
| 39 | + // increment samples |
| 40 | + *samples += 1; |
| 41 | + |
| 42 | + // new ave = ((Prev*Count) + NewVal) / (Count+1) |
| 43 | + *ave_time = (curr_ave + (t - entry_time) as f64) / (*samples as f64); |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + // O(1) |
| 48 | + fn get_average_time(&self, start_station: String, end_station: String) -> f64 { |
| 49 | + if let Some((ave_time, _)) = self.station_times.get(&(start_station, end_station)) { |
| 50 | + return *ave_time; |
| 51 | + } |
| 52 | + 0.0 |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +// Your UndergroundSystem object will be instantiated and called as such: |
| 57 | +// let obj = UndergroundSystem::new(); |
| 58 | +// obj.check_in(id, stationName, t); |
| 59 | +// obj.check_out(id, stationName, t); |
| 60 | +// let ret_3: f64 = obj.get_average_time(startStation, endStation); |
| 61 | + |
| 62 | +#[test] |
| 63 | +fn test1() { |
| 64 | + let mut underground_system: UndergroundSystem = UndergroundSystem::new(); |
| 65 | + underground_system.check_in(10, String::from("Leyton"), 3); |
| 66 | + underground_system.check_out(10, String::from("Paradise"), 8); // Customer 10 String::from("Leyton") -> String::from("Paradise") in 8-3 = 5 |
| 67 | + |
| 68 | + let r1 = underground_system.get_average_time(String::from("Leyton"), String::from("Paradise")); // return 5.00000, (5) / 1 = 5 |
| 69 | + assert_eq!(r1, 5.0); |
| 70 | + |
| 71 | + underground_system.check_in(5, String::from("Leyton"), 10); |
| 72 | + underground_system.check_out(5, String::from("Paradise"), 16); // Customer 5 String::from("Leyton") -> String::from("Paradise") in 16-10 = 6 |
| 73 | + |
| 74 | + let r2 = underground_system.get_average_time(String::from("Leyton"), String::from("Paradise")); // return 5.50000, (5 + 6) / 2 = 5.5 |
| 75 | + assert_eq!(r2, 5.5); |
| 76 | + |
| 77 | + underground_system.check_in(2, String::from("Leyton"), 21); |
| 78 | + underground_system.check_out(2, String::from("Paradise"), 30); // Customer 2 String::from("Leyton") -> String::from("Paradise") in 30-21 = 9 |
| 79 | + let r3 = underground_system.get_average_time(String::from("Leyton"), String::from("Paradise")); |
| 80 | + assert_eq!(r3, 20.0 / 3.0); // return 6.66667, (5 + 6 + 9) / 3 = 6.66667 |
| 81 | +} |
0 commit comments