Homework/Hacks for Sections 17-18
Homework/Hacks for Sections 17-18
- Notes:
- Vocab:
- HACK 1
- HACK 2
- HACK 3: Rewrite this JavaScript Code in a More Efficient Way (Hint: Use Binary Search)
- Rewritten Code:
- Hack 3 Reflection:
Notes:
- An algorithm can be made more efficient by reducing the number of steps needed to accomplish the task
- This is why different correct algorithms for the same problem can have different efficiencies
- A way to informally measure an algorithm's efficiency is by determining the number of times a statement or group of statements executes
- Approximate solutions are found when problems cannot be solved in a reasonable amount of time because there is no efficient algorithm for solving them
- It is possible for there to be some solutions to an input of an undecidable problem
Vocab:
- Four Types of Algorithms:
- 1 Step: An integer being multiplied by a variable
- 2 Step: An integer to the power of the variable
- 3 Step: A variable multiplied by an integer, all raised to the power of 2
- 4 Step: A variable factorial
- Decidable Problems: Problems for which algorithms could be written to solve/produce a correct output for all inputs.
- Undecidable Problems: Problems for which no algorithms can be built that can provide a correct yes or no answer or a solution
- Constant Time: Algorithm that always takes a fixed number of steps, no matter how large the input size increases
- Linear Time: Algorithm in which the number of steps increases in direct proportion to the input size
- Quadratic Time: Algorithm where the number of steps increase in proportion to the input size squared
- Exponential Time: Algorithm where the number of steps increases faster than a polynomial function of the input size
- Polynomial Time: Any run time that does not increase faster than n^k
- Superpolynomial Time: Any run time that does increase faster than n^k
- Reasonable Time: Algorithms with a polynomial efficiency or lower (constant, linear, square, cube, etc.)
- Unreasonable Time: Algorithms with exponential or factorial efficiencies
Please write a short 1-2 sentence explanation describing the difference between decidable and undecidable problems. Make sure to provide at least one example of each.
Decidable Problem: Decidable problems are problems for which algorithms can be written to produce an output for all possible inputs.
Example:
a = True
if a == True:
print("hello")
else:
print("bye")
Undecidable Problem: Undecidable problems are problems for which no algorithm can be built that can provide a correct yes or no answer. It is possible for there to be some algorithmic solutions for some inputs of an undecidable problem.
Example (Halting Problem):
def haltingProblem():
a = 0
x = 1
while a != 1:
x = x + 1
print(x)
haltingProblem()
Which of the following is a 3 step algorithm?
A. 2 x 6 x 8
B. 4^5
C. (3 x 8)^2
D. None of the above
E. All of the above
☆ My answer: The correct answer is C. This is because a 3 step algorithm needs to have an integer variable multiplied by another integer which is all raised to the power of 2 and (3 x 8)^2 meets these requirements.
function peak_finder(array){
let counter = 0
let peak = 0
let peak_index =0
while (counter <= array.length){
console.log(counter)
if (counter === 0){
if (a[0]>=a[1]){
peak = a[0]
peak_index = counter
counter = array.length
return `The ${counter-1} indexed number, ${peak} is a peak`
}else{
counter+=1
}
}else if(counter === array.length-1){
if (a[array.length-1] >= a[array.length-2]){
peak = a[array.length-1]
peak_index = counter
counter = array.length
return `The ${counter-1} indexed number, ${peak} is a peak`
}
}else{
if (a[counter]> a[counter+1] && a[counter]> a[counter-1]){
peak = a[counter]
peak_index = counter
counter = array.length
return `The ${counter-1} indexed number, ${peak} is a peak`
}else{
counter += 1
}
}
}
}
function peak_finder(list) {
var peak = list[0];
for (i = 0; i < list.length; i ++) {
if (list[i] > peak) {
var peak = list[i];
}
}
return peak; # after all comparisons, returns highest value in list
}
var data = [5, 2, 3, 4, 9];
console.log(peak_finder(data)); # prints highest number in list (9)
Hack 3 Reflection:
This hack was a little confusing because I wasn't sure how to use binary search to make the code more efficient. Instead, since I'm pretty sure the code is supposed to find the highest number in a list, I made code that compares elements in the list to each other to determine the highest value in the list.
def merge_sort(data):
if len(data) <= 1:
return
mid = len(data) // 2
left_data = data[:mid]
right_data = data[mid:]
merge_sort(left_data)
merge_sort(right_data)
left_index = 0
right_index = 0
data_index = 0
while left_index < len(left_data) and right_index < len(right_data):
if left_data[left_index] < right_data[right_index]:
data[data_index] = left_data[left_index]
left_index += 1
else:
data[data_index] = right_data[right_index]
right_index += 1
data_index += 1
if left_index < len(left_data):
del data[data_index:]
data += left_data[left_index:]
elif right_index < len(right_data):
del data[data_index:]
data += right_data[right_index:]
if __name__ == '__main__':
data = [9, 1, 7, 6, 2, 8, 5, 3, 4, 0]
merge_sort(data)
print(data)
data = [9, 1, 7, 6, 2, 8, 5, 3, 4, 0]
data.sort() # sort function orders the data from least to greatest
print("Sorted List:", data)
def heap_permutation(data, n):
if n == 1:
print(data)
return
for i in range(n):
heap_permutation(data, n - 1)
if n % 2 == 0:
data[i], data[n-1] = data[n-1], data[i]
else:
data[0], data[n-1] = data[n-1], data[0]
if __name__ == '__main__':
data = [1, 2, 3]
heap_permutation(data, len(data))
from itertools import permutations
data = [1, 2, 3]
allPermutations = permutations(data)
for i in list(allPermutations):
print (i) # prints all the permutations
if __name__ == '__main__':
abc = ["a", "b", "c"]
heap_permutation(abc, len(abc))
from itertools import permutations
abc = ["a", "b", "c"]
abcPermutations = permutations(abc)
for i in list(abcPermutations):
print (i)