Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Тип стороны прямоугольника
- type RectSide = f64;
- //Верхняя граница на стороны прямоугольника
- const SIDE_BOUND: RectSide = 1_000_000_000.0;
- #[derive(Debug, PartialEq)]
- enum MaxSquareSideError { //Тип ошибки при решении задачи:
- NonPositive(RectSide), //сторона неположительна,
- OutOfBound(RectSide), //сторона слишком большая,
- Malformed(RectSide), //сторона сошла с ума.
- }
- //Принимает на вход стороны прямоугольника.
- //Возвращает наибольшую возможную сторону квадрата, которые можно вырезать
- //в количестве 3 штук из прямоугольника с переданными размерами,
- //или ошибку, если ответ дать невозможно.
- fn max_square_side(a: RectSide, b: RectSide) -> Result<RectSide, MaxSquareSideError> {
- //Проверяет на ошибки сторону
- fn check_side(x: RectSide) -> Result<RectSide, MaxSquareSideError> {
- use MaxSquareSideError::*;
- if x.is_nan() || x.is_infinite() {
- return Err(Malformed(x));
- }
- if x <= 0.0 {
- return Err(NonPositive(x));
- }
- if x > SIDE_BOUND {
- return Err(OutOfBound(x));
- }
- Ok(x)
- }
- check_side(a)?; //Проверяем сторону a и при ошибке немедленно возвращаем.
- check_side(b)?; //Аналогично с b.
- //Максимизировать сторону квадрата можно двумя способами:
- let (bigger, smaller) = if a > b { (a, b) } else { (b, a) };
- //расположив уголком (в этом случае сторона квадрата составляет
- //половину меньшей стороны)
- let max1 = smaller / 2.0;
- //или расположив полосой (в этом случае сторона квадрата составляет
- //меньшее из меньшей стороны и трети большой).
- let max2 = smaller.min(bigger / 3.0);
- //Из двух возможных вариантов возвращаем бо́льшую сторону
- Ok(max1.max(max2))
- }
- #[test]
- fn ensure_bound_correctness() {
- assert!(!SIDE_BOUND.is_nan()
- && !SIDE_BOUND.is_infinite()
- && SIDE_BOUND > 0.0);
- assert!(!(SIDE_BOUND * SIDE_BOUND).is_infinite());
- }
- #[test]
- fn some_variants() {
- assert_eq!(max_square_side(210.0, 297.0), Ok(105.0));
- assert_eq!(max_square_side(250.0, 100.0), Ok(83.33333333333333));
- assert_eq!(max_square_side(400.0, 404.0), Ok(200.0));
- assert_eq!(max_square_side(1.0, 100.0), Ok(1.0));
- assert_eq!(max_square_side(870.0, 300.0), Ok(290.0));
- }
- #[test]
- fn check_bound() {
- use MaxSquareSideError::*;
- let (a, b) = (SIDE_BOUND + 1.0, 3.14);
- assert_eq!(max_square_side(a, b), Err(OutOfBound(a)));
- }
- #[test]
- fn check_nonpositive() {
- use MaxSquareSideError::*;
- let (a, b) = (0.0, 3.14);
- assert_eq!(max_square_side(a, b), Err(NonPositive(a)));
- let (a, b) = (3.14, -42.0);
- assert_eq!(max_square_side(a, b), Err(NonPositive(b)));
- }
- #[test]
- fn check_malformed() {
- use MaxSquareSideError::*;
- let (a, b) = (0.0/0.0, 3.14);
- //NaN не равен самому себе
- match max_square_side(a, b) {
- Err(Malformed(val)) => assert!(val.is_nan()),
- _ => unreachable!(),
- }
- let (a, b) = (1.0/0.0, 666.9);
- assert_eq!(max_square_side(a, b), Err(Malformed(a)));
- let (a, b) = (-1.0/0.0, 123.4);
- assert_eq!(max_square_side(a, b), Err(Malformed(a)));
- }
Add Comment
Please, Sign In to add comment