Guest User

Untitled

a guest
Apr 26th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.75 KB | None | 0 0
  1. //Тип стороны прямоугольника
  2. type RectSide = f64;
  3.  
  4. //Верхняя граница на стороны прямоугольника
  5. const SIDE_BOUND: RectSide = 1_000_000_000.0;
  6.  
  7. #[derive(Debug, PartialEq)]
  8. enum MaxSquareSideError { //Тип ошибки при решении задачи:
  9. NonPositive(RectSide), //сторона неположительна,
  10. OutOfBound(RectSide), //сторона слишком большая,
  11. Malformed(RectSide), //сторона сошла с ума.
  12. }
  13.  
  14. //Принимает на вход стороны прямоугольника.
  15. //Возвращает наибольшую возможную сторону квадрата, которые можно вырезать
  16. //в количестве 3 штук из прямоугольника с переданными размерами,
  17. //или ошибку, если ответ дать невозможно.
  18. fn max_square_side(a: RectSide, b: RectSide) -> Result<RectSide, MaxSquareSideError> {
  19. //Проверяет на ошибки сторону
  20. fn check_side(x: RectSide) -> Result<RectSide, MaxSquareSideError> {
  21. use MaxSquareSideError::*;
  22. if x.is_nan() || x.is_infinite() {
  23. return Err(Malformed(x));
  24. }
  25. if x <= 0.0 {
  26. return Err(NonPositive(x));
  27. }
  28. if x > SIDE_BOUND {
  29. return Err(OutOfBound(x));
  30. }
  31. Ok(x)
  32. }
  33.  
  34. check_side(a)?; //Проверяем сторону a и при ошибке немедленно возвращаем.
  35. check_side(b)?; //Аналогично с b.
  36.  
  37. //Максимизировать сторону квадрата можно двумя способами:
  38. let (bigger, smaller) = if a > b { (a, b) } else { (b, a) };
  39. //расположив уголком (в этом случае сторона квадрата составляет
  40. //половину меньшей стороны)
  41. let max1 = smaller / 2.0;
  42. //или расположив полосой (в этом случае сторона квадрата составляет
  43. //меньшее из меньшей стороны и трети большой).
  44. let max2 = smaller.min(bigger / 3.0);
  45.  
  46. //Из двух возможных вариантов возвращаем бо́льшую сторону
  47. Ok(max1.max(max2))
  48. }
  49.  
  50. #[test]
  51. fn ensure_bound_correctness() {
  52. assert!(!SIDE_BOUND.is_nan()
  53. && !SIDE_BOUND.is_infinite()
  54. && SIDE_BOUND > 0.0);
  55.  
  56. assert!(!(SIDE_BOUND * SIDE_BOUND).is_infinite());
  57. }
  58.  
  59. #[test]
  60. fn some_variants() {
  61. assert_eq!(max_square_side(210.0, 297.0), Ok(105.0));
  62. assert_eq!(max_square_side(250.0, 100.0), Ok(83.33333333333333));
  63. assert_eq!(max_square_side(400.0, 404.0), Ok(200.0));
  64. assert_eq!(max_square_side(1.0, 100.0), Ok(1.0));
  65. assert_eq!(max_square_side(870.0, 300.0), Ok(290.0));
  66. }
  67.  
  68. #[test]
  69. fn check_bound() {
  70. use MaxSquareSideError::*;
  71. let (a, b) = (SIDE_BOUND + 1.0, 3.14);
  72. assert_eq!(max_square_side(a, b), Err(OutOfBound(a)));
  73. }
  74.  
  75. #[test]
  76. fn check_nonpositive() {
  77. use MaxSquareSideError::*;
  78.  
  79. let (a, b) = (0.0, 3.14);
  80. assert_eq!(max_square_side(a, b), Err(NonPositive(a)));
  81.  
  82. let (a, b) = (3.14, -42.0);
  83. assert_eq!(max_square_side(a, b), Err(NonPositive(b)));
  84. }
  85.  
  86. #[test]
  87. fn check_malformed() {
  88. use MaxSquareSideError::*;
  89.  
  90. let (a, b) = (0.0/0.0, 3.14);
  91. //NaN не равен самому себе
  92. match max_square_side(a, b) {
  93. Err(Malformed(val)) => assert!(val.is_nan()),
  94. _ => unreachable!(),
  95. }
  96.  
  97. let (a, b) = (1.0/0.0, 666.9);
  98. assert_eq!(max_square_side(a, b), Err(Malformed(a)));
  99.  
  100. let (a, b) = (-1.0/0.0, 123.4);
  101. assert_eq!(max_square_side(a, b), Err(Malformed(a)));
  102. }
Add Comment
Please, Sign In to add comment