This commit is contained in:
ridethepig 2023-02-23 07:31:06 +00:00
parent 6291739e3f
commit 65fe3e800b
3 changed files with 82 additions and 21 deletions

View File

@ -9,8 +9,9 @@ fn main() {
println!("{}", ref3.to_uppercase());
}
```
Answer:
This code won't compile. Reference to mutable variable 's' is used later, so it shouldn't change before all borrows are returned to 's'.
If the 'println' is set above assignment of 's', it should be ok.
Example 2:
```
@ -20,6 +21,8 @@ fn drip_drop() -> &String {
}
```
Answer:
This code won't compile. It returns a reference, but when the function leaves, the owner will be dropped, the refernece becomes dangling, this is unacceptable.
Example 3:
@ -32,3 +35,7 @@ fn main() {
println!("{}", s2);
}
```
Answer:
The ownership is transfered to `v` after push, that's good.
However, `let s2 = v[0]` requires for a ownership move(or Copy trait which String doesnt have), but 'Index operator []' returns a reference(&self::Output), so it couldn't been moved.

View File

@ -30,18 +30,25 @@ impl Grid {
/// but others argue that makes code needlessly complex. Here, we decided to return Option to
/// give you more practice with Option :) and because this similar library returns Option:
/// https://docs.rs/array2d/0.2.1/array2d/struct.Array2D.html
#[allow(unused)] // TODO: delete this line when you implement this function
pub fn get(&self, row: usize, col: usize) -> Option<usize> {
unimplemented!();
// Be sure to delete the #[allow(unused)] line above
if row >= self.num_rows || col >= self.num_cols {
None
}
else {
Some(self.elems[row * self.num_cols + col])
}
}
/// Sets the element at the specified location to the specified value. If the location is out
/// of bounds, returns Err with an error message.
#[allow(unused)] // TODO: delete this line when you implement this function
pub fn set(&mut self, row: usize, col: usize, val: usize) -> Result<(), &'static str> {
unimplemented!();
// Be sure to delete the #[allow(unused)] line above
if row >= self.num_rows || col >= self.num_cols {
Err("Outof Boundry")
}
else {
self.elems[row * self.num_cols + col] = val;
Ok(())
}
}
/// Prints a visual representation of the grid. You can use this for debugging.

View File

@ -7,30 +7,74 @@ use std::process;
pub mod grid;
/// Reads the file at the supplied path, and returns a vector of strings.
#[allow(unused)] // TODO: delete this line when you implement this function
fn read_file_lines(filename: &String) -> Result<Vec<String>, io::Error> {
unimplemented!();
// Be sure to delete the #[allow(unused)] line above
let file = File::open(filename)?;
let mut lines = Vec::new();
for line in io::BufReader::new(file).lines() {
lines.push(line.unwrap());
}
Ok(lines)
}
fn max<T: PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
}
#[allow(unused)] // TODO: delete this line when you implement this function
fn lcs(seq1: &Vec<String>, seq2: &Vec<String>) -> Grid {
// Note: Feel free to use unwrap() in this code, as long as you're basically certain it'll
// never happen. Conceptually, unwrap() is justified here, because there's not really any error
// condition you're watching out for (i.e. as long as your code is written correctly, nothing
// external can go wrong that we would want to handle in higher-level functions). The unwrap()
// calls act like having asserts in C code, i.e. as guards against programming error.
unimplemented!();
// Be sure to delete the #[allow(unused)] line above
let m = seq1.len();
let n = seq2.len();
let mut dp = Grid::new(m + 1, n + 1);
for i in 0..m + 1 {
dp.set(i, 0, 0).unwrap();
}
for j in 0..n + 1 {
dp.set(0, j, 0).unwrap();
}
for i in 0..m {
for j in 0..n {
if seq1[i] == seq2[j] {
dp.set(i + 1, j + 1, dp.get(i, j).unwrap() + 1).unwrap();
} else {
dp.set(
i + 1,
j + 1,
max(dp.get(i + 1, j).unwrap(), dp.get(i, j + 1).unwrap()),
)
.unwrap();
}
}
}
dp
}
#[allow(unused)] // TODO: delete this line when you implement this function
fn print_diff(lcs_table: &Grid, lines1: &Vec<String>, lines2: &Vec<String>, i: usize, j: usize) {
unimplemented!();
// Be sure to delete the #[allow(unused)] line above
if i > 0 && j > 0 && lines1[i - 1] == lines2[j - 1] {
// found the same line
print_diff(lcs_table, lines1, lines2, i - 1, j - 1);
println!(" {}", lines1[i - 1])
} else if j > 0
&& (i == 0 || lcs_table.get(i, j - 1).unwrap() >= lcs_table.get(i -1, j).unwrap())
{
// walk back along lines2, because it is a string out of LCS.
print_diff(lcs_table, lines1, lines2, i, j - 1);
println!("> {}", lines2[j - 1])
} else if i > 0
&& (j == 0 || lcs_table.get(i, j - 1).unwrap() < lcs_table.get(i - 1, j).unwrap())
{
print_diff(lcs_table, lines1, lines2, i - 1, j);
println!("< {}", lines1[i - 1])
}
}
#[allow(unused)] // TODO: delete this line when you implement this function
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 3 {
@ -39,9 +83,12 @@ fn main() {
}
let filename1 = &args[1];
let filename2 = &args[2];
unimplemented!();
// Be sure to delete the #[allow(unused)] line above
let content1 =
read_file_lines(filename1).expect(format!("Cannot read file {}", filename1).as_str());
let content2 =
read_file_lines(filename2).expect(format!("Cannot read file {}", filename2).as_str());
let lsc_grid = lcs(&content1, &content2);
print_diff(&lsc_grid, &content1, &content2, content1.len(), content2.len());
}
#[cfg(test)]