Skip to content

Commit 3756f15

Browse files
authored
Merge pull request #197 from IanWhitney/implement_triangle
Implement Triangle
2 parents 40924af + 3e28089 commit 3756f15

File tree

8 files changed

+286
-0
lines changed

8 files changed

+286
-0
lines changed

config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"etl",
2020
"sieve",
2121
"rna-transcription",
22+
"triangle",
2223
"roman-numerals",
2324
"all-your-base",
2425
"grade-school",

exercises/triangle/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
/target/
4+
5+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
6+
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
7+
Cargo.lock

exercises/triangle/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[package]
2+
name = "triangle"
3+
version = "0.0.0"

exercises/triangle/HINTS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Triangle in Rust
2+
3+
- [Result](https://doc.rust-lang.org/std/result/index.html)
4+
5+
Implementation of this can take many forms. Here are some topics that may help you, depending on the approach you take.
6+
7+
- [Enums](https://doc.rust-lang.org/book/enums.html)
8+
- [Traits](https://doc.rust-lang.org/book/traits.html)
9+
- [BTreeSet](https://doc.rust-lang.org/std/collections/btree_set/struct.BTreeSet.html)
10+
11+
Or maybe you will come up with an approach that uses none of those!

exercises/triangle/example.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use std::iter::FromIterator;
2+
use std::collections::BTreeSet;
3+
4+
pub struct Triangle {
5+
sides: [u16; 3],
6+
}
7+
8+
impl Triangle {
9+
#[cfg_attr(rustfmt, rustfmt_skip)]
10+
fn valid_sides(&self) -> bool {
11+
(self.sides.iter().all(|&s| s > 0)) &&
12+
(self.sides[0] + self.sides[1] >= self.sides[2]) &&
13+
(self.sides[1] + self.sides[2] >= self.sides[0]) &&
14+
(self.sides[2] + self.sides[0] >= self.sides[1])
15+
}
16+
17+
pub fn build(sides: [u16; 3]) -> Result<Self, ()> {
18+
let t = Triangle { sides: sides };
19+
20+
if t.valid_sides() {
21+
Ok(t)
22+
} else {
23+
Err(())
24+
}
25+
}
26+
27+
pub fn is_equilateral(&self) -> bool {
28+
BTreeSet::from_iter(self.sides.iter()).len() == 1
29+
}
30+
31+
pub fn is_isosceles(&self) -> bool {
32+
BTreeSet::from_iter(self.sides.iter()).len() == 2
33+
}
34+
35+
pub fn is_scalene(&self) -> bool {
36+
BTreeSet::from_iter(self.sides.iter()).len() == 3
37+
}
38+
}

exercises/triangle/float_example.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use std::iter::FromIterator;
2+
use std::collections::BTreeSet;
3+
4+
extern crate num;
5+
6+
use num::Num;
7+
8+
pub struct Triangle<T> {
9+
sides: [T; 3],
10+
}
11+
12+
impl<T: Num + PartialOrd + PartialEq + Copy> Triangle<T> {
13+
#[cfg_attr(rustfmt, rustfmt_skip)]
14+
fn valid_sides(&self) -> bool {
15+
let z = self.sides[0] - self.sides[0];
16+
(self.sides.iter().all(|&s| s > z)) &&
17+
(self.sides[0] + self.sides[1] >= self.sides[2]) &&
18+
(self.sides[1] + self.sides[2] >= self.sides[0]) &&
19+
(self.sides[2] + self.sides[0] >= self.sides[1])
20+
}
21+
22+
pub fn build(sides: [T; 3]) -> Result<Self, ()> {
23+
let t = Triangle { sides: sides };
24+
25+
if t.valid_sides() {
26+
Ok(t)
27+
} else {
28+
Err(())
29+
}
30+
}
31+
32+
pub fn is_equilateral(&self) -> bool {
33+
let a = self.sides[0];
34+
let b = self.sides[1];
35+
let c = self.sides[2];
36+
37+
a == b && b == c
38+
}
39+
40+
pub fn is_isosceles(&self) -> bool {
41+
let a = self.sides[0];
42+
let b = self.sides[1];
43+
let c = self.sides[2];
44+
45+
(a == b && a != c) || (a == c && a != b) || (b == c && a != b)
46+
}
47+
48+
pub fn is_scalene(&self) -> bool {
49+
let a = self.sides[0];
50+
let b = self.sides[1];
51+
let c = self.sides[2];
52+
53+
a != b && a != c && b != c
54+
}
55+
}

exercises/triangle/tests/triangle.rs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
extern crate triangle;
2+
3+
use triangle::*;
4+
5+
#[test]
6+
fn positive_length_sides_are_ok() {
7+
let sides = [2, 2, 2];
8+
let triangle = Triangle::build(sides);
9+
assert!(triangle.is_ok());
10+
}
11+
12+
#[test]
13+
#[ignore]
14+
fn zero_length_sides_are_illegal() {
15+
let sides = [0, 0, 0];
16+
let triangle = Triangle::build(sides);
17+
assert!(triangle.is_err());
18+
}
19+
20+
#[test]
21+
#[ignore]
22+
fn equilateral_triangles_have_equal_sides() {
23+
let sides = [2, 2, 2];
24+
let triangle = Triangle::build(sides).unwrap();
25+
assert!(triangle.is_equilateral());
26+
assert!(!triangle.is_isosceles());
27+
assert!(!triangle.is_scalene());
28+
}
29+
30+
#[test]
31+
#[ignore]
32+
fn larger_equilateral_triangles_have_equal_sides() {
33+
let sides = [10, 10, 10];
34+
let triangle = Triangle::build(sides).unwrap();
35+
assert!(triangle.is_equilateral());
36+
assert!(!triangle.is_isosceles());
37+
assert!(!triangle.is_scalene());
38+
}
39+
40+
#[test]
41+
#[ignore]
42+
fn isocseles_triangles_have_two_equal_sides_one() {
43+
let sides = [3, 4, 4];
44+
let triangle = Triangle::build(sides).unwrap();
45+
assert!(!triangle.is_equilateral());
46+
assert!(triangle.is_isosceles());
47+
assert!(!triangle.is_scalene());
48+
}
49+
50+
#[test]
51+
#[ignore]
52+
fn isocseles_triangles_have_two_equal_sides_two() {
53+
let sides = [4, 4, 3];
54+
let triangle = Triangle::build(sides).unwrap();
55+
assert!(!triangle.is_equilateral());
56+
assert!(triangle.is_isosceles());
57+
assert!(!triangle.is_scalene());
58+
}
59+
60+
#[test]
61+
#[ignore]
62+
fn isocseles_triangles_have_two_equal_sides_three() {
63+
let sides = [4, 3, 4];
64+
let triangle = Triangle::build(sides).unwrap();
65+
assert!(!triangle.is_equilateral());
66+
assert!(triangle.is_isosceles());
67+
assert!(!triangle.is_scalene());
68+
}
69+
70+
#[test]
71+
#[ignore]
72+
fn isocseles_triangles_have_two_equal_sides_four() {
73+
let sides = [4, 7, 4];
74+
let triangle = Triangle::build(sides).unwrap();
75+
assert!(!triangle.is_equilateral());
76+
assert!(triangle.is_isosceles());
77+
assert!(!triangle.is_scalene());
78+
}
79+
80+
#[test]
81+
#[ignore]
82+
fn scalene_triangle_has_no_equal_sides_one() {
83+
let sides = [3, 4, 5];
84+
let triangle = Triangle::build(sides).unwrap();
85+
assert!(!triangle.is_equilateral());
86+
assert!(!triangle.is_isosceles());
87+
assert!(triangle.is_scalene());
88+
}
89+
90+
#[test]
91+
#[ignore]
92+
fn scalene_triangle_has_no_equal_sides_two() {
93+
let sides = [5, 4, 6];
94+
let triangle = Triangle::build(sides).unwrap();
95+
assert!(!triangle.is_equilateral());
96+
assert!(!triangle.is_isosceles());
97+
assert!(triangle.is_scalene());
98+
}
99+
100+
#[test]
101+
#[ignore]
102+
fn scalene_triangle_has_no_equal_sides_three() {
103+
let sides = [10, 11, 12];
104+
let triangle = Triangle::build(sides).unwrap();
105+
assert!(!triangle.is_equilateral());
106+
assert!(!triangle.is_isosceles());
107+
assert!(triangle.is_scalene());
108+
}
109+
110+
#[test]
111+
#[ignore]
112+
fn scalene_triangle_has_no_equal_sides_four() {
113+
let sides = [5, 4, 2];
114+
let triangle = Triangle::build(sides).unwrap();
115+
assert!(!triangle.is_equilateral());
116+
assert!(!triangle.is_isosceles());
117+
assert!(triangle.is_scalene());
118+
}
119+
120+
#[test]
121+
#[ignore]
122+
fn sum_of_two_sides_must_equal_or_exceed_the_remaining_side_one() {
123+
let sides = [7, 3, 2];
124+
let triangle = Triangle::build(sides);
125+
assert!(triangle.is_err());
126+
}
127+
128+
#[test]
129+
#[ignore]
130+
fn sum_of_two_sides_must_equal_or_exceed_the_remaining_side_two() {
131+
let sides = [1, 1, 3];
132+
let triangle = Triangle::build(sides);
133+
assert!(triangle.is_err());
134+
}
135+
136+
// Optional Tests
137+
//
138+
// Support Triangles with non-integer sides.
139+
//
140+
// You'll probably want to use the Num crate
141+
//
142+
// https://crates.io/crates/num
143+
//
144+
145+
// #[test]
146+
// fn scalene_triangle_with_floating_point_sides() {
147+
// let sides = [0.4, 0.6, 0.3];
148+
// let triangle = Triangle::build(sides).unwrap();
149+
// assert!(!triangle.is_equilateral());
150+
// assert!(!triangle.is_isosceles());
151+
// assert!(triangle.is_scalene());
152+
// }
153+
//
154+
// #[test]
155+
// fn equilateral_triangles_with_floating_point_sides() {
156+
// let sides = [0.2, 0.2, 0.2];
157+
// let triangle = Triangle::build(sides).unwrap();
158+
// assert!(triangle.is_equilateral());
159+
// assert!(!triangle.is_isosceles());
160+
// assert!(!triangle.is_scalene());
161+
// }
162+
//
163+
// #[test]
164+
// fn isocseles_triangle_with_floating_point_sides() {
165+
// let sides = [0.3, 0.4, 0.4];
166+
// let triangle = Triangle::build(sides).unwrap();
167+
// assert!(!triangle.is_equilateral());
168+
// assert!(triangle.is_isosceles());
169+
// assert!(!triangle.is_scalene());
170+
// }

problems.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ word-count | hashmap, str vs string, chars, entry api
3838
etl | btree
3939
sieve | vector, map, while let (optional)
4040
rna-transcription | match, struct, str vs string
41+
triangle | Math, Struct. Enum, Trait, Box -- depending on implementation
4142
roman-numerals | mutable, results, loops, struct, traits
4243
all-your-base | Result, enumerate, fold, map
4344
grade-school | struct, entry api, Vec, Option

0 commit comments

Comments
 (0)