How can I simplify this horribly nested error handling code in Rust? - error-handling

I'm writing a function to compute a Summed Area Table of a Vec<Vec<isize>> in Rust, without the use of any external crates. I'm trying to learn to do this as idiomatically as possible, but I'm running into some roadblocks with error handling.
Basically all I'm trying to do is this, which is mentioned on the Wikipedia page:
The summed-area table can be computed efficiently in a single pass
over the image, as the value in the summed-area table at (x, y) is
just:
where i provides values from the grid, and I from the previously
computed values of the table. Obviously, if x or y is 0, then some of
these won't exist, in which case they are replaced with 0.
However, of note is the fact that if I(x, y - 1) does not exist even if y - 1 exists, then the grid we're working with is in fact non-rectangular, and we want to return an NonRectError in that case.
With all that background, here's the code: I need to protect against overflow errors from the subtractions, and return the NonRectError in the special case:
fn compute_summed_area_table(grid: &Vec<Vec<isize>>) -> Result<Vec<Vec<isize>>, NonRectError> {
let mut summed_area_table =
vec![Vec::with_capacity(grid[0].len()); grid.len()];
for (yi, row) in grid.iter().enumerate() {
for (xi, &value) in row.iter().enumerate() {
let (prev_row, prev_column_idx) = (
yi.checked_sub(1).and_then(|i| summed_area_table.get(i)),
xi.checked_sub(1)
);
let summed_values =
value +
// I(x, y - 1)
match prev_row {
None => &0,
Some(prev_row_vec) => match prev_row_vec.get(xi) {
Some(v) => v,
None => return Err(NonRectError { xi, yi })
}
} +
// I(x - 1, y)
(prev_column_idx
.and_then(|i| summed_area_table[yi].get(i))
.unwrap_or(&0)) -
// I(x - 1, y - 1)
(prev_row
.map_or(&0, |r| {
prev_column_idx
.and_then(|i| r.get(i))
.unwrap_or(&0)
}));
summed_area_table[yi].push(summed_values);
}
}
Ok(summed_area_table)
}
// Omitted the definition of NonRectError here, but it is defined.
This code is clearly the definition of sin itself, but I'm not sure which angle to approach simplifying this from - there are so many gosh darn edge cases!
Are there any built-in methods that'll allow me to escape this nested error-checking stuff? Can I return the NonRectError in some easier way than this?

Here are some things you can try:
Use an array, not nested Vecs. With an array, you can guarantee that all the rows have the same width, and NonRectError can't happen. (But maybe you have good reasons to use nested Vecs, so the rest of my examples use nested Vecs.)
The block where you calculate summed_value is pretty long. I'd break it up like this:
// I(x, y - 1)
let north = ...;
// I(x - 1, y)
let west = ...;
// I(x - 1, y - 1)
let northwest = ...;
let summed_values = value + north + west - northwest;
Instead of checked subtraction, it's easier to check if xi and yi are nonzero. Also, .ok_or() is a good way to convert None to an error.
let northwest = match (xi, yi) {
(0, _) => 0,
(_, 0) => 0,
(_, _) => {
// We know xi and yi are nonzero, so we can subtract without checks
summed_area_table.get(yi - 1)
.and_then(|row| row.get(xi - 1))
.ok_or(NonRectError { xi, yi })?
}
};
You could also write that with an if/else chain. They're both idiomatic, it's just a matter of preference. I prefer match because it feels more concise.
let northwest = if xi == 0 {
0
} else if yi == 0 {
0
} else {
// same as above
};

Related

How to identify time and space complexity of recursive backtracking algorithms with step-by-step analysis

