Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Created April 18, 2018 22:29
Show Gist options
  • Save AnthonyMikh/dc305c30315f4a8f77f41656d085a5f1 to your computer and use it in GitHub Desktop.
Save AnthonyMikh/dc305c30315f4a8f77f41656d085a5f1 to your computer and use it in GitHub Desktop.
Решение задачи №86 от UniLecs
//Тип стороны прямоугольника
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)));
}
@AnthonyMikh
Copy link
Author

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