Last active
May 14, 2018 20:09
-
-
Save AnthonyMikh/e676d27a8ea1fb24953916579a8e4240 to your computer and use it in GitHub Desktop.
Решение задачи №93 от UniLecs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Duration = u32; | |
type DurationTriple = (Duration, Duration, Duration); | |
const TIME_BOUND: Duration = 1_000; | |
const LEN_BOUND: usize = 1_000; | |
#[derive(Clone)] | |
struct SellTimes { | |
one: Duration, | |
two: Duration, | |
three: Duration, | |
} | |
impl ::std::convert::From<DurationTriple> for SellTimes { | |
fn from((one, two, three): DurationTriple) -> Self { | |
Self { one, two, three } | |
} | |
} | |
#[derive(Clone)] | |
struct SellDuration { | |
to_current: Duration, | |
sell: SellTimes, | |
} | |
impl ::std::convert::From<(Duration, SellTimes)> for SellDuration { | |
fn from((to_current, sell): (Duration, SellTimes)) -> Self { | |
Self { to_current, sell } | |
} | |
} | |
#[derive(Debug, PartialEq, Eq)] | |
enum LeastTimeError { | |
OutOfBound(usize), | |
TooLarge, | |
} | |
fn least_time<T>(sell_times: T) -> Result<Duration, LeastTimeError> | |
where | |
T: IntoIterator<Item = SellTimes>, | |
{ | |
let to = |x: &SellDuration| x.to_current; | |
const MAX_DURATION: Duration = Duration::max_value(); | |
let init = SellDuration::from((0, (0, MAX_DURATION, MAX_DURATION).into())); | |
let mut prevs = (init.clone(), init.clone(), init); | |
for (i, sell) in sell_times.into_iter().enumerate() { | |
if i >= LEN_BOUND { | |
return Err(LeastTimeError::TooLarge); | |
} | |
if sell.three > TIME_BOUND || sell.two > TIME_BOUND || sell.one > TIME_BOUND { | |
return Err(LeastTimeError::OutOfBound(i)); | |
} | |
let (first, second, third) = prevs; | |
let to_current = (to(&first) + second.sell.three) | |
.min(to(&second) + third.sell.two) | |
.min(to(&third) + sell.one); | |
prevs = (second, third, (to_current, sell).into()); | |
} | |
let (_, _, last) = prevs; | |
Ok(to(&last)) | |
} | |
fn least_time_arrs(a: &[Duration], b: &[Duration], c: &[Duration]) -> Result<Duration, LeastTimeError> { | |
assert!( | |
a.len() == b.len() && b.len() == c.len(), | |
"least_time_arrs error: all three arrays must share the same length" | |
); | |
let triples = a.iter() | |
.cloned() | |
.zip(b.iter().cloned()) | |
.zip(c.iter().cloned()) | |
.map(|((x, y), z)| (x, y, z).into()); | |
least_time(triples) | |
} | |
#[test] | |
fn some_examples() { | |
let a = [5, 2, 5, 20, 20]; | |
let b = [10, 10, 5, 20, 1]; | |
let c = [5, 15, 5, 1, 1]; | |
assert_eq!(least_time_arrs(&a, &b, &c), Ok(12)); | |
let times = [ | |
(2, 7, 4), | |
(6, 1, 1), | |
(1, 3, 4), | |
(7, 9, 9), | |
(12, 20, 3), | |
(5, 6, 22), | |
]; | |
let times = times.iter().cloned().map(Into::<SellTimes>::into); | |
assert_eq!(least_time(times), Ok(12)); | |
} | |
#[test] | |
fn check_errors() { | |
use LeastTimeError::*; | |
let arr = [(1, 2, 3), (TIME_BOUND + 1, 23, 22)]; | |
let arr = arr.iter().cloned().map(Into::<SellTimes>::into); | |
assert_eq!(least_time(arr), Err(OutOfBound(1))); | |
let arr = [(1, 1, 1); LEN_BOUND + 1]; | |
let arr = arr.iter().cloned().map(Into::<SellTimes>::into); | |
assert_eq!(least_time(arr), Err(TooLarge)); | |
} | |
#[test] | |
fn check_empty() { | |
let times = ::std::iter::empty(); | |
assert_eq!(least_time(times), Ok(0)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Playground (rev. 1): http://play.rust-lang.org/?gist=3a49eaa0a879c6b6cfe55948569b2f7e&version=stable&mode=debug
Playground (rev. 2): http://play.rust-lang.org/?gist=68d96e626886ca7333ac4b6fc7181b90&version=stable&mode=debug