Background Information: I solved the N-Queens problem with the C# algorithm below, which returns the total number of solutions given the board of size n x n. It works, but I do not understand why this would be O(n!) time complexity, or if it is a different time complexity. I am also unsure of the space used in the recursion stack (but am aware of the extra space used in the boolean jagged array). I cannot seem to wrap my mind around understanding the time and space complexity of such solutions. Having this understanding would be especially useful during technical interviews, for complexity analysis without the ability to run code.
Preliminary Investigation: I have read several SO posts where the author directly asks the community to provide the time and space complexity of their algorithms. Rather than doing the same and asking for the quick and easy answers, I would like to understand how to calculate the time and space complexity of backtracking algorithms so that I can do so moving forward.
I have also read in numerous locations within and outside of SO that generally, recursive backtracking algorithms are O(n!) time complexity since at each of the n iterations, you look at one less item: n, then n - 1, then n - 2, ... 1. However, I have not found any explanation as to why this is the case. I also have not found any explanation for the space complexity of such algorithms.
Question: Can someone please explain the step-by-step problem-solving approach to identify time and space complexities of recursive backtracking algorithms such as these?
public class Solution {
public int NumWays { get; set; }
public int TotalNQueens(int n) {
if (n <= 0)
{
return 0;
}
NumWays = 0;
bool[][] board = new bool[n][];
for (int i = 0; i < board.Length; i++)
{
board[i] = new bool[n];
}
Solve(n, board, 0);
return NumWays;
}
private void Solve(int n, bool[][] board, int row)
{
if (row == n)
{
// Terminate since we've hit the bottom of the board
NumWays++;
return;
}
for (int col = 0; col < n; col++)
{
if (CanPlaceQueen(board, row, col))
{
board[row][col] = true; // Place queen
Solve(n, board, row + 1);
board[row][col] = false; // Remove queen
}
}
}
private bool CanPlaceQueen(bool[][] board, int row, int col)
{
// We only need to check diagonal-up-left, diagonal-up-right, and straight up.
// this is because we should not have a queen in a later row anywhere, and we should not have a queen in the same row
for (int i = 1; i <= row; i++)
{
if (row - i >= 0 && board[row - i][col]) return false;
if (col - i >= 0 && board[row - i][col - i]) return false;
if (col + i < board[0].Length && board[row - i][col + i]) return false;
}
return true;
}
}
First of all, it's definitely not true that recursive backtracking algorithms are all in O(n!): of course it depends on the algorithm, and it could well be worse. Having said that, the general approach is to write down a recurrence relation for the time complexity T(n), and then try to solve it or at least characterize its asymptotic behaviour.
Step 1: Make the question precise
Are we interested in the worst-case, best-case or average-case? What are the input parameters?
In this example, let us assume we want to analyze the worst-case behaviour, and the relevant input parameter is n in the Solve method.
In recursive algorithms, it is useful (though not always possible) to find a parameter that starts off with the value of the input parameter and then decreases with every recursive call until it reaches the base case.
In this example, we can define k = n - row. So with every recursive call, k is decremented starting from n down to 0.
Step 2: Annotate and strip down the code
No we look at the code, strip it down to just the relevant bits and annotate it with complexities.
We can boil your example down to the following:
private void Solve(int n, bool[][] board, int row)
{
if (row == n) // base case
{
[...] // O(1)
return;
}
for (...) // loop n times
{
if (CanPlaceQueen(board, row, col)) // O(k)
{
[...] // O(1)
Solve(n, board, row + 1); // recurse on k - 1 = n - (row + 1)
[...] // O(1)
}
}
}
Step 3: Write down the recurrence relation
The recurrence relation for this example can be read off directly from the code:
T(0) = 1 // base case
T(k) = k * // loop n times
(O(k) + // if (CanPlaceQueen(...))
T(k-1)) // Solve(n, board, row + 1)
= k T(k-1) + O(k)
Step 4: Solve the recurrence relation
For this step, it is useful to know a few general forms of recurrence relations and their solutions. The relation above is of the general form
T(n) = n T(n-1) + f(n)
which has the exact solution
T(n) = n!(T(0) + Sum { f(i)/i!, for i = 1..n })
which we can easily prove by induction:
T(n) = n T(n-1) + f(n) // by def.
= n((n-1)!(T(0) + Sum { f(i)/i!, for i = 1..n-1 })) + f(n) // by ind. hypo.
= n!(T(0) + Sum { f(i)/i!, for i = 1..n-1 }) + f(n)/n!)
= n!(T(0) + Sum { f(i)/i!, for i = 1..n }) // qed
Now, we don't need the exact solution; we just need the asymptotic behaviour when n approaches infinity.
So let's look at the infinite series
Sum { f(i)/i!, for i = 1..infinity }
In our case, f(n) = O(n), but let's look at the more general case where f(n) is an arbitary polynomial in n (because it will turn out that it really doesn't matter). It is easy to see that the series converges, using the ratio test:
L = lim { | (f(n+1)/(n+1)!) / (f(n)/n!) |, for n -> infinity }
= lim { | f(n+1) / (f(n)(n+1)) |, for n -> infinity }
= 0 // if f is a polynomial
< 1, and hence the series converges
Therefore, for n -> infinity,
T(n) -> n!(T(0) + Sum { f(i)/i!, for i = 1..infinity })
= T(0) n!, if f is a polynomial
Step 5: The result
Since the limit of T(n) is T(0) n!, we can write
T(n) ∈ Θ(n!)
which is a tight bound on the worst-case complexity of your algorithm.
In addition, we've proven that it doesn't matter how much work you do within the for-loop in adddition to the recursive calls, as long as it's polynomial, the complexity stays Θ(n!) (for this form of recurrence relations). (In bold because there are lots of SO answers that get this wrong.)
For a similar analysis with a different form of recurrence relation, see here.
Update
I made a mistake in the annotation of the code (I'll leave it because it is still instructive). Actually, both the loop and the work done within the loop do not depend on k = n - row but on the initial value n (let's call it n0 to make it clear).
So the recurrence relation becomes
T(k) = n0 T(k-1) + n0
for which the exact solution is
T(k) = n0^k (T(0) + Sum { n0^(1-i), for i = 1..k })
But since initially n0 = k, we have
T(k) = k^k (T(0) + Sum { n0^(1-i), for i = 1..k })
∈ Θ(k^k)
which is a bit worse than Θ(k!).

