From 3fe14b8ac0072cd03cdf6bf136c905242aba90cd Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Tue, 6 Feb 2024 21:53:17 +0000 Subject: [PATCH] clean up repo. add more notes --- .gitignore | 4 +++- chapter1/README.md | 5 +++++ chapter1/binary.py | 13 ++++++++----- chapter1/ex1.1.py | 7 ------- chapter1/ex1.2.py | 7 ------- chapter2/README.md | 7 +++++++ chapter4/README.md | 12 ++++++++++++ chapter4/binary.py | 10 +++++++--- chapter6/README.md | 9 +++++++++ chapter9/README.md | 2 +- chapter9/examples/heaptest.py | 10 ---------- chapter9/examples/list.py | 14 -------------- chapter9/examples/priorityqueuetest.py | 12 ------------ 13 files changed, 52 insertions(+), 60 deletions(-) create mode 100644 chapter1/README.md delete mode 100644 chapter1/ex1.1.py delete mode 100644 chapter1/ex1.2.py create mode 100644 chapter2/README.md create mode 100644 chapter4/README.md create mode 100644 chapter6/README.md delete mode 100644 chapter9/examples/heaptest.py delete mode 100644 chapter9/examples/list.py delete mode 100644 chapter9/examples/priorityqueuetest.py diff --git a/.gitignore b/.gitignore index 8de3757..f2f459a 100644 --- a/.gitignore +++ b/.gitignore @@ -159,4 +159,6 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ -words_alpha.txt \ No newline at end of file +words_alpha.txt + +tests/ \ No newline at end of file diff --git a/chapter1/README.md b/chapter1/README.md new file mode 100644 index 0000000..15ab396 --- /dev/null +++ b/chapter1/README.md @@ -0,0 +1,5 @@ +# Binary Search + +Repeatedly split the array checking if value is greater or less than the mid point. Stop when the exact value is found. + +It takes log N steps to reduce an array of size N to an array of size 1. Time complexity for this algorithm is `O(log N)`. diff --git a/chapter1/binary.py b/chapter1/binary.py index 8ca4d13..664a93e 100644 --- a/chapter1/binary.py +++ b/chapter1/binary.py @@ -30,11 +30,14 @@ SAMPLE_SIZE = 1000 numbers = random.sample(range(LOWER, UPPER), SAMPLE_SIZE) numbers.sort() +seen = set() +count = 0 result = None -while result is None: +while not result: guess = random.randrange(LOWER, UPPER) - logger.debug(f"guess: {guess}") - result = binary_search(numbers, guess) + if guess not in seen: + count += 1 + seen.add(guess) + result = binary_search(numbers, guess) - -print(f"Found {guess} at index {result}.") +print(f"Found {guess} at index {result} after {count} attempts") diff --git a/chapter1/ex1.1.py b/chapter1/ex1.1.py deleted file mode 100644 index 613ddd8..0000000 --- a/chapter1/ex1.1.py +++ /dev/null @@ -1,7 +0,0 @@ -import math - -num_steps = int(math.log2(128)) -print( - f"A binary search would take maximum {num_steps} steps " - "to search a list of 128 items." -) diff --git a/chapter1/ex1.2.py b/chapter1/ex1.2.py deleted file mode 100644 index aa80532..0000000 --- a/chapter1/ex1.2.py +++ /dev/null @@ -1,7 +0,0 @@ -import math - -num_steps = int(math.log2(128*2)) -print( - f"A binary search would take maximum {num_steps} steps " - "to search a list of 256 items." -) diff --git a/chapter2/README.md b/chapter2/README.md new file mode 100644 index 0000000..4309a4b --- /dev/null +++ b/chapter2/README.md @@ -0,0 +1,7 @@ +# Selection Sort + +We have to perform N swaps a total of N times. This takes N^N steps, therefore: + +This algorithm has time complexity `O(N^2)` + +Technically (`n – 1, n - 2 ... 2, 1` ~= N/2) swaps are performed but in BigO the constants are dropped. diff --git a/chapter4/README.md b/chapter4/README.md new file mode 100644 index 0000000..37fffe3 --- /dev/null +++ b/chapter4/README.md @@ -0,0 +1,12 @@ +# Recursion + +Recursive functions must have both: + +- one or more base cases +- a recursive case + +The base cases are required to ensure the recursion stops when meeting a condition + +The recursive case adds functions onto the call stack and completes each one top down. + +Note. Quicksort should be implemented using a random pivot to ensure average runtimes. diff --git a/chapter4/binary.py b/chapter4/binary.py index a16a86a..7f3f9e1 100644 --- a/chapter4/binary.py +++ b/chapter4/binary.py @@ -32,10 +32,14 @@ SAMPLE_SIZE = 1000 numbers = random.sample(range(LOWER, UPPER), SAMPLE_SIZE) numbers.sort() +seen = set() +count = 0 result = None while result is None: guess = random.randrange(LOWER, UPPER) - logger.debug(f"guess: {guess}") - result = binary_search(numbers, 0, len(numbers) - 1, guess) + if guess not in seen: + count += 1 + seen.add(guess) + result = binary_search(numbers, 0, len(numbers) - 1, guess) -print(f"Found {guess} at index {result}.") +print(f"Found {guess} at index {result} after {count} attempts.") diff --git a/chapter6/README.md b/chapter6/README.md new file mode 100644 index 0000000..04000da --- /dev/null +++ b/chapter6/README.md @@ -0,0 +1,9 @@ +# Breadth-First Search + +Can tell you if there's a path between A and B and will find the shortest. + +In these examples, 1st degree Mango sellers are found before 2nd degree, 2nd before 3rd and so on. + +Visted nodes should be stored in a set to ensure no infinite loops. + +Running time for BFS on a directed graph: `O(V + E`) where V = vertices, E = edges. diff --git a/chapter9/README.md b/chapter9/README.md index cca7401..d386194 100644 --- a/chapter9/README.md +++ b/chapter9/README.md @@ -2,4 +2,4 @@ - Dijkstra's algorithm works when all weights are non-negative - If there are negative weights use Bellman-Ford. -- Priority queue + min heap is optimal when compared to a function that operates on a list. +- The book demonstrates a function that operates on a list. Priority queue + min heap added for completeness. diff --git a/chapter9/examples/heaptest.py b/chapter9/examples/heaptest.py deleted file mode 100644 index 9af2fb5..0000000 --- a/chapter9/examples/heaptest.py +++ /dev/null @@ -1,10 +0,0 @@ -import heapq - -customers = [] -heapq.heappush(customers, (2, "Harry")) -heapq.heappush(customers, (3, "Charles")) -heapq.heappush(customers, (1, "Riya")) -heapq.heappush(customers, (4, "Stacy")) - -while customers: - print(heapq.heappop(customers)) diff --git a/chapter9/examples/list.py b/chapter9/examples/list.py deleted file mode 100644 index 0e04b1c..0000000 --- a/chapter9/examples/list.py +++ /dev/null @@ -1,14 +0,0 @@ -customers = [] -customers.append((2, "Harry")) # no sort needed here because 1 item. -customers.append((3, "Charles")) -customers.sort(reverse=True) -# Need to sort to maintain order -customers.append((1, "Riya")) -customers.sort(reverse=True) -# Need to sort to maintain order -customers.append((4, "Stacy")) -customers.sort(reverse=True) - -while customers: - print(customers.pop(0)) -# Will print names in the order: Stacy, Charles, Harry, Riya. diff --git a/chapter9/examples/priorityqueuetest.py b/chapter9/examples/priorityqueuetest.py deleted file mode 100644 index 4c48746..0000000 --- a/chapter9/examples/priorityqueuetest.py +++ /dev/null @@ -1,12 +0,0 @@ -from queue import PriorityQueue - -customers = ( - PriorityQueue() -) # we initialise the PQ class instead of using a function to operate upon a list. -customers.put((2, "Harry")) -customers.put((3, "Charles")) -customers.put((1, "Riya")) -customers.put((4, "Stacy")) - -while customers: - print(customers.get())