Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Last active May 14, 2018 20:09
Show Gist options
  • Save AnthonyMikh/e676d27a8ea1fb24953916579a8e4240 to your computer and use it in GitHub Desktop.
Save AnthonyMikh/e676d27a8ea1fb24953916579a8e4240 to your computer and use it in GitHub Desktop.
Решение задачи №93 от UniLecs
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));
}
@AnthonyMikh
Copy link
Author

AnthonyMikh commented May 11, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment