|
1 | | -// Write three methods for BloodType: |
2 | | -// - can_receive_from(&self, other: BloodType) -> bool {}: which |
3 | | -// returns true if self can receive blood from `other` blood type |
4 | | -// - donors(&self) -> Vec<BloodType>: which returns |
5 | | -// all the blood types that can give blood to self |
6 | | -// - recipients(&self) -> Vec<BloodType>: which returns all the blood |
7 | | -// types that can receive blood from self |
8 | | - |
9 | | -#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] |
| 1 | +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] |
10 | 2 | pub enum Antigen { |
11 | 3 | A, |
12 | 4 | AB, |
13 | 5 | B, |
14 | 6 | O, |
15 | 7 | } |
16 | 8 |
|
17 | | -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
| 9 | +impl Antigen { |
| 10 | + pub const EVERY: &[Self] = &[Self::A, Self::AB, Self::B, Self::O]; |
| 11 | +} |
| 12 | + |
| 13 | +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] |
18 | 14 | pub enum RhFactor { |
19 | 15 | Positive, |
20 | 16 | Negative, |
21 | 17 | } |
22 | 18 |
|
23 | | -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
| 19 | +impl RhFactor { |
| 20 | + pub const EVERY: &[Self] = &[Self::Positive, Self::Negative]; |
| 21 | +} |
| 22 | + |
| 23 | +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] |
24 | 24 | pub struct BloodType { |
25 | | - pub antigen: Antigen, |
26 | 25 | pub rh_factor: RhFactor, |
| 26 | + pub antigen: Antigen, |
27 | 27 | } |
28 | 28 |
|
29 | 29 | impl BloodType { |
30 | | - pub fn can_receive_from(&self, other: &Self) -> bool { |
31 | | - // Positive can only receive from positive |
32 | | - // A can only give from A |
33 | | - // And B can only give to B |
34 | | - if self.rh_factor != other.rh_factor && self.rh_factor == RhFactor::Negative { |
35 | | - return false; |
36 | | - } |
37 | | - |
38 | | - if other.antigen == Antigen::O { |
39 | | - return true; |
40 | | - } |
41 | | - |
42 | | - // if self.rh_factor contains one of the antigens of other |
43 | | - // then it can receive from it |
44 | | - self.antigen == Antigen::AB || other.antigen == self.antigen |
| 30 | + #[inline] |
| 31 | + pub fn every() -> impl Iterator<Item = Self> { |
| 32 | + Antigen::EVERY.iter().copied().flat_map(|a| { |
| 33 | + RhFactor::EVERY.iter().copied().map(move |r| Self { |
| 34 | + antigen: a, |
| 35 | + rh_factor: r, |
| 36 | + }) |
| 37 | + }) |
45 | 38 | } |
46 | 39 |
|
47 | | - // who are the donors of self |
48 | | - pub fn donors(&self) -> Vec<Self> { |
49 | | - // all blood types A, B, AB, O |
50 | | - let mut blood_types = Vec::new(); |
51 | | - let mut antigens = if self.antigen == Antigen::O { |
52 | | - vec![Antigen::O] |
53 | | - } else { |
54 | | - vec![Antigen::O, self.antigen.clone()] |
55 | | - }; |
56 | | - |
57 | | - let rh_factors = if self.rh_factor == RhFactor::Negative { |
58 | | - vec![RhFactor::Negative] |
59 | | - } else { |
60 | | - vec![RhFactor::Positive, RhFactor::Negative] |
61 | | - }; |
62 | | - |
63 | | - if self.antigen == Antigen::AB { |
64 | | - antigens.extend(vec![Antigen::A, Antigen::B]); |
65 | | - } |
66 | | - |
67 | | - for factor in rh_factors.iter() { |
68 | | - for ant in antigens.iter() { |
69 | | - blood_types.push(BloodType { |
70 | | - rh_factor: (*factor).clone(), |
71 | | - antigen: (*ant).clone(), |
72 | | - }) |
73 | | - } |
74 | | - } |
75 | | - |
76 | | - blood_types |
| 40 | + #[inline] |
| 41 | + fn can_donate_to(self, other: Self) -> bool { |
| 42 | + other.can_receive_from(self) |
77 | 43 | } |
78 | 44 |
|
79 | | - // who are the recipients of self |
80 | | - pub fn recipients(&self) -> Vec<BloodType> { |
81 | | - let mut blood_types = Vec::new(); |
82 | | - let mut antigens = if self.antigen != Antigen::AB { |
83 | | - vec![Antigen::AB, self.antigen.clone()] |
84 | | - } else { |
85 | | - vec![Antigen::AB] |
86 | | - }; |
87 | | - |
88 | | - let rh_factors = if self.rh_factor == RhFactor::Negative { |
89 | | - vec![RhFactor::Positive, RhFactor::Negative] |
90 | | - } else { |
91 | | - vec![RhFactor::Positive] |
92 | | - }; |
93 | | - |
94 | | - if self.antigen == Antigen::O { |
95 | | - antigens.extend(vec![Antigen::A, Antigen::B]); |
96 | | - } |
97 | | - |
98 | | - for factor in rh_factors.iter() { |
99 | | - for ant in antigens.iter() { |
100 | | - blood_types.push(BloodType { |
101 | | - rh_factor: (*factor).clone(), |
102 | | - antigen: (*ant).clone(), |
103 | | - }) |
104 | | - } |
| 45 | + pub fn can_receive_from(self, other: Self) -> bool { |
| 46 | + if !(self.rh_factor == other.rh_factor || self.rh_factor == RhFactor::Positive) { |
| 47 | + return false; |
105 | 48 | } |
106 | 49 |
|
107 | | - blood_types |
| 50 | + other.antigen == Antigen::O || self.antigen == Antigen::AB || other.antigen == self.antigen |
108 | 51 | } |
109 | | -} |
110 | | - |
111 | | -// fn main() { |
112 | | -// let blood_type: BloodType = "O+".parse().unwrap(); |
113 | | -// println!("recipients of O+ {:?}", blood_type.recipients()); |
114 | | -// println!("donors of O+ {:?}", blood_type.donors()); |
115 | | -// let another_blood_type: BloodType = "A-".parse().unwrap(); |
116 | | -// println!( |
117 | | -// "donors of O+ can receive from {:?} {:?}", |
118 | | -// &another_blood_type, |
119 | | -// blood_type.can_receive_from(&another_blood_type) |
120 | | -// ); |
121 | | -// } |
122 | | - |
123 | | -#[cfg(test)] |
124 | | -mod tests { |
125 | | - use super::*; |
126 | 52 |
|
127 | | - #[test] |
128 | | - fn compatible_ab_neg_with_a_pos() { |
129 | | - let blood_type = BloodType { |
130 | | - antigen: Antigen::AB, |
131 | | - rh_factor: RhFactor::Negative, |
132 | | - }; |
133 | | - let other_bt = BloodType { |
134 | | - antigen: Antigen::A, |
135 | | - rh_factor: RhFactor::Positive, |
136 | | - }; |
137 | | - assert!(!blood_type.can_receive_from(&other_bt)); |
| 53 | + #[inline] |
| 54 | + pub fn donors(self) -> Vec<Self> { |
| 55 | + Self::every() |
| 56 | + .filter(|&b| self.can_receive_from(b)) |
| 57 | + .collect() |
138 | 58 | } |
139 | 59 |
|
140 | | - #[test] |
141 | | - fn compatible_a_neg_with_a_pos() { |
142 | | - let blood_type = BloodType { |
143 | | - antigen: Antigen::A, |
144 | | - rh_factor: RhFactor::Negative, |
145 | | - }; |
146 | | - let other_bt = BloodType { |
147 | | - antigen: Antigen::A, |
148 | | - rh_factor: RhFactor::Positive, |
149 | | - }; |
150 | | - assert!(!blood_type.can_receive_from(&other_bt)); |
151 | | - } |
152 | | - |
153 | | - #[test] |
154 | | - fn compatible_a_neg_with_ab_neg() { |
155 | | - let blood_type = BloodType { |
156 | | - antigen: Antigen::AB, |
157 | | - rh_factor: RhFactor::Negative, |
158 | | - }; |
159 | | - let other_bt = BloodType { |
160 | | - antigen: Antigen::A, |
161 | | - rh_factor: RhFactor::Negative, |
162 | | - }; |
163 | | - assert!(blood_type.can_receive_from(&other_bt)); |
164 | | - } |
165 | | - |
166 | | - #[test] |
167 | | - fn compatible_ab_neg_with_o_pos() { |
168 | | - let blood_type = BloodType { |
169 | | - antigen: Antigen::AB, |
170 | | - rh_factor: RhFactor::Negative, |
171 | | - }; |
172 | | - let other_bt = BloodType { |
173 | | - antigen: Antigen::O, |
174 | | - rh_factor: RhFactor::Positive, |
175 | | - }; |
176 | | - assert!(!blood_type.can_receive_from(&other_bt)); |
177 | | - } |
178 | | - |
179 | | - #[test] |
180 | | - fn compatible_ab_pos_with_o_pos() { |
181 | | - let blood_type = BloodType { |
182 | | - antigen: Antigen::AB, |
183 | | - rh_factor: RhFactor::Positive, |
184 | | - }; |
185 | | - let other_bt = BloodType { |
186 | | - antigen: Antigen::O, |
187 | | - rh_factor: RhFactor::Positive, |
188 | | - }; |
189 | | - assert!(blood_type.can_receive_from(&other_bt)); |
190 | | - } |
191 | | - |
192 | | - #[test] |
193 | | - fn test_compatible_ab_neg_with_o_neg() { |
194 | | - let blood_type = BloodType { |
195 | | - antigen: Antigen::AB, |
196 | | - rh_factor: RhFactor::Negative, |
197 | | - }; |
198 | | - let other_bt = BloodType { |
199 | | - antigen: Antigen::O, |
200 | | - rh_factor: RhFactor::Negative, |
201 | | - }; |
202 | | - assert!(blood_type.can_receive_from(&other_bt)); |
203 | | - } |
204 | | - |
205 | | - #[test] |
206 | | - fn test_antigen_ab_from_str() { |
207 | | - let blood_type = BloodType { |
208 | | - antigen: Antigen::AB, |
209 | | - rh_factor: RhFactor::Positive, |
210 | | - }; |
211 | | - assert_eq!(blood_type.antigen, Antigen::AB); |
212 | | - assert_eq!(blood_type.rh_factor, RhFactor::Positive); |
213 | | - } |
214 | | - |
215 | | - #[test] |
216 | | - fn test_antigen_a_from_str() { |
217 | | - let blood_type = BloodType { |
218 | | - antigen: Antigen::A, |
219 | | - rh_factor: RhFactor::Negative, |
220 | | - }; |
221 | | - assert_eq!(blood_type.antigen, Antigen::A); |
222 | | - assert_eq!(blood_type.rh_factor, RhFactor::Negative); |
223 | | - } |
224 | | - |
225 | | - #[test] |
226 | | - fn test_donors() { |
227 | | - let blood_type = BloodType { |
228 | | - antigen: Antigen::AB, |
229 | | - rh_factor: RhFactor::Positive, |
230 | | - }; |
231 | | - let mut givers = blood_type.donors(); |
232 | | - // println!("Before sorting {:?}", &givers); |
233 | | - givers.sort(); |
234 | | - // println!("{:?}", &givers); |
235 | | - let mut expected = vec![ |
236 | | - BloodType { |
237 | | - antigen: Antigen::AB, |
238 | | - rh_factor: RhFactor::Negative, |
239 | | - }, |
240 | | - BloodType { |
241 | | - antigen: Antigen::A, |
242 | | - rh_factor: RhFactor::Negative, |
243 | | - }, |
244 | | - BloodType { |
245 | | - antigen: Antigen::B, |
246 | | - rh_factor: RhFactor::Negative, |
247 | | - }, |
248 | | - BloodType { |
249 | | - antigen: Antigen::O, |
250 | | - rh_factor: RhFactor::Negative, |
251 | | - }, |
252 | | - BloodType { |
253 | | - antigen: Antigen::AB, |
254 | | - rh_factor: RhFactor::Positive, |
255 | | - }, |
256 | | - BloodType { |
257 | | - antigen: Antigen::A, |
258 | | - rh_factor: RhFactor::Positive, |
259 | | - }, |
260 | | - BloodType { |
261 | | - antigen: Antigen::B, |
262 | | - rh_factor: RhFactor::Positive, |
263 | | - }, |
264 | | - BloodType { |
265 | | - antigen: Antigen::O, |
266 | | - rh_factor: RhFactor::Positive, |
267 | | - }, |
268 | | - ]; |
269 | | - expected.sort(); |
270 | | - assert_eq!(givers, expected); |
271 | | - } |
272 | | - |
273 | | - #[test] |
274 | | - fn test_a_neg_donors() { |
275 | | - let blood = BloodType { |
276 | | - antigen: Antigen::A, |
277 | | - rh_factor: RhFactor::Negative, |
278 | | - }; |
279 | | - let mut givers = blood.donors(); |
280 | | - givers.sort(); |
281 | | - let mut expected = vec![ |
282 | | - BloodType { |
283 | | - antigen: Antigen::A, |
284 | | - rh_factor: RhFactor::Negative, |
285 | | - }, |
286 | | - BloodType { |
287 | | - antigen: Antigen::O, |
288 | | - rh_factor: RhFactor::Negative, |
289 | | - }, |
290 | | - ]; |
291 | | - |
292 | | - expected.sort(); |
293 | | - assert_eq!(givers, expected); |
294 | | - } |
295 | | - |
296 | | - #[test] |
297 | | - fn test_o_neg_donors() { |
298 | | - let blood = BloodType { |
299 | | - antigen: Antigen::O, |
300 | | - rh_factor: RhFactor::Negative, |
301 | | - }; |
302 | | - |
303 | | - let mut givers = blood.donors(); |
304 | | - givers.sort(); |
305 | | - let mut expected = vec![blood.clone()]; |
306 | | - expected.sort(); |
307 | | - assert_eq!(givers, expected); |
308 | | - } |
309 | | - |
310 | | - #[test] |
311 | | - fn test_ab_pos_recipients() { |
312 | | - let blood = BloodType { |
313 | | - antigen: Antigen::AB, |
314 | | - rh_factor: RhFactor::Positive, |
315 | | - }; |
316 | | - let mut recipients = blood.recipients(); |
317 | | - recipients.sort(); |
318 | | - let mut expected = vec![blood.clone()]; |
319 | | - expected.sort(); |
320 | | - assert_eq!(recipients, expected); |
321 | | - } |
322 | | - |
323 | | - #[test] |
324 | | - fn test_a_neg_recipients() { |
325 | | - let blood = BloodType { |
326 | | - antigen: Antigen::A, |
327 | | - rh_factor: RhFactor::Negative, |
328 | | - }; |
329 | | - |
330 | | - let mut recipients = blood.recipients(); |
331 | | - recipients.sort(); |
332 | | - let mut expected = vec![ |
333 | | - blood.clone(), |
334 | | - BloodType { |
335 | | - antigen: Antigen::AB, |
336 | | - rh_factor: RhFactor::Positive, |
337 | | - }, |
338 | | - BloodType { |
339 | | - antigen: Antigen::A, |
340 | | - rh_factor: RhFactor::Positive, |
341 | | - }, |
342 | | - BloodType { |
343 | | - antigen: Antigen::AB, |
344 | | - rh_factor: RhFactor::Negative, |
345 | | - }, |
346 | | - ]; |
347 | | - expected.sort(); |
348 | | - assert_eq!(recipients, expected); |
| 60 | + #[inline] |
| 61 | + pub fn recipients(self) -> Vec<Self> { |
| 62 | + Self::every().filter(|&b| self.can_donate_to(b)).collect() |
349 | 63 | } |
350 | 64 | } |
0 commit comments