Skip to content

Commit 2d2ffc4

Browse files
sozelfistvil02
andauthored
Refator Egg Dropping Implementation (#776)
* ref: improve egg dropping implementation * chore: update docstring * style: use proper grammar --------- Co-authored-by: Piotr Idzik <[email protected]>
1 parent 45edeb9 commit 2d2ffc4

File tree

1 file changed

+70
-77
lines changed

1 file changed

+70
-77
lines changed
Lines changed: 70 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,84 @@
1-
/// # Egg Dropping Puzzle
1+
//! This module contains the `egg_drop` function, which determines the minimum number of egg droppings
2+
//! required to find the highest floor from which an egg can be dropped without breaking. It also includes
3+
//! tests for the function using various test cases, including edge cases.
24
3-
/// `egg_drop(eggs, floors)` returns the least number of egg droppings
4-
/// required to determine the highest floor from which an egg will not
5-
/// break upon dropping
5+
/// Returns the least number of egg droppings required to determine the highest floor from which an egg will not break upon dropping.
66
///
7-
/// Assumptions: n > 0
8-
pub fn egg_drop(eggs: u32, floors: u32) -> u32 {
9-
assert!(eggs > 0);
10-
11-
// Explicity handle edge cases (optional)
12-
if eggs == 1 || floors == 0 || floors == 1 {
13-
return floors;
14-
}
15-
16-
let eggs_index = eggs as usize;
17-
let floors_index = floors as usize;
18-
19-
// Store solutions to subproblems in 2D Vec,
20-
// where egg_drops[i][j] represents the solution to the egg dropping
21-
// problem with i eggs and j floors
22-
let mut egg_drops: Vec<Vec<u32>> = vec![vec![0; floors_index + 1]; eggs_index + 1];
23-
24-
// Assign solutions for egg_drop(n, 0) = 0, egg_drop(n, 1) = 1
25-
for egg_drop in egg_drops.iter_mut().skip(1) {
26-
egg_drop[0] = 0;
27-
egg_drop[1] = 1;
28-
}
29-
30-
// Assign solutions to egg_drop(1, k) = k
31-
for j in 1..=floors_index {
32-
egg_drops[1][j] = j as u32;
7+
/// # Arguments
8+
///
9+
/// * `eggs` - The number of eggs available.
10+
/// * `floors` - The number of floors in the building.
11+
///
12+
/// # Returns
13+
///
14+
/// * `Some(usize)` - The minimum number of drops required if the number of eggs is greater than 0.
15+
/// * `None` - If the number of eggs is 0.
16+
pub fn egg_drop(eggs: usize, floors: usize) -> Option<usize> {
17+
if eggs == 0 {
18+
return None;
3319
}
3420

35-
// Complete solutions vector using optimal substructure property
36-
for i in 2..=eggs_index {
37-
for j in 2..=floors_index {
38-
egg_drops[i][j] = u32::MAX;
39-
40-
for k in 1..=j {
41-
let res = 1 + std::cmp::max(egg_drops[i - 1][k - 1], egg_drops[i][j - k]);
42-
43-
if res < egg_drops[i][j] {
44-
egg_drops[i][j] = res;
45-
}
46-
}
47-
}
21+
if eggs == 1 || floors == 0 || floors == 1 {
22+
return Some(floors);
4823
}
4924

50-
egg_drops[eggs_index][floors_index]
25+
// Create a 2D vector to store solutions to subproblems
26+
let mut egg_drops: Vec<Vec<usize>> = vec![vec![0; floors + 1]; eggs + 1];
27+
28+
// Base cases: 0 floors -> 0 drops, 1 floor -> 1 drop
29+
(1..=eggs).for_each(|i| {
30+
egg_drops[i][1] = 1;
31+
});
32+
33+
// Base case: 1 egg -> k drops for k floors
34+
(1..=floors).for_each(|j| {
35+
egg_drops[1][j] = j;
36+
});
37+
38+
// Fill the table using the optimal substructure property
39+
(2..=eggs).for_each(|i| {
40+
(2..=floors).for_each(|j| {
41+
egg_drops[i][j] = (1..=j)
42+
.map(|k| 1 + std::cmp::max(egg_drops[i - 1][k - 1], egg_drops[i][j - k]))
43+
.min()
44+
.unwrap();
45+
});
46+
});
47+
48+
Some(egg_drops[eggs][floors])
5149
}
5250

5351
#[cfg(test)]
5452
mod tests {
55-
use super::egg_drop;
56-
57-
#[test]
58-
fn zero_floors() {
59-
assert_eq!(egg_drop(5, 0), 0);
60-
}
61-
62-
#[test]
63-
fn one_egg() {
64-
assert_eq!(egg_drop(1, 8), 8);
65-
}
66-
67-
#[test]
68-
fn eggs2_floors2() {
69-
assert_eq!(egg_drop(2, 2), 2);
70-
}
71-
72-
#[test]
73-
fn eggs3_floors5() {
74-
assert_eq!(egg_drop(3, 5), 3);
75-
}
76-
77-
#[test]
78-
fn eggs2_floors10() {
79-
assert_eq!(egg_drop(2, 10), 4);
80-
}
81-
82-
#[test]
83-
fn eggs2_floors36() {
84-
assert_eq!(egg_drop(2, 36), 8);
53+
use super::*;
54+
55+
macro_rules! egg_drop_tests {
56+
($($name:ident: $test_cases:expr,)*) => {
57+
$(
58+
#[test]
59+
fn $name() {
60+
let (eggs, floors, expected) = $test_cases;
61+
assert_eq!(egg_drop(eggs, floors), expected);
62+
}
63+
)*
64+
}
8565
}
8666

87-
#[test]
88-
fn large_floors() {
89-
assert_eq!(egg_drop(2, 100), 14);
67+
egg_drop_tests! {
68+
test_no_floors: (5, 0, Some(0)),
69+
test_one_egg_multiple_floors: (1, 8, Some(8)),
70+
test_multiple_eggs_one_floor: (5, 1, Some(1)),
71+
test_two_eggs_two_floors: (2, 2, Some(2)),
72+
test_three_eggs_five_floors: (3, 5, Some(3)),
73+
test_two_eggs_ten_floors: (2, 10, Some(4)),
74+
test_two_eggs_thirty_six_floors: (2, 36, Some(8)),
75+
test_many_eggs_one_floor: (100, 1, Some(1)),
76+
test_many_eggs_few_floors: (100, 5, Some(3)),
77+
test_few_eggs_many_floors: (2, 1000, Some(45)),
78+
test_zero_eggs: (0, 10, None::<usize>),
79+
test_no_eggs_no_floors: (0, 0, None::<usize>),
80+
test_one_egg_no_floors: (1, 0, Some(0)),
81+
test_one_egg_one_floor: (1, 1, Some(1)),
82+
test_maximum_floors_one_egg: (1, usize::MAX, Some(usize::MAX)),
9083
}
9184
}

0 commit comments

Comments
 (0)