Iterate over copy types

It is clear that iterators pass around a references to avoid moving objects into iterator or it's closure argument, but what with Copy types? Let me show you a small snippet:
fn is_odd(x: &&i32) -> bool { *x & 1 == 1 }
// [1] fn is_odd(x: &i32) -> bool { x & 1 == 1 }
// [2] fn is_odd(x: i32) -> bool { x & 1 == 1 }
fn main() {
let xs = &[ 10, 20, 13, 14 ];
for x in xs.iter().filter(is_odd) {
assert_eq!(13, *x);
}
// [1] ...is slightly better, but not ideal
// for x in xs.iter().cloned().filter(is_odd) {
// assert_eq!(13, x);
// }
}
Am I right that .cloned() is preferred when we iterate over something like &[i32] or &[u8], where extra indirection is involved instead of just copying the tiny data unit?
But it looks like I can not avoid references passed into is_odd function.
Is there a way to make [2] function from above snippet work for higher-level functions like filter?
Assume that I understand that moving non-Copy type into predicate function is silly. But not all types use move semantics by default, right?
It is clear that iterators pass around a references
This blanket statement is not true, iterators are more than capable of yielding a non-reference. filter will provide a reference to the closure because it doesn't want to give ownership of the item to the closure. In your example, your iterated value is a &i32, and then filter provides a &&i32.
Is there a way to make [2] function from above snippet work for higher-level functions like filter?
Certainly, just provide a closure that does the dereferencing:
fn is_odd(x: i32) -> bool { x & 1 == 1 }
fn main() {
let xs = &[ 10, 20, 13, 14 ];
for x in xs.iter().filter(|&&x| is_odd(x)) {
assert_eq!(13, *x);
}
}

Using an iterator, how do I skip a number of values and then display the rest?

Random access to the elements is not allowed.
let vec = vec![1,2,3,4,5,6,7,8,9,0];
let n = 3;
for v in vec.iter().rev().take(n) {
println!("{}", v);
}
// this printed: 0, 9, 8
// need: 8, 9, 0
for v in vec.iter().rev().skip(n).rev() does not work.
I think the code you wrote does what you're asking it to.
You are reversing the vec with rev() and then you're taking the first 3 elements of the reversed vector (therefore 0, 9, 8)
To obtain the last 3 in non-reversed order you can skip to the end of the vector minus 3 elements, without reversing it:
let vec = vec![1,2,3,4,5,6,7,8,9,0];
let n = vec.len() - 3;
for v in vec.iter().skip(n) {
println!("{}", v);
}
Neither skip nor take yield DoubleEndIterator, you have to either:
skip, which is O(N) in the number of skipped items
collect the result of .rev().take(), and then rev it, which is O(N) in the number of items to be printed, and requires allocating memory for them
The skip is obvious, so let me illustrate the collect:
let vec = vec![1,2,3,4,5,6,7,8,9,0];
let vec: Vec<_> = vec.iter().rev().take(3).collect();
for v in vec.iter().rev() {
println!("{}", v);
}
Of course, the inefficiency is due to you shooting yourself in the foot by avoiding random access in the first place...
Based on the comments, I guess you want to iterate specifically through the elements of a Vec or slice. If that is the case, you could use range slicing, as shown below:
let vec = vec![1,2,3,4,5,6,7,8,9,0];
let n = vec.len() - 3;
for v in &vec[n..] {
println!("{}", v);
}
The big advantage of this approach is that it doesn't require to skip through elements you are not interested in (which may have a big cost if not optimized away). It will just make a new slice and then iterate through it. In other words, you have the guarantee that it will be fast.

