Created
April 18, 2018 22:29
-
-
Save AnthonyMikh/dc305c30315f4a8f77f41656d085a5f1 to your computer and use it in GitHub Desktop.
Решение задачи №86 от 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 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))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Playground: https://play.rust-lang.org/?gist=68ae532ea4e0119f658ff51e162ed2f5&version=stable