Advent of Code solutions in Rust

feat: output durations to three significant places

+70 -14
+10 -9
Cargo.lock
··· 171 171 "serde_json", 172 172 "termion", 173 173 "thiserror", 174 + "time", 174 175 "tokio", 175 176 ] 176 177 ··· 410 411 411 412 [[package]] 412 413 name = "deranged" 413 - version = "0.3.11" 414 + version = "0.5.5" 414 415 source = "registry+https://github.com/rust-lang/crates.io-index" 415 - checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 416 + checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" 416 417 dependencies = [ 417 418 "powerfmt", 418 419 ] ··· 1551 1552 "once_cell", 1552 1553 "socket2", 1553 1554 "tracing", 1554 - "windows-sys 0.52.0", 1555 + "windows-sys 0.60.2", 1555 1556 ] 1556 1557 1557 1558 [[package]] ··· 2202 2203 2203 2204 [[package]] 2204 2205 name = "time" 2205 - version = "0.3.37" 2206 + version = "0.3.44" 2206 2207 source = "registry+https://github.com/rust-lang/crates.io-index" 2207 - checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" 2208 + checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" 2208 2209 dependencies = [ 2209 2210 "deranged", 2210 2211 "itoa", ··· 2217 2218 2218 2219 [[package]] 2219 2220 name = "time-core" 2220 - version = "0.1.2" 2221 + version = "0.1.6" 2221 2222 source = "registry+https://github.com/rust-lang/crates.io-index" 2222 - checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 2223 + checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" 2223 2224 2224 2225 [[package]] 2225 2226 name = "time-macros" 2226 - version = "0.2.19" 2227 + version = "0.2.24" 2227 2228 source = "registry+https://github.com/rust-lang/crates.io-index" 2228 - checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" 2229 + checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" 2229 2230 dependencies = [ 2230 2231 "num-conv", 2231 2232 "time-core",
+1
aoc_companion/Cargo.toml
··· 18 18 serde_json = "1.0.145" 19 19 termion = "4.0.6" 20 20 thiserror = { workspace = true } 21 + time = "0.3.44" 21 22 tokio = { workspace = true, features = ["macros", "fs"] }
+4 -2
aoc_companion/src/door.rs
··· 119 119 pub enum DoorPartResult { 120 120 Computed { 121 121 answer: String, 122 - time: std::time::Duration, 122 + time: time::Duration, 123 123 }, 124 124 Skipped, 125 125 } ··· 135 135 let end = std::time::Instant::now(); 136 136 Ok(DoorPartResult::Computed { 137 137 answer: answer.to_string(), 138 - time: end - start, 138 + time: (end - start) 139 + .try_into() 140 + .expect("duration should be positive"), 139 141 }) 140 142 } 141 143 }
+55 -3
aoc_companion/src/output.rs
··· 9 9 use std::collections::BTreeMap; 10 10 use std::fmt::{Display, Formatter}; 11 11 use std::io::Write; 12 + use std::num::NonZero; 12 13 13 14 #[derive(Debug)] 14 15 pub enum Progress { ··· 37 38 Ok(PartValidation { 38 39 guess: DoorPartResult::Computed { answer, time }, 39 40 validity: Consistent, 40 - }) => (format!("{answer} ({time:?})"), '⭐'), 41 + }) => ( 42 + format!("{answer} ({time:.0$})", significant_decimals(time, 3)), 43 + '⭐', 44 + ), 41 45 Ok(PartValidation { 42 46 guess: DoorPartResult::Computed { answer, .. }, 43 47 validity: DisparateAnswer { correct }, ··· 45 49 Ok(PartValidation { 46 50 guess: DoorPartResult::Computed { answer, time }, 47 51 validity: GuessSubmitted(Correct), 48 - }) => (format!("{answer} ({time:?})"), '🌟'), 52 + }) => ( 53 + format!("{answer} ({time:.0$})", significant_decimals(time, 3)), 54 + '🌟', 55 + ), 49 56 Ok(PartValidation { 50 57 guess: DoorPartResult::Computed { answer, .. }, 51 58 validity: GuessSubmitted(GuessedTooRecently), ··· 56 63 Ok(PartValidation { 57 64 guess: DoorPartResult::Computed { answer, time }, 58 65 validity: Unknown, 59 - }) => (format!("{answer} ({time:?})"), '🤷'), 66 + }) => ( 67 + format!("{answer} ({time:.0$})", significant_decimals(time, 3)), 68 + '🤷', 69 + ), 60 70 Ok(PartValidation { 61 71 guess: DoorPartResult::Skipped, 62 72 validity: Skipped { correct }, ··· 155 165 156 166 table 157 167 } 168 + 169 + fn significant_decimals(duration: &time::Duration, significant_places: usize) -> usize { 170 + let seconds = duration.as_seconds_f64(); 171 + let Some(non_zero_unit) = 172 + NonZero::new((seconds / time::convert::Second::per_t::<f64>(time::convert::Day)) as i64) 173 + .or_else(|| { 174 + NonZero::new( 175 + (seconds / time::convert::Second::per_t::<f64>(time::convert::Hour)) as i64, 176 + ) 177 + }) 178 + .or_else(|| { 179 + NonZero::new( 180 + (seconds / time::convert::Second::per_t::<f64>(time::convert::Minute)) as i64, 181 + ) 182 + }) 183 + .or_else(|| NonZero::new((seconds) as i64)) 184 + .or_else(|| { 185 + NonZero::new( 186 + (seconds * time::convert::Millisecond::per_t::<f64>(time::convert::Second)) 187 + as i64, 188 + ) 189 + }) 190 + .or_else(|| { 191 + NonZero::new( 192 + (seconds * time::convert::Microsecond::per_t::<f64>(time::convert::Second)) 193 + as i64, 194 + ) 195 + }) 196 + .or_else(|| { 197 + NonZero::new( 198 + (seconds * time::convert::Nanosecond::per_t::<f64>(time::convert::Second)) 199 + as i64, 200 + ) 201 + }) 202 + else { 203 + return 0; 204 + }; 205 + 206 + let leading_digits = non_zero_unit.get().checked_ilog10().unwrap_or(0) as usize + 1; 207 + 208 + significant_places.saturating_sub(leading_digits) 209 + }