Quick Index
Algorithm Rough Draft


It may be helpful to jot down a quick "rough draft" of an algorithm to help get started.

For example, for the "indexOf(anElem)" method in this chapter something as simple as this:

Loop through our elements until we find a match
Return the index of the match

Object Universe 💡


Before starting on our algorithms, it is key to get familiar with the context or "object universe" for the given problem, which may may any number of classes including the "subject" class (i.e. 'this')

Reuse and Helper Algorithms


Overview


Helper algorithms (or "helper methods") just means any other algorithms we call from the one we are working on.

We previously wrote an algorithm for "Making Tomato Sandwiches". One possibility for that algorithm was to call another algorithm named "Make Toast". That way the caller is simplified.

Pseudocode Example


Let's say we are writing the algorithm (p-code) for the method "findClosestToEnd".

The method header is shown to the right.

Remember, we are coding in a MyArray object -- so it is part of our context (environment).
findClosestToEnd(compareFct) {
	//ALGORITHM HERE
}
First we'll just scribble out a quick "rough" algo in any human language for the purpose is just helping us get going with pseudocode.

Note for the two searches we use the arg "compareFct" that is provided to the algorithm.
findClosestToEnd(compareFct) {
	firstIndex = get index of first (left) end of array
	lastIndex = get index of last (right) end of array
	firstMatchingIndex	= search for first matching elem (index)
	lastMatchingIndex = search for last matching elem (index)
	leftDistance = distance from firstIndex to the firstMatchingIndex
	rightDistance = distance from lastMatchingIndex to the lastIndex
}
Algos are all about iteration. Here is our second, improved, scribble of our "human" algorithm.

We can see that four of the steps require only simple math.

But the other two steps (searches) are going to require some serious work.
findClosestToEnd(compareFct) {
	firstIndex = 0
	lastIndex = this.length - 1
	firstMatchingIndex	= search for first matching elem (index)
	lastMatchingIndex = search for last matching elem (index)
	leftDistance = firstMatchingIndex - firstIndex
	rightDistance = lastIndex - lastMatchingIndex
}
But wait! What is our context/scope? What other objects and algorithms (methods) do we have available?

We know have "MyArray" (the object we are coding in -- i.e. "this").

The question is, does it provide a method(s) that will help us with the searches?
	firstMatchingIndex = search for first matching element (index) using compareFct
	lastMatchingIndex = search for last matching element (index) using compareFct
Browsing a MyArray listing, we see an algorithm (method) named findIndex

If we read about that algorithm, we learn it does exactly what we need for our search to find the first matching index.

We should also look for something similar for finding the last matching index.
MyArray algorithms (methods) menu:
If we do not find a algorithm (method) that will do the job we may still consider adding a helper algorithm to make our current algorithm simpler.

Simplify with the Return Statement


Overview


A coder's favorite word: simplify

We'll demo how a basic return statement can be used to simplify code.

Example


In this example we'll use pseudocode for the logic to determine if a number is prime.

We'll call the algorithm "isPrime".

We'll start an algorithm that favors variables and only has one return statement at end of logic.

We'll then simplify the method by adding simple return statements.

Demo


One Return Statement at End of Logic
Here we take the approach of keeping a "result" variable.

We can work to get this to give the correct results.

However, the logic is complex. This is a welcoming environment for bugs.

Also, as we'll learn below, that this is very inefficient.

Generally coders try to shy away from deep, nested bracing.
static isPrime(n) {
	let result;
	if (n <= 1) {
		result = false;
	} else {
		if (n == 2) {
			result = true;
		} else {
			if (n % 2 == 0) {
				result = false;
			} else {
				if (n <= 7) {
					result = true;
				} else {
					result = true
					let max = Math.sqrt(n)
					let factor = 3
					while (factor <= max) {
						if (n % factor == 0) {
							result = false;
						}
						factor += 2;
					}
				}
			}
		}
	}
	return result;
}
Simplified with Return Statements
The main things that we do differently in this try are:

  • Look for special conditions at the start of the logic and return when they are found
  • When we find the result (e.g., when we find a factor, we return immediately

Benefits:

  • The code is so much simpler. The main logic is now just a very short while loop.
  • Much more efficient than the previous because when a result is known it is returned and the logic ends its work.
static isPrime(n) {
	// Special Cases
	if (n <= 1) return false;
	if (n == 2) return true;
	if (n % 2 == 0) return false;
	if (n <= 7) return true;
	let max = Math.sqrt(n)
	let factor = 3
	// "Return" if we find result
	while (factor <= max) {
		if (n % factor == 0)
			return false;
		factor += 2;
	}
	return true;
}
Side-by-Side Comparison
One Return Statement at End of Logic
static isPrime(n) {
	let result;
	if (n <= 1) {
		result = false;
	} else {
		if (n == 2) {
			result = true;
		} else {
			if (n % 2 == 0) {
				result = false;
			} else {
				if (n <= 7) {
					result = true;
				} else {
					result = true
					let max = Math.sqrt(n)
					let factor = 3
					while (factor <= max) {
						if (n % factor == 0) {
							result = false;
						}
						factor += 2;
					}
				}
			}
		}
	}
	return result;
}



Simplified with Return Statements
static isPrime(n) {
	// Special Cases
	if (n <= 1) return false;
	if (n == 2) return true;
	if (n % 2 == 0) return false;
	if (n <= 7) return true;
	let max = Math.sqrt(n)
	let factor = 3
	// "Return" if we find result
	while (factor <= max) {
		if (n % factor == 0)
			return false;
		factor += 2;
	}
	return true;
}

Mapping Algorithms to Code


Mapping Algorithm to Code


Algorithms usually map nicely to program code. Here is an example where we can see that the mapping is mostly a matter of
polishing on the language syntax.

Example
Algorithm:
z = 1
while (n < 10)
	print ("n is: " + n)
	increment n
finish()

Program Code:
z = 1;
while (n < 10) {
	System.out.println("n is: " + n);
	n++;
}
finish();