Conflicting lifetime requirement for iterator returned from function

This may be a duplicate. I don't know. I couldn't understand the other answers well enough to know that. :)
Rust version: rustc 1.0.0-nightly (b47aebe3f 2015-02-26) (built 2015-02-27)
Basically, I'm passing a bool to this function that's supposed to build an iterator that filters one way for true and another way for false. Then it kind of craps itself because it doesn't know how to keep that boolean value handy, I guess. I don't know. There are actually multiple lifetime problems here, which is discouraging because this is a really common pattern for me, since I come from a .NET background.
fn main() {
for n in values(true) {
println!("{}", n);
}
}
fn values(even: bool) -> Box<Iterator<Item=usize>> {
Box::new([3usize, 4, 2, 1].iter()
.map(|n| n * 2)
.filter(|n| if even {
n % 2 == 0
} else {
true
}))
}
Is there a way to make this work?
You have two conflicting issues, so let break down a few representative pieces:
[3usize, 4, 2, 1].iter()
.map(|n| n * 2)
.filter(|n| n % 2 == 0))
Here, we create an array in the stack frame of the method, then get an iterator to it. Since we aren't allowed to consume the array, the iterator item is &usize. We then map from the &usize to a usize. Then we filter against a &usize - we aren't allowed to consume the filtered item, otherwise the iterator wouldn't have it to return!
The problem here is that we are ultimately rooted to the stack frame of the function. We can't return this iterator, because the array won't exist after the call returns!
To work around this for now, let's just make it static. Now we can focus on the issue with even.
filter takes a closure. Closures capture any variable used that isn't provided as an argument to the closure. By default, these variables are captured by reference. However, even is again a variable located on the stack frame. This time however, we can give it to the closure by using the move keyword. Here's everything put together:
fn main() {
for n in values(true) {
println!("{}", n);
}
}
static ITEMS: [usize; 4] = [3, 4, 2, 1];
fn values(even: bool) -> Box<Iterator<Item=usize>> {
Box::new(ITEMS.iter()
.map(|n| n * 2)
.filter(move |n| if even {
n % 2 == 0
} else {
true
}))
}

Should there be an indicesWhere method on Scala's List class?

Scala's List classes have indexWhere methods, which return a single index for a List element which matches the supplied predicate (or -1 if none exists).
I recently found myself wanting to gather all indices in a List which matched a given predicate, and found myself writing an expression like:
list.zipWithIndex.filter({case (elem, _) => p(elem)}).map({case (_, index) => index})
where p here is some predicate function for selecting matching elements. This seems a bit of an unwieldy expression for such a simple requirement (but I may be missing a trick or two).
I was half expecting to find an indicesWhere function on List which would allow me to write instead:
list.indicesWhere(p)
Should something like this be part of the Scala's List API, or is there a much simpler expression than what I've shown above for doing the same thing?
Well, here's a shorter expression that removes some of the syntactic noise you have in yours (modified to use Travis's suggestion):
list.zipWithIndex.collect { case (x, i) if p(x) => i }
Or alternatively:
for ((x,i) <- list.zipWithIndex if p(x)) yield i
But if you use this frequently, you should just add it as an implicit method:
class EnrichedWithIndicesWhere[T, CC[X] <: Seq[X]](xs: CC[T]) {
def indicesWhere(p: T => Boolean)(implicit bf: CanBuildFrom[CC[T], Int, CC[Int]]): CC[Int] = {
val b = bf()
for ((x, i) <- xs.zipWithIndex if p(x)) b += i
b.result
}
}
implicit def enrichWithIndicesWhere[T, CC[X] <: Seq[X]](xs: CC[T]) = new EnrichedWithIndicesWhere(xs)
val list = List(1, 2, 3, 4, 5)
def p(i: Int) = i % 2 == 1
list.indicesWhere(p) // List(0, 2, 4)
You could use unzip to replace the map:
list.zipWithIndex.filter({case (elem, _) => p(elem)}).unzip._2