8.17 Exercises
Click to see the list of suggested exercises
-
Maximum Function Variants
-
Variant 1: Write a function
max_i32
that takes twoi32
parameters by value and returns the maximum value.fn max_i32(a: i32, b: i32) -> i32 { if a > b { a } else { b } } fn main() { let result = max_i32(3, 7); println!("The maximum is {}", result); // Output: The maximum is 7 }
-
Variant 2: Write a function
max_ref
that takes references (&i32
) to twoi32
values and returns a reference (&i32
) to the maximum value. Pay attention to lifetimes.// The lifetime 'a indicates that the returned reference is tied to the shortest // lifetime of the input references 'a' and 'b'. fn max_ref<'a>(a: &'a i32, b: &'a i32) -> &'a i32 { if a > b { a } else { b } } fn main() { let x = 5; let y = 10; let result_ref = max_ref(&x, &y); println!("The maximum reference points to: {}", result_ref); // Output: 10 // *result_ref is 10. result_ref is valid as long as x and y are. }
-
Variant 3: Write a single generic function
max_generic
that works with any typeT
that can be compared (PartialOrd
) and copied (Copy
). Test it withi32
andf64
.use std::cmp::PartialOrd; use std::marker::Copy; // Often implicitly required by usage, good to be explicit fn max_generic<T: PartialOrd + Copy>(a: T, b: T) -> T { if a > b { a } else { b } } fn main() { let int_max = max_generic(3, 7); let float_max = max_generic(2.5, 1.8); println!("The maximum integer is {}", int_max); // Output: 7 println!("The maximum float is {}", float_max); // Output: 2.5 }
-
-
String Concatenation Write a function
concat_strings
that takes two string slices (&str
) as input and returns a newly allocatedString
containing the concatenation of the two.fn concat_strings(s1: &str, s2: &str) -> String { let mut result = String::with_capacity(s1.len() + s2.len()); // Pre-allocate cap. result.push_str(s1); result.push_str(s2); result // Return the new owned String } fn main() { let greeting = "Hello, "; let name = "Rustacean!"; let combined = concat_strings(greeting, name); println!("{}", combined); // Output: Hello, Rustacean! }
-
Distance Calculation Define a function
distance
that takes two points as tuples(f64, f64)
representing (x, y) coordinates, and returns the Euclidean distance between them as anf64
. Recall distance = sqrt((x2-x1)^2 + (y2-y1)^2).fn distance(p1: (f64, f64), p2: (f64, f64)) -> f64 { let dx = p2.0 - p1.0; let dy = p2.1 - p1.1; (dx.powi(2) + dy.powi(2)).sqrt() // Use powi(2) for squaring, then sqrt() } fn main() { let point_a = (0.0, 0.0); let point_b = (3.0, 4.0); let dist = distance(point_a, point_b); println!("Distance between {:?} and {:?} is {}", point_a, point_b, dist); // 5.0 }
-
Array Reversal In-Place Write a function
reverse_slice
that takes a mutable slice ofi32
(&mut [i32]
) and reverses the order of its elements in place (without creating a new array or vector).fn reverse_slice(slice: &mut [i32]) { let len = slice.len(); if len == 0 { return; } // Handle empty slice let mid = len / 2; for i in 0..mid { // Swap element i with element len - 1 - i slice.swap(i, len - 1 - i); } } fn main() { let mut data1 = [1, 2, 3, 4, 5]; reverse_slice(&mut data1); println!("Reversed data1: {:?}", data1); // Output: [5, 4, 3, 2, 1] let mut data2 = [10, 20, 30, 40]; reverse_slice(&mut data2); println!("Reversed data2: {:?}", data2); // Output: [40, 30, 20, 10] let mut data3: [i32; 0] = []; // Empty slice reverse_slice(&mut data3); println!("Reversed empty: {:?}", data3); // Output: [] }
-
Find Element in Slice Write a function
find_index
that takes a slice ofi32
(&[i32]
) and a targeti32
value. It should returnOption<usize>
, containingSome(index)
if the target is found, andNone
otherwise. Return the index of the first occurrence.fn find_index(slice: &[i32], target: i32) -> Option<usize> { for (index, &value) in slice.iter().enumerate() { if value == target { return Some(index); // Found it, return early } } None // Went through the whole slice, not found } fn main() { let numbers = [10, 25, 30, 15, 25, 40]; match find_index(&numbers, 30) { Some(idx) => println!("Found 30 at index {}", idx), // Output: Found 30 at index 2 None => println!("30 not found"), } match find_index(&numbers, 25) { Some(idx) => println!("Found 25 at index {}", idx), // Output: Found 25 at index 1 (first occurrence) None => println!("25 not found"), } match find_index(&numbers, 99) { Some(idx) => println!("Found 99 at index {}", idx), None => println!("99 not found"), // Output: 99 not found } }