From 52278875e5bff5fdcdd84d96cb4e6f03f4773d4e Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 10 May 2019 09:00:54 -0700 Subject: [PATCH 01/39] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a7ba5093..e137132a3 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Commit your code regularly and meaningfully. This helps both you (in case you ev This Sprint Challenge is split into three parts: -1. Writing an algorithm to traverse through a binary search tree +1. Implement a data structure called a ring buffer (description in the README in the `ring_buffer` directory 2. Optimizing some inefficient code 3. Analyzing time and space complexities from parts 1 and 2 From 1262f36a0faf3ff1c23cd082e3fbb76c31c78f83 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 10 May 2019 09:26:36 -0700 Subject: [PATCH 02/39] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e137132a3..30881a7fb 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Commit your code regularly and meaningfully. This helps both you (in case you ev This Sprint Challenge is split into three parts: -1. Implement a data structure called a ring buffer (description in the README in the `ring_buffer` directory +1. Implement a data structure called a ring buffer (more details below) 2. Optimizing some inefficient code 3. Analyzing time and space complexities from parts 1 and 2 @@ -66,9 +66,7 @@ Six seconds is an eternity so you've been tasked with speeding up the code. Can #### Task 3. Analyze Some Runtimes -Open up the `Data_Structures_Answers.md` file. This is where you'll jot down your answers for the runtimes of the functions you just implemented. If you implemented depth-first traversal, just answer the questions pertaining to the depth-first traversal algorithm. If you implemented breadth-first traversal, just answer the questions pertaining to breadth-first traversal. - -Also, include the runtime and space complexities of the original code and your optimized solution from `names.py`. +Open up the `Data_Structures_Answers.md` file. This is where you'll jot down your answers for the runtimes of the functions/data structures you just implemented. Also include the runtime and space complexities of the original code and your optimized solution from `names.py`. ### Stretch Problems From 1d3463210621486aeb7210c4066b078465fc4838 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Thu, 22 Aug 2019 09:20:53 -0600 Subject: [PATCH 03/39] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 30881a7fb..2860813a0 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,8 @@ Navigate into the `names` directory. Here you will find two text files containin Six seconds is an eternity so you've been tasked with speeding up the code. Can you get the runtime to under a second? Under one hundredth of a second? +*You may not use the built in Python list or set for this problem* + (Hint: You might try importing a data structure you built during the week) #### Task 3. Analyze Some Runtimes From 2cfbbaa282440c8d077a537880ede89eb147c20f Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 23 Aug 2019 11:15:43 -0600 Subject: [PATCH 04/39] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2860813a0..6cb1e7331 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,8 @@ buffer.get() # should return ['d', 'e', 'f'] #### Task 2. Runtime Optimization +***!Important!*** If you are running this using PowerShell by clicking on the green play button, you will get an error that `names1.txt` is not found. To resolve this, run it, get the error, then `cd` into the `names` directory in the `python` terminal that opens in VSCode. + Navigate into the `names` directory. Here you will find two text files containing 10,000 names each, along with a program `names.py` that compares the two files and prints out duplicate name entries. Try running the code with `python3 names.py`. Be patient because it might take a while: approximately six seconds on my laptop. What is the runtime complexity of this code? Six seconds is an eternity so you've been tasked with speeding up the code. Can you get the runtime to under a second? Under one hundredth of a second? From f4b541f07d587f4ec95c60389163fda0f46dfd07 Mon Sep 17 00:00:00 2001 From: Elissa Date: Fri, 13 Sep 2019 19:51:54 -0500 Subject: [PATCH 05/39] Adding Linked List task --- Data_Structures_Answers.md | 18 --------------- README.md | 43 ++++++++++++---------------------- reverse/reverse.py | 47 ++++++++++++++++++++++++++++++++++++++ reverse/test_reverse.py | 47 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 46 deletions(-) delete mode 100644 Data_Structures_Answers.md create mode 100644 reverse/reverse.py create mode 100644 reverse/test_reverse.py diff --git a/Data_Structures_Answers.md b/Data_Structures_Answers.md deleted file mode 100644 index e39545492..000000000 --- a/Data_Structures_Answers.md +++ /dev/null @@ -1,18 +0,0 @@ -Add your answers to the questions below. - -1. What is the runtime complexity of your ring buffer's `append` method? - -2. What is the space complexity of your ring buffer's `append` function? - -3. What is the runtime complexity of your ring buffer's `get` method? - -4. What is the space complexity of your ring buffer's `get` method? - - -5. What is the runtime complexity of the provided code in `names.py`? - -6. What is the space complexity of the provided code in `names.py`? - -7. What is the runtime complexity of your optimized code in `names.py`? - -8. What is the space complexity of your optimized code in `names.py`? diff --git a/README.md b/README.md index 6cb1e7331..9930829cb 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ In this week's Sprint you implemented some classic and fundamental data structur This is an individual assessment. All work must be your own. Your Challenge score is a measure of your ability to work independently using the material covered throughout this sprint. You need to demonstrate proficiency in the concepts and objectives that were introduced and that you practiced in the preceding days. -You are not allowed to collaborate during the Sprint Challenge. However, you are encouraged to follow the twenty-minute rule and seek support from your PM and Instructor in your cohort help channel on Slack. Your submitted work reflects your proficiency in the concepts and topics that were covered this week. +You are not allowed to collaborate during the Sprint Challenge. However, you are encouraged to follow the twenty-minute rule and seek support from your TL and Instructor in your cohort help channel on Slack. Your submitted work reflects your proficiency in the concepts and topics that were covered this week. You have three hours to complete this Sprint Challenge. Plan your time accordingly. @@ -22,7 +22,7 @@ This Sprint Challenge is split into three parts: 1. Implement a data structure called a ring buffer (more details below) 2. Optimizing some inefficient code -3. Analyzing time and space complexities from parts 1 and 2 +3. Reversing the contents of a singly linked list ### Minimum Viable Product @@ -68,37 +68,24 @@ Six seconds is an eternity so you've been tasked with speeding up the code. Can (Hint: You might try importing a data structure you built during the week) -#### Task 3. Analyze Some Runtimes -Open up the `Data_Structures_Answers.md` file. This is where you'll jot down your answers for the runtimes of the functions/data structures you just implemented. Also include the runtime and space complexities of the original code and your optimized solution from `names.py`. +#### Task 3. Reverse a Linked List +Inside of the `reverse` directory, you'll find a basic implementation of a Singly Linked List. _Without_ making it a Doubly Linked List (adding a tail attribute), complete the `reverse_list()` function within `reverse/reverse.py` reverse the contents of the list. + +For example, +``` +1->2->3->None +``` +would become... +``` +3->2->1->None +``` + +While credit will be given for a functional solution, only optimal solutions will earn a ***3*** on this task. ### Stretch Problems 1. Say your code from `names.py` is to run on an embedded computer with very limited RAM. Because of this, memory is extremely constrained and you are only allowed to store names in arrays (i.e. Python lists). How would you go about optimizing the code under these conditions? Try it out and compare your solution to the original runtime. (If this solution is less efficient than your original solution, include both and label the strech solution with a comment) ### Rubric - -#### Ring Buffer - -- Ring buffer implementation passes the tests: 10 points total - -#### Names - -- Optimize with an O(n log n) runtime solution: 8 points total -- Optimize with an O(n) runtime solution: 10 points total - -#### Complexity - -- One point each: 8 points total - -#### Stretch - -- `names.py` is optimized with sub-quadratic runtime complexity and tightly constrained linear space complexity: 4 points - - -#### Grading - -* *3*: 28+ -* *2*: 20-27 -* *1*: 0-19 diff --git a/reverse/reverse.py b/reverse/reverse.py new file mode 100644 index 000000000..95ed9d1d4 --- /dev/null +++ b/reverse/reverse.py @@ -0,0 +1,47 @@ +class Node: + def __init__(self, value=None, next_node=None): + # the value at this linked list node + self.value = value + # reference to the next node in the list + self.next_node = next_node + + def get_value(self): + return self.value + + def get_next(self): + return self.next_node + + def set_next(self, new_next): + # set this node's next_node reference to the passed in node + self.next_node = new_next + +class LinkedList: + def __init__(self): + # reference to the head of the list + self.head = None + + def add_to_head(self, value): + node = Node(value) + if self.head is not None: + node.set_next(self.head) + + self.head = node + + def contains(self, value): + if not self.head: + return False + # get a reference to the node we're currently at; update this as we traverse the list + current = self.head + # check to see if we're at a valid node + while current: + # return True if the current value we're looking at matches our target value + if current.get_value() == value: + return True + # update our current node to the current node's next node + current = current.get_next() + # if we've gotten here, then the target node isn't in our list + return False + + def reverse_list(self): + # TO BE COMPLETED + pass \ No newline at end of file diff --git a/reverse/test_reverse.py b/reverse/test_reverse.py new file mode 100644 index 000000000..50cbfe3f3 --- /dev/null +++ b/reverse/test_reverse.py @@ -0,0 +1,47 @@ +import unittest +from reverse import LinkedList + +class LinkedListTests(unittest.TestCase): + def setUp(self): + self.list = LinkedList() + + def test_add_to_head(self): + self.list.add_to_head(1) + self.assertEqual(self.list.head.value, 1) + self.list.add_to_head(2) + self.assertEqual(self.list.head.value, 2) + + def test_contains(self): + self.list.add_to_head(1) + self.list.add_to_head(2) + self.list.add_to_head(10) + self.assertTrue(self.list.contains(2)) + self.assertTrue(self.list.contains(10)) + self.assertFalse(self.list.contains(1000)) + + def test_empty_reverse(self): + self.list.reverse_list() + self.assertEqual(self.list.head, None) + + def test_single_reverse(self): + self.list.add_to_head(1) + self.list.reverse_list() + self.assertEqual(self.list.head.value, 1) + + def test_longer_reverse(self): + self.list.add_to_head(1) + self.list.add_to_head(2) + self.list.add_to_head(3) + self.list.add_to_head(4) + self.list.add_to_head(5) + self.assertEqual(self.list.head.value, 5) + self.list.reverse_list() + self.assertEqual(self.list.head.value, 1) + self.assertEqual(self.list.head.get_next().value, 2) + self.assertEqual(self.list.head.get_next().get_next().value, 3) + + + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From bf92f0d2945bfdde36db0b74f8bbf1d3cd4db8a4 Mon Sep 17 00:00:00 2001 From: Elissa Thomas <4015794+et-code-home@users.noreply.github.com> Date: Fri, 13 Sep 2019 17:55:30 -0700 Subject: [PATCH 06/39] Adding rubric --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 9930829cb..fd2b8c675 100644 --- a/README.md +++ b/README.md @@ -89,3 +89,14 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric +| OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | +| ---------- | ----- | ------- | ------- | ------- | -- | +| _Student should be able to enumerate how queues work as well as what some of their pros and cons are._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 7/9 tests | Solution in `ring_buffer.py` has no syntax or logical errors and passes 9/9 tests | | +| _Student should be able to enumerate how binary search trees work as well as what some of their pros and cons are_ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student correctly identifies the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n) or better | | +| _Student should be able to enumerate how linked lists work as well as what some of their pros and cons are._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| _Student should be able to write code that utilizes Python Collections_ | [STRETCH] Optimize code from Task 2, given the constraint that **only standard Python collections** may be used to store names | Level 1 solution provided | Level 2 solution provided | Level 3 solution provided | | +| **FINAL SCORE** | _(3 tasks + 1 STRETCH goal)_ | **0-5** | **6-9** | **10-12** | | + + +#### Passing the Sprint +Score ranges for a 1, 2, and 3 are shown in the rubric above. For a student to have _passed_ a sprint challenge, they need to earn an **average of at least 2** for all items on the rubric. From 5cd75905666b45703ea48f645da62e58b150c70a Mon Sep 17 00:00:00 2001 From: Elissa Thomas <4015794+et-code-home@users.noreply.github.com> Date: Fri, 13 Sep 2019 17:56:55 -0700 Subject: [PATCH 07/39] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fd2b8c675..d7fd1cb0a 100644 --- a/README.md +++ b/README.md @@ -83,9 +83,10 @@ would become... ``` While credit will be given for a functional solution, only optimal solutions will earn a ***3*** on this task. -### Stretch Problems -1. Say your code from `names.py` is to run on an embedded computer with very limited RAM. Because of this, memory is extremely constrained and you are only allowed to store names in arrays (i.e. Python lists). How would you go about optimizing the code under these conditions? Try it out and compare your solution to the original runtime. (If this solution is less efficient than your original solution, include both and label the strech solution with a comment) +#### Stretch + +* Say your code from `names.py` is to run on an embedded computer with very limited RAM. Because of this, memory is extremely constrained and you are only allowed to store names in arrays (i.e. Python lists). How would you go about optimizing the code under these conditions? Try it out and compare your solution to the original runtime. (If this solution is less efficient than your original solution, include both and label the strech solution with a comment) ### Rubric From 17fe5c1b4c95e4e3bed368fc06587a93becffce0 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Tue, 24 Sep 2019 15:19:24 -0600 Subject: [PATCH 08/39] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d7fd1cb0a..dbdf3c864 100644 --- a/README.md +++ b/README.md @@ -92,9 +92,9 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric | OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ---------- | ----- | ------- | ------- | ------- | -- | -| _Student should be able to enumerate how queues work as well as what some of their pros and cons are._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 7/9 tests | Solution in `ring_buffer.py` has no syntax or logical errors and passes 9/9 tests | | -| _Student should be able to enumerate how binary search trees work as well as what some of their pros and cons are_ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student correctly identifies the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n) or better | | -| _Student should be able to enumerate how linked lists work as well as what some of their pros and cons are._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 7/9 tests | Solution in `ring_buffer.py` has no syntax or logical errors and passes 9/9 tests | | +| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student correctly identifies the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n) or better | | +| _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | | _Student should be able to write code that utilizes Python Collections_ | [STRETCH] Optimize code from Task 2, given the constraint that **only standard Python collections** may be used to store names | Level 1 solution provided | Level 2 solution provided | Level 3 solution provided | | | **FINAL SCORE** | _(3 tasks + 1 STRETCH goal)_ | **0-5** | **6-9** | **10-12** | | From 0d683f84f76bef5db782ac208721cf921c734040 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 18 Oct 2019 13:49:53 -0600 Subject: [PATCH 09/39] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dbdf3c864..004cd15da 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Navigate into the `names` directory. Here you will find two text files containin Six seconds is an eternity so you've been tasked with speeding up the code. Can you get the runtime to under a second? Under one hundredth of a second? -*You may not use the built in Python list or set for this problem* +*You may not use the built in Python list, set, or dictionary for this problem* (Hint: You might try importing a data structure you built during the week) @@ -93,7 +93,7 @@ While credit will be given for a functional solution, only optimal solutions wil | OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ---------- | ----- | ------- | ------- | ------- | -- | | _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 7/9 tests | Solution in `ring_buffer.py` has no syntax or logical errors and passes 9/9 tests | | -| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student correctly identifies the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of O(n) or better | | +| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | | _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | | _Student should be able to write code that utilizes Python Collections_ | [STRETCH] Optimize code from Task 2, given the constraint that **only standard Python collections** may be used to store names | Level 1 solution provided | Level 2 solution provided | Level 3 solution provided | | | **FINAL SCORE** | _(3 tasks + 1 STRETCH goal)_ | **0-5** | **6-9** | **10-12** | | From c1f68c291efdec0c5841e663d0f667bc7563cbcb Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 18 Oct 2019 15:48:59 -0600 Subject: [PATCH 10/39] Update test_ring_buffer.py --- ring_buffer/test_ring_buffer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ring_buffer/test_ring_buffer.py b/ring_buffer/test_ring_buffer.py index 6508c10af..623b3cd1b 100644 --- a/ring_buffer/test_ring_buffer.py +++ b/ring_buffer/test_ring_buffer.py @@ -28,7 +28,11 @@ def test_ring_buffer(self): self.buffer.append('i') self.assertEqual(len(self.buffer.storage), 5) self.assertEqual(self.buffer.get(), ['f', 'g', 'h', 'i', 'e']) + + self.buffer.append('j') + self.buffer.append('k') + self.assertEqual(self.buffer.get(), ['k', 'g', 'h', 'i', 'j']) if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() From ebc6a51d2856e857ef11e31b4d22d37548fb19ee Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 18 Oct 2019 16:04:11 -0600 Subject: [PATCH 11/39] Update test_ring_buffer.py --- ring_buffer/test_ring_buffer.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ring_buffer/test_ring_buffer.py b/ring_buffer/test_ring_buffer.py index 623b3cd1b..277ff8a00 100644 --- a/ring_buffer/test_ring_buffer.py +++ b/ring_buffer/test_ring_buffer.py @@ -4,6 +4,7 @@ class RingBufferTests(unittest.TestCase): def setUp(self): self.buffer = RingBuffer(5) + self.buffer_2 = RingBuffer(5) def test_ring_buffer(self): self.assertEqual(len(self.buffer.storage), 5) @@ -32,6 +33,10 @@ def test_ring_buffer(self): self.buffer.append('j') self.buffer.append('k') self.assertEqual(self.buffer.get(), ['k', 'g', 'h', 'i', 'j']) + + for i in range(50): + self.buffer_2.append(i) + self.assertEqual(self.buffer2.get(), [45, 46, 47, 48, 49]) if __name__ == '__main__': From 679328f177f06c39b81b30573630f5d36a8235fa Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 15 Nov 2019 10:36:05 -0600 Subject: [PATCH 12/39] Update test_ring_buffer.py --- ring_buffer/test_ring_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ring_buffer/test_ring_buffer.py b/ring_buffer/test_ring_buffer.py index 277ff8a00..842b5d693 100644 --- a/ring_buffer/test_ring_buffer.py +++ b/ring_buffer/test_ring_buffer.py @@ -36,7 +36,7 @@ def test_ring_buffer(self): for i in range(50): self.buffer_2.append(i) - self.assertEqual(self.buffer2.get(), [45, 46, 47, 48, 49]) + self.assertEqual(self.buffer_2.get(), [45, 46, 47, 48, 49]) if __name__ == '__main__': From c0db60317338cddb633725c9c0ddc639ba92a29e Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 15 Nov 2019 10:36:14 -0600 Subject: [PATCH 13/39] Update test_ring_buffer.py From fa4feac6c5e625a9c42fbfbcea4f82127933eb09 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 15 Nov 2019 11:11:44 -0600 Subject: [PATCH 14/39] fix edge case test --- ring_buffer/test_ring_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ring_buffer/test_ring_buffer.py b/ring_buffer/test_ring_buffer.py index 842b5d693..a8462ffbf 100644 --- a/ring_buffer/test_ring_buffer.py +++ b/ring_buffer/test_ring_buffer.py @@ -36,7 +36,7 @@ def test_ring_buffer(self): for i in range(50): self.buffer_2.append(i) - self.assertEqual(self.buffer_2.get(), [45, 46, 47, 48, 49]) + self.assertEqual(self.buffer_2.get(), [45, 46, 47, 48, 49]) if __name__ == '__main__': From 07fc8734d6fdda8251c50a02640ab571bfe4a2c1 Mon Sep 17 00:00:00 2001 From: briandoyle81 Date: Mon, 18 Nov 2019 10:48:08 -0600 Subject: [PATCH 15/39] Update readme for LL version of ring buffer --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 004cd15da..8be4fafa3 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,11 @@ This Sprint Challenge is split into three parts: A ring buffer is a non-growable buffer with a fixed size. When the ring buffer is full and a new element is inserted, the oldest element in the ring buffer is overwritten with the newest element. This kind of data structure is very useful for use cases such as storing logs and history information, where you typically want to store information up until it reaches a certain age, after which you don't care about it anymore and don't mind seeing it overwritten by newer data. -Implement this behavior in the RingBuffer class. RingBuffer has two methods, `append` and `get`. The `append` method adds elements to the buffer. The `get` method returns all of the elements in the buffer in a list in their given order. It should not return any `None` values in the list even if they are present in the ring buffer. +Implement this behavior in the RingBuffer class. RingBuffer has two methods, `append` and `get`. The `append` method adds elements to the buffer. The `get` method, which is provided, returns all of the elements in the buffer in a list in their given order. It should not return any `None` values in the list even if they are present in the ring buffer. + +_You may not use a Python List in your implementation of the `append` method (except for the stretch goal)_ + +*Stretch Goal*: Another method of implementing a ring buffer uses an array (Python List) instead of a linked list. What are the advantages and disadvantages of using this method? What disadvantage normally found in arrays is overcome with this arrangement? For example: From 5fafef5c43dd52c3aa0b1cebc3b608a68d6ee3f9 Mon Sep 17 00:00:00 2001 From: briandoyle81 Date: Mon, 18 Nov 2019 10:49:16 -0600 Subject: [PATCH 16/39] add DLL to ring buffer folder --- ring_buffer/doubly_linked_list.py | 138 ++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 ring_buffer/doubly_linked_list.py diff --git a/ring_buffer/doubly_linked_list.py b/ring_buffer/doubly_linked_list.py new file mode 100644 index 000000000..4f445a868 --- /dev/null +++ b/ring_buffer/doubly_linked_list.py @@ -0,0 +1,138 @@ +"""Each ListNode holds a reference to its previous node +as well as its next node in the List.""" + + +class ListNode: + def __init__(self, value, prev=None, next=None): + self.value = value + self.prev = prev + self.next = next + + """Wrap the given value in a ListNode and insert it + after this node. Note that this node could already + have a next node it is point to.""" + def insert_after(self, value): + current_next = self.next + self.next = ListNode(value, self, current_next) + if current_next: + current_next.prev = self.next + + """Wrap the given value in a ListNode and insert it + before this node. Note that this node could already + have a previous node it is point to.""" + def insert_before(self, value): + current_prev = self.prev + self.prev = ListNode(value, current_prev, self) + if current_prev: + current_prev.next = self.prev + + """Rearranges this ListNode's previous and next pointers + accordingly, effectively deleting this ListNode.""" + def delete(self): + if self.prev: + self.prev.next = self.next + if self.next: + self.next.prev = self.prev + + +"""Our doubly-linked list class. It holds references to +the list's head and tail nodes.""" + + +class DoublyLinkedList: + def __init__(self, node=None): + self.head = node + self.tail = node + self.length = 1 if node is not None else 0 + + def __len__(self): + return self.length + + """Wraps the given value in a ListNode and inserts it + as the new head of the list. Don't forget to handle + the old head node's previous pointer accordingly.""" + def add_to_head(self, value): + new_node = ListNode(value, None, None) + self.length += 1 + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + else: + new_node.next = self.head + self.head.prev = new_node + self.head = new_node + + """Removes the List's current head node, making the + current head's next node the new head of the List. + Returns the value of the removed Node.""" + def remove_from_head(self): + value = self.head.value + self.delete(self.head) + return value + + """Wraps the given value in a ListNode and inserts it + as the new tail of the list. Don't forget to handle + the old tail node's next pointer accordingly.""" + def add_to_tail(self, value): + new_node = ListNode(value, None, None) + self.length += 1 + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + else: + new_node.prev = self.tail + self.tail.next = new_node + self.tail = new_node + + """Removes the List's current tail node, making the + current tail's previous node the new tail of the List. + Returns the value of the removed Node.""" + def remove_from_tail(self): + value = self.tail.value + self.delete(self.tail) + return value + + """Removes the input node from its current spot in the + List and inserts it as the new head node of the List.""" + def move_to_front(self, node): + if node is self.head: + return + value = node.value + self.delete(node) + self.add_to_head(value) + + """Removes the input node from its current spot in the + List and inserts it as the new tail node of the List.""" + def move_to_end(self, node): + if node is self.tail: + return + value = node.value + self.delete(node) + self.add_to_tail(value) + + """Removes a node from the list and handles cases where + the node was the head or the tail""" + def delete(self, node): + self.length -= 1 + if self.head is self.tail: + self.head = None + self.tail = None + elif self.head is node: + self.head = node.next + node.delete() + elif self.tail is node: + self.tail = node.prev + node.delete() + else: + node.delete() + + """Returns the highest value currently in the list""" + def get_max(self): + max_value = self.head.value + current = self.head + while current is not None: + if current.value > max_value: + max_value = current.value + current = current.next + + return max_value From 38a28874069fd1c4f62ff2f0686cffa438053f77 Mon Sep 17 00:00:00 2001 From: briandoyle81 Date: Mon, 18 Nov 2019 10:54:25 -0600 Subject: [PATCH 17/39] update starter for LL and 4 spaces --- ring_buffer/ring_buffer.py | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index 35fd33cac..ef88f0d6b 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -1,11 +1,32 @@ +from doubly_linked_list import DoublyLinkedList + + class RingBuffer: - def __init__(self, capacity): - self.capacity = capacity - self.current = 0 - self.storage = [None]*capacity + def __init__(self, capacity): + self.capacity = capacity + self.current = None + self.storage = DoublyLinkedList() + + def append(self, item): + pass + + def get(self): + # Note: This is the only [] allowed + list_buffer_contents = [] + + # TODO: Your code here + + return list_buffer_contents + +# ----------------Stretch Goal------------------- + + +class ArrayRingBuffer: + def __init__(self, capacity): + pass - def append(self, item): - pass + def append(self, item): + pass - def get(self): - pass \ No newline at end of file + def get(self): + pass From b6f92d6d76e7b05efd9a3a1fceeb29c661aae2d4 Mon Sep 17 00:00:00 2001 From: briandoyle81 Date: Mon, 18 Nov 2019 11:25:49 -0600 Subject: [PATCH 18/39] update tests --- ring_buffer/test_ring_buffer.py | 47 ++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/ring_buffer/test_ring_buffer.py b/ring_buffer/test_ring_buffer.py index a8462ffbf..3eb2bda1f 100644 --- a/ring_buffer/test_ring_buffer.py +++ b/ring_buffer/test_ring_buffer.py @@ -1,5 +1,6 @@ import unittest -from ring_buffer import RingBuffer +from ring_buffer import RingBuffer, ArrayRingBuffer + class RingBufferTests(unittest.TestCase): def setUp(self): @@ -7,6 +8,44 @@ def setUp(self): self.buffer_2 = RingBuffer(5) def test_ring_buffer(self): + self.assertEqual(self.buffer.storage.length, 0) + + self.buffer.append('a') + self.buffer.append('b') + self.buffer.append('c') + self.buffer.append('d') + self.assertEqual(self.buffer.storage.length, 4) + self.assertEqual(self.buffer.get(), ['a', 'b', 'c', 'd']) + + self.buffer.append('e') + self.assertEqual(self.buffer.storage.length, 5) + self.assertEqual(self.buffer.get(), ['a', 'b', 'c', 'd', 'e']) + + self.buffer.append('f') + self.assertEqual(self.buffer.storage.length, 5) + self.assertEqual(self.buffer.get(), ['f', 'b', 'c', 'd', 'e']) + + self.buffer.append('g') + self.buffer.append('h') + self.buffer.append('i') + self.assertEqual(self.buffer.storage.length, 5) + self.assertEqual(self.buffer.get(), ['f', 'g', 'h', 'i', 'e']) + + self.buffer.append('j') + self.buffer.append('k') + self.assertEqual(self.buffer.get(), ['k', 'g', 'h', 'i', 'j']) + + for i in range(50): + self.buffer_2.append(i) + self.assertEqual(self.buffer_2.get(), [45, 46, 47, 48, 49]) + + +class ArrayRingBufferTests(unittest.TestCase): + def setUp(self): + self.buffer = ArrayRingBuffer(5) + self.buffer_2 = ArrayRingBuffer(5) + + def test__array_ring_buffer(self): self.assertEqual(len(self.buffer.storage), 5) self.buffer.append('a') @@ -29,11 +68,7 @@ def test_ring_buffer(self): self.buffer.append('i') self.assertEqual(len(self.buffer.storage), 5) self.assertEqual(self.buffer.get(), ['f', 'g', 'h', 'i', 'e']) - - self.buffer.append('j') - self.buffer.append('k') - self.assertEqual(self.buffer.get(), ['k', 'g', 'h', 'i', 'j']) - + for i in range(50): self.buffer_2.append(i) self.assertEqual(self.buffer_2.get(), [45, 46, 47, 48, 49]) From b8a30c72f7578943564b5f6fc10039aa3e490da6 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Mon, 18 Nov 2019 11:42:12 -0600 Subject: [PATCH 19/39] Update names.py --- names/names.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/names/names.py b/names/names.py index 586e8393e..96a8b1a17 100644 --- a/names/names.py +++ b/names/names.py @@ -20,3 +20,7 @@ print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") print (f"runtime: {end_time - start_time} seconds") +# ---------- Stretch Goal ----------- +# Python has built-in tools that allow for a very efficient approach to this problem +# What's the best time you can accomplish with no restrictions on techniques or data +# structures? From 8311e37601e6e53d49fdef532f8c2f25c392978c Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 31 Jan 2020 11:41:52 -0600 Subject: [PATCH 20/39] Update names.py --- names/names.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/names/names.py b/names/names.py index 96a8b1a17..0fcdd6eab 100644 --- a/names/names.py +++ b/names/names.py @@ -10,7 +10,9 @@ names_2 = f.read().split("\n") # List containing 10000 names f.close() -duplicates = [] +duplicates = [] # Return the list of duplicates in this data structure + +# Replace the nested for loops below with your improvements for name_1 in names_1: for name_2 in names_2: if name_1 == name_2: From b863ebf796d3ec8dec25b2d76f0777dd8b67eff0 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 31 Jan 2020 11:45:36 -0600 Subject: [PATCH 21/39] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8be4fafa3..8b5d358e8 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Navigate into the `names` directory. Here you will find two text files containin Six seconds is an eternity so you've been tasked with speeding up the code. Can you get the runtime to under a second? Under one hundredth of a second? -*You may not use the built in Python list, set, or dictionary for this problem* +*You may not use the built in Python list, set, or dictionary in your solution for this problem. However, you can and should use the provided `duplicates` list to return your solution.* (Hint: You might try importing a data structure you built during the week) From 33ecaaa7cea7e5c89cc4d73a0e8710770c78182c Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Fri, 31 Jan 2020 12:35:26 -0600 Subject: [PATCH 22/39] Update names.py --- names/names.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/names/names.py b/names/names.py index 0fcdd6eab..ea158997f 100644 --- a/names/names.py +++ b/names/names.py @@ -24,5 +24,5 @@ # ---------- Stretch Goal ----------- # Python has built-in tools that allow for a very efficient approach to this problem -# What's the best time you can accomplish with no restrictions on techniques or data -# structures? +# What's the best time you can accomplish? Thare are no restrictions on techniques or data +# structures, but you may not import any additional libraries that you did not write yourself. From 4e6f99526eb2283fc1f4cafecfcf8587a04aad9a Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Mon, 2 Mar 2020 12:47:26 -0600 Subject: [PATCH 23/39] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b5d358e8..57a59adb2 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric | OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ---------- | ----- | ------- | ------- | ------- | -- | -| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 7/9 tests | Solution in `ring_buffer.py` has no syntax or logical errors and passes 9/9 tests | | +| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 9/11 tests (Note that each _assert_ function is a test.) | Solution in `ring_buffer.py` has no syntax or logical errors and passes 11/11 tests (Note that each _assert_ function is a test.)| | | _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | | _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | | _Student should be able to write code that utilizes Python Collections_ | [STRETCH] Optimize code from Task 2, given the constraint that **only standard Python collections** may be used to store names | Level 1 solution provided | Level 2 solution provided | Level 3 solution provided | | From 16c2504ec399f4bfe42d6900838f908e304985d7 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Tue, 10 Mar 2020 14:44:42 -0600 Subject: [PATCH 24/39] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57a59adb2..d65fa6a16 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ While credit will be given for a functional solution, only optimal solutions wil | _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | | _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | | _Student should be able to write code that utilizes Python Collections_ | [STRETCH] Optimize code from Task 2, given the constraint that **only standard Python collections** may be used to store names | Level 1 solution provided | Level 2 solution provided | Level 3 solution provided | | -| **FINAL SCORE** | _(3 tasks + 1 STRETCH goal)_ | **0-5** | **6-9** | **10-12** | | + #### Passing the Sprint From 37d6a73e5c33465c90e6d1789475e1f2991cf445 Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Tue, 10 Mar 2020 14:45:49 -0600 Subject: [PATCH 25/39] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index d65fa6a16..9cd7f4a2b 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,6 @@ While credit will be given for a functional solution, only optimal solutions wil | _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 9/11 tests (Note that each _assert_ function is a test.) | Solution in `ring_buffer.py` has no syntax or logical errors and passes 11/11 tests (Note that each _assert_ function is a test.)| | | _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | | _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | -| _Student should be able to write code that utilizes Python Collections_ | [STRETCH] Optimize code from Task 2, given the constraint that **only standard Python collections** may be used to store names | Level 1 solution provided | Level 2 solution provided | Level 3 solution provided | | - #### Passing the Sprint From 36b9252720dbcaf37c958ae62ed4ac9ddca94d36 Mon Sep 17 00:00:00 2001 From: briandoyle81 Date: Tue, 24 Mar 2020 16:54:20 -0600 Subject: [PATCH 26/39] change reverse sll to require recursion --- reverse/reverse.py | 85 +++++++++++++++++++++-------------------- reverse/test_reverse.py | 6 +-- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/reverse/reverse.py b/reverse/reverse.py index 95ed9d1d4..825d00556 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -1,47 +1,50 @@ class Node: - def __init__(self, value=None, next_node=None): - # the value at this linked list node - self.value = value - # reference to the next node in the list - self.next_node = next_node + def __init__(self, value=None, next_node=None): + # the value at this linked list node + self.value = value + # reference to the next node in the list + self.next_node = next_node - def get_value(self): - return self.value + def get_value(self): + return self.value - def get_next(self): - return self.next_node + def get_next(self): + return self.next_node + + def set_next(self, new_next): + # set this node's next_node reference to the passed in node + self.next_node = new_next - def set_next(self, new_next): - # set this node's next_node reference to the passed in node - self.next_node = new_next class LinkedList: - def __init__(self): - # reference to the head of the list - self.head = None - - def add_to_head(self, value): - node = Node(value) - if self.head is not None: - node.set_next(self.head) - - self.head = node - - def contains(self, value): - if not self.head: - return False - # get a reference to the node we're currently at; update this as we traverse the list - current = self.head - # check to see if we're at a valid node - while current: - # return True if the current value we're looking at matches our target value - if current.get_value() == value: - return True - # update our current node to the current node's next node - current = current.get_next() - # if we've gotten here, then the target node isn't in our list - return False - - def reverse_list(self): - # TO BE COMPLETED - pass \ No newline at end of file + def __init__(self): + # reference to the head of the list + self.head = None + + def add_to_head(self, value): + node = Node(value) + if self.head is not None: + node.set_next(self.head) + + self.head = node + + def contains(self, value): + if not self.head: + return False + # get a reference to the node we're currently at; update this as we + # traverse the list + current = self.head + # check to see if we're at a valid node + while current: + # return True if the current value we're looking at matches our + # target value + if current.get_value() == value: + return True + # update our current node to the current node's next node + current = current.get_next() + # if we've gotten here, then the target node isn't in our list + return False + + def reverse_list(self, node, prev): + # You must use recursion for this solution + pass diff --git a/reverse/test_reverse.py b/reverse/test_reverse.py index 50cbfe3f3..7ef0b4bf0 100644 --- a/reverse/test_reverse.py +++ b/reverse/test_reverse.py @@ -20,12 +20,12 @@ def test_contains(self): self.assertFalse(self.list.contains(1000)) def test_empty_reverse(self): - self.list.reverse_list() + self.list.reverse_list(self.list.head, None) self.assertEqual(self.list.head, None) def test_single_reverse(self): self.list.add_to_head(1) - self.list.reverse_list() + self.list.reverse_list(self.list.head, None) self.assertEqual(self.list.head.value, 1) def test_longer_reverse(self): @@ -35,7 +35,7 @@ def test_longer_reverse(self): self.list.add_to_head(4) self.list.add_to_head(5) self.assertEqual(self.list.head.value, 5) - self.list.reverse_list() + self.list.reverse_list(self.list.head, None) self.assertEqual(self.list.head.value, 1) self.assertEqual(self.list.head.get_next().value, 2) self.assertEqual(self.list.head.get_next().get_next().value, 3) From 3b8d64f954aab64c00e0608fb42d0c2580c97a51 Mon Sep 17 00:00:00 2001 From: Andrew Benedict Date: Thu, 26 Mar 2020 12:59:29 -0400 Subject: [PATCH 27/39] added recursion to README for Linked List problem --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9cd7f4a2b..f66e9e01c 100644 --- a/README.md +++ b/README.md @@ -73,9 +73,9 @@ Six seconds is an eternity so you've been tasked with speeding up the code. Can (Hint: You might try importing a data structure you built during the week) -#### Task 3. Reverse a Linked List +#### Task 3. Reverse a Linked List Recursively -Inside of the `reverse` directory, you'll find a basic implementation of a Singly Linked List. _Without_ making it a Doubly Linked List (adding a tail attribute), complete the `reverse_list()` function within `reverse/reverse.py` reverse the contents of the list. +Inside of the `reverse` directory, you'll find a basic implementation of a Singly Linked List. _Without_ making it a Doubly Linked List (adding a tail attribute), complete the `reverse_list()` function within `reverse/reverse.py` reverse the contents of the list using recursion, *not a loop.* For example, ``` @@ -98,7 +98,7 @@ While credit will be given for a functional solution, only optimal solutions wil | ---------- | ----- | ------- | ------- | ------- | -- | | _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 9/11 tests (Note that each _assert_ function is a test.) | Solution in `ring_buffer.py` has no syntax or logical errors and passes 11/11 tests (Note that each _assert_ function is a test.)| | | _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | -| _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | #### Passing the Sprint From 0b4376cb8f5f6601cf1a5814c45b470c733bac81 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 8 May 2020 11:45:22 -0700 Subject: [PATCH 28/39] Remove constraint that reverse needs to be implemented recursively --- reverse/reverse.py | 18 ++-- reverse/test_reverse.py | 3 - ring_buffer/doubly_linked_list.py | 138 ------------------------------ ring_buffer/ring_buffer.py | 25 +----- ring_buffer/test_ring_buffer.py | 3 +- 5 files changed, 7 insertions(+), 180 deletions(-) delete mode 100644 ring_buffer/doubly_linked_list.py diff --git a/reverse/reverse.py b/reverse/reverse.py index 825d00556..6116252d1 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -1,8 +1,6 @@ class Node: def __init__(self, value=None, next_node=None): - # the value at this linked list node self.value = value - # reference to the next node in the list self.next_node = next_node def get_value(self): @@ -12,17 +10,15 @@ def get_next(self): return self.next_node def set_next(self, new_next): - # set this node's next_node reference to the passed in node self.next_node = new_next - class LinkedList: def __init__(self): - # reference to the head of the list self.head = None def add_to_head(self, value): node = Node(value) + if self.head is not None: node.set_next(self.head) @@ -31,20 +27,16 @@ def add_to_head(self, value): def contains(self, value): if not self.head: return False - # get a reference to the node we're currently at; update this as we - # traverse the list + current = self.head - # check to see if we're at a valid node + while current: - # return True if the current value we're looking at matches our - # target value if current.get_value() == value: return True - # update our current node to the current node's next node + current = current.get_next() - # if we've gotten here, then the target node isn't in our list + return False def reverse_list(self, node, prev): - # You must use recursion for this solution pass diff --git a/reverse/test_reverse.py b/reverse/test_reverse.py index 7ef0b4bf0..0199b1a20 100644 --- a/reverse/test_reverse.py +++ b/reverse/test_reverse.py @@ -40,8 +40,5 @@ def test_longer_reverse(self): self.assertEqual(self.list.head.get_next().value, 2) self.assertEqual(self.list.head.get_next().get_next().value, 3) - - - if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/ring_buffer/doubly_linked_list.py b/ring_buffer/doubly_linked_list.py deleted file mode 100644 index 4f445a868..000000000 --- a/ring_buffer/doubly_linked_list.py +++ /dev/null @@ -1,138 +0,0 @@ -"""Each ListNode holds a reference to its previous node -as well as its next node in the List.""" - - -class ListNode: - def __init__(self, value, prev=None, next=None): - self.value = value - self.prev = prev - self.next = next - - """Wrap the given value in a ListNode and insert it - after this node. Note that this node could already - have a next node it is point to.""" - def insert_after(self, value): - current_next = self.next - self.next = ListNode(value, self, current_next) - if current_next: - current_next.prev = self.next - - """Wrap the given value in a ListNode and insert it - before this node. Note that this node could already - have a previous node it is point to.""" - def insert_before(self, value): - current_prev = self.prev - self.prev = ListNode(value, current_prev, self) - if current_prev: - current_prev.next = self.prev - - """Rearranges this ListNode's previous and next pointers - accordingly, effectively deleting this ListNode.""" - def delete(self): - if self.prev: - self.prev.next = self.next - if self.next: - self.next.prev = self.prev - - -"""Our doubly-linked list class. It holds references to -the list's head and tail nodes.""" - - -class DoublyLinkedList: - def __init__(self, node=None): - self.head = node - self.tail = node - self.length = 1 if node is not None else 0 - - def __len__(self): - return self.length - - """Wraps the given value in a ListNode and inserts it - as the new head of the list. Don't forget to handle - the old head node's previous pointer accordingly.""" - def add_to_head(self, value): - new_node = ListNode(value, None, None) - self.length += 1 - if not self.head and not self.tail: - self.head = new_node - self.tail = new_node - else: - new_node.next = self.head - self.head.prev = new_node - self.head = new_node - - """Removes the List's current head node, making the - current head's next node the new head of the List. - Returns the value of the removed Node.""" - def remove_from_head(self): - value = self.head.value - self.delete(self.head) - return value - - """Wraps the given value in a ListNode and inserts it - as the new tail of the list. Don't forget to handle - the old tail node's next pointer accordingly.""" - def add_to_tail(self, value): - new_node = ListNode(value, None, None) - self.length += 1 - if not self.head and not self.tail: - self.head = new_node - self.tail = new_node - else: - new_node.prev = self.tail - self.tail.next = new_node - self.tail = new_node - - """Removes the List's current tail node, making the - current tail's previous node the new tail of the List. - Returns the value of the removed Node.""" - def remove_from_tail(self): - value = self.tail.value - self.delete(self.tail) - return value - - """Removes the input node from its current spot in the - List and inserts it as the new head node of the List.""" - def move_to_front(self, node): - if node is self.head: - return - value = node.value - self.delete(node) - self.add_to_head(value) - - """Removes the input node from its current spot in the - List and inserts it as the new tail node of the List.""" - def move_to_end(self, node): - if node is self.tail: - return - value = node.value - self.delete(node) - self.add_to_tail(value) - - """Removes a node from the list and handles cases where - the node was the head or the tail""" - def delete(self, node): - self.length -= 1 - if self.head is self.tail: - self.head = None - self.tail = None - elif self.head is node: - self.head = node.next - node.delete() - elif self.tail is node: - self.tail = node.prev - node.delete() - else: - node.delete() - - """Returns the highest value currently in the list""" - def get_max(self): - max_value = self.head.value - current = self.head - while current is not None: - if current.value > max_value: - max_value = current.value - current = current.next - - return max_value diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index ef88f0d6b..37e9fb0dd 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -1,27 +1,4 @@ -from doubly_linked_list import DoublyLinkedList - - class RingBuffer: - def __init__(self, capacity): - self.capacity = capacity - self.current = None - self.storage = DoublyLinkedList() - - def append(self, item): - pass - - def get(self): - # Note: This is the only [] allowed - list_buffer_contents = [] - - # TODO: Your code here - - return list_buffer_contents - -# ----------------Stretch Goal------------------- - - -class ArrayRingBuffer: def __init__(self, capacity): pass @@ -29,4 +6,4 @@ def append(self, item): pass def get(self): - pass + pass \ No newline at end of file diff --git a/ring_buffer/test_ring_buffer.py b/ring_buffer/test_ring_buffer.py index 3eb2bda1f..48d4213dd 100644 --- a/ring_buffer/test_ring_buffer.py +++ b/ring_buffer/test_ring_buffer.py @@ -1,6 +1,5 @@ import unittest -from ring_buffer import RingBuffer, ArrayRingBuffer - +from ring_buffer import RingBuffer class RingBufferTests(unittest.TestCase): def setUp(self): From 08a9096b0f4d138da1f5f0751a83aa8db73086c1 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 8 May 2020 15:54:52 -0700 Subject: [PATCH 29/39] Update README --- README.md | 8 +--- ring_buffer/test_ring_buffer.py | 65 ++++++++++----------------------- 2 files changed, 22 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index f66e9e01c..a92d0aa68 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,7 @@ This Sprint Challenge is split into three parts: A ring buffer is a non-growable buffer with a fixed size. When the ring buffer is full and a new element is inserted, the oldest element in the ring buffer is overwritten with the newest element. This kind of data structure is very useful for use cases such as storing logs and history information, where you typically want to store information up until it reaches a certain age, after which you don't care about it anymore and don't mind seeing it overwritten by newer data. -Implement this behavior in the RingBuffer class. RingBuffer has two methods, `append` and `get`. The `append` method adds elements to the buffer. The `get` method, which is provided, returns all of the elements in the buffer in a list in their given order. It should not return any `None` values in the list even if they are present in the ring buffer. - -_You may not use a Python List in your implementation of the `append` method (except for the stretch goal)_ - -*Stretch Goal*: Another method of implementing a ring buffer uses an array (Python List) instead of a linked list. What are the advantages and disadvantages of using this method? What disadvantage normally found in arrays is overcome with this arrangement? +Implement this behavior in the RingBuffer class. RingBuffer has two methods, `append` and `get`. The `append` method adds the given element to the buffer. The `get` method returns all of the elements in the buffer in a list in their given order. It should not return any `None` values in the list even if they are present in the ring buffer. For example: @@ -73,7 +69,7 @@ Six seconds is an eternity so you've been tasked with speeding up the code. Can (Hint: You might try importing a data structure you built during the week) -#### Task 3. Reverse a Linked List Recursively +#### Task 3. Reverse a Linked List Inside of the `reverse` directory, you'll find a basic implementation of a Singly Linked List. _Without_ making it a Doubly Linked List (adding a tail attribute), complete the `reverse_list()` function within `reverse/reverse.py` reverse the contents of the list using recursion, *not a loop.* diff --git a/ring_buffer/test_ring_buffer.py b/ring_buffer/test_ring_buffer.py index 48d4213dd..31e1f247d 100644 --- a/ring_buffer/test_ring_buffer.py +++ b/ring_buffer/test_ring_buffer.py @@ -3,75 +3,50 @@ class RingBufferTests(unittest.TestCase): def setUp(self): - self.buffer = RingBuffer(5) - self.buffer_2 = RingBuffer(5) + self.capacity = 5 + self.buffer = RingBuffer(self.capacity) + + def test_new_buffer_has_appropriate_capacity(self): + self.assertEqual(self.buffer.capacity, self.capacity) - def test_ring_buffer(self): - self.assertEqual(self.buffer.storage.length, 0) + def test_adding_one_element_to_buffer(self): + self.buffer.append('a') + self.assertEqual(self.buffer.get(), ['a']) + def test_filling_buffer_to_capacity(self): self.buffer.append('a') self.buffer.append('b') self.buffer.append('c') self.buffer.append('d') - self.assertEqual(self.buffer.storage.length, 4) - self.assertEqual(self.buffer.get(), ['a', 'b', 'c', 'd']) - self.buffer.append('e') - self.assertEqual(self.buffer.storage.length, 5) self.assertEqual(self.buffer.get(), ['a', 'b', 'c', 'd', 'e']) + def test_adding_one_element_to_full_buffer(self): + self.buffer.append('a') + self.buffer.append('b') + self.buffer.append('c') + self.buffer.append('d') + self.buffer.append('e') self.buffer.append('f') - self.assertEqual(self.buffer.storage.length, 5) self.assertEqual(self.buffer.get(), ['f', 'b', 'c', 'd', 'e']) - self.buffer.append('g') - self.buffer.append('h') - self.buffer.append('i') - self.assertEqual(self.buffer.storage.length, 5) - self.assertEqual(self.buffer.get(), ['f', 'g', 'h', 'i', 'e']) - - self.buffer.append('j') - self.buffer.append('k') - self.assertEqual(self.buffer.get(), ['k', 'g', 'h', 'i', 'j']) - - for i in range(50): - self.buffer_2.append(i) - self.assertEqual(self.buffer_2.get(), [45, 46, 47, 48, 49]) - - -class ArrayRingBufferTests(unittest.TestCase): - def setUp(self): - self.buffer = ArrayRingBuffer(5) - self.buffer_2 = ArrayRingBuffer(5) - - def test__array_ring_buffer(self): - self.assertEqual(len(self.buffer.storage), 5) - + def test_adding_many_elements_to_full_buffer(self): self.buffer.append('a') self.buffer.append('b') self.buffer.append('c') self.buffer.append('d') - self.assertEqual(len(self.buffer.storage), 5) - self.assertEqual(self.buffer.get(), ['a', 'b', 'c', 'd']) - self.buffer.append('e') - self.assertEqual(len(self.buffer.storage), 5) - self.assertEqual(self.buffer.get(), ['a', 'b', 'c', 'd', 'e']) - self.buffer.append('f') - self.assertEqual(len(self.buffer.storage), 5) - self.assertEqual(self.buffer.get(), ['f', 'b', 'c', 'd', 'e']) - self.buffer.append('g') self.buffer.append('h') self.buffer.append('i') - self.assertEqual(len(self.buffer.storage), 5) self.assertEqual(self.buffer.get(), ['f', 'g', 'h', 'i', 'e']) + def test_adding_50_elements_to_buffer(self): for i in range(50): - self.buffer_2.append(i) - self.assertEqual(self.buffer_2.get(), [45, 46, 47, 48, 49]) + self.buffer.append(i) + self.assertEqual(self.buffer.get(), [45, 46, 47, 48, 49]) if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file From f9276560d10a2c5a44fa57b9c2a5ddd79fc9240e Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 8 May 2020 15:59:26 -0700 Subject: [PATCH 30/39] Update rubric --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a92d0aa68..72d083766 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,8 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric | OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ---------- | ----- | ------- | ------- | ------- | -- | -| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 3 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 9/11 tests (Note that each _assert_ function is a test.) | Solution in `ring_buffer.py` has no syntax or logical errors and passes 11/11 tests (Note that each _assert_ function is a test.)| | -| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | +| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | +| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | | _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | From c20c2aa264f592e255443c89eb66f6dde41d59fe Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 12 Jun 2020 10:59:25 -0700 Subject: [PATCH 31/39] Update rubric --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 72d083766..487a24dc4 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,11 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric -| OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | +| TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ---------- | ----- | ------- | ------- | ------- | -- | -| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | -| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | -| _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | +| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | +| Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | #### Passing the Sprint From 83724dde6d07d9680ac2a9ab8efe55d4d2f14719 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 12 Jun 2020 11:02:09 -0700 Subject: [PATCH 32/39] Fix rubric formatting --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 487a24dc4..03fe728de 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,11 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric -| TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | +| | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ---------- | ----- | ------- | ------- | ------- | -- | | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | -| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | -| Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | +| | Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | #### Passing the Sprint From b5ad8b62f52c850e934ca4e33b9a041babeda4ad Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 12 Jun 2020 11:03:02 -0700 Subject: [PATCH 33/39] Revert --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 03fe728de..72d083766 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,11 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric -| | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | +| OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ---------- | ----- | ------- | ------- | ------- | -- | -| Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | -| | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | -| | Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | +| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | +| _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | #### Passing the Sprint From 4540093393fe1a468af2b1a41d6260f8cc197e44 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 12 Jun 2020 11:04:12 -0700 Subject: [PATCH 34/39] Correctly fix formatting --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 72d083766..4e4ad25be 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,11 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric -| OBJECTIVE | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | -| ---------- | ----- | ------- | ------- | ------- | -- | -| _Student should be able to construct a queue and stack and justify the decision to use a linked list instead of an array._ | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | -| _Student should be able to construct a binary search tree class that can perform basic operations with O(log n) runtime._ | Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | -| _Student should be able to construct a linked list and compare the runtime of operations to an array to make the optimal choice between them._ | Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | +| ----- | ------- | ------- | ------- | -- | +| Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | +| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | +| Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | #### Passing the Sprint From 9956d18e984141dad613354bdbac91b1d23d4418 Mon Sep 17 00:00:00 2001 From: Matt McCarley Date: Fri, 17 Jul 2020 12:44:40 -0700 Subject: [PATCH 35/39] Clarify grading for the SC --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e4ad25be..d52123843 100644 --- a/README.md +++ b/README.md @@ -98,4 +98,4 @@ While credit will be given for a functional solution, only optimal solutions wil #### Passing the Sprint -Score ranges for a 1, 2, and 3 are shown in the rubric above. For a student to have _passed_ a sprint challenge, they need to earn an **average of at least 2** for all items on the rubric. +Score ranges for a 1, 2, and 3 are shown in the rubric above. For a student to have _passed_ a sprint challenge, they need to earn an **at least 2** for all items on the rubric. From 99746d6888a05d7adf436c71b4e7c258becb1367 Mon Sep 17 00:00:00 2001 From: Matt McCarley Date: Fri, 17 Jul 2020 13:51:53 -0700 Subject: [PATCH 36/39] Update README to remove recursion requirement --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d52123843..0e4381f41 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Six seconds is an eternity so you've been tasked with speeding up the code. Can #### Task 3. Reverse a Linked List -Inside of the `reverse` directory, you'll find a basic implementation of a Singly Linked List. _Without_ making it a Doubly Linked List (adding a tail attribute), complete the `reverse_list()` function within `reverse/reverse.py` reverse the contents of the list using recursion, *not a loop.* +Inside of the `reverse` directory, you'll find a basic implementation of a Singly Linked List. _Without_ making it a Doubly Linked List (adding a tail attribute), complete the `reverse_list()` function within `reverse/reverse.py`. For example, ``` From 82bc5df1efe81fe434f997ca89a25928224f80ae Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 17 Jul 2020 13:56:52 -0700 Subject: [PATCH 37/39] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e4381f41..c0d3123d7 100644 --- a/README.md +++ b/README.md @@ -93,8 +93,8 @@ While credit will be given for a functional solution, only optimal solutions wil | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ----- | ------- | ------- | ------- | -- | | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | -| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution of O(n log n) or better | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with a solution of 0(n log n) or better | | -| Task 3. Reverse the contents of a Singly Linked List using Recursion| Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND it has a runtime of O(n) or better | | +| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution that exhibits the appropriate runtime. | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with an appropriate runtime. | | +| Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND exhibits an appropriate runtime. | | #### Passing the Sprint From 404c158b34bd8e7d6de69fdd4b245fa61aa31101 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 17 Jul 2020 13:58:20 -0700 Subject: [PATCH 38/39] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c0d3123d7..26f5ed416 100644 --- a/README.md +++ b/README.md @@ -92,9 +92,9 @@ While credit will be given for a functional solution, only optimal solutions wil ### Rubric | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ----- | ------- | ------- | ------- | -- | -| Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test) | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test)| | -| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution that exhibits the appropriate runtime. | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with an appropriate runtime. | | -| Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once) | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND exhibits an appropriate runtime. | | +| Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests. | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test). | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test). | | +| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds. | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution that exhibits the appropriate runtime. | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with an appropriate runtime. | | +| Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests. | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once). | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND exhibits an appropriate runtime. | | #### Passing the Sprint From d44bd5d714d79f2d735ac971df30ee3a71d6024f Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 17 Jul 2020 14:06:55 -0700 Subject: [PATCH 39/39] Update README.md --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 26f5ed416..7468701de 100644 --- a/README.md +++ b/README.md @@ -62,12 +62,9 @@ buffer.get() # should return ['d', 'e', 'f'] Navigate into the `names` directory. Here you will find two text files containing 10,000 names each, along with a program `names.py` that compares the two files and prints out duplicate name entries. Try running the code with `python3 names.py`. Be patient because it might take a while: approximately six seconds on my laptop. What is the runtime complexity of this code? -Six seconds is an eternity so you've been tasked with speeding up the code. Can you get the runtime to under a second? Under one hundredth of a second? - -*You may not use the built in Python list, set, or dictionary in your solution for this problem. However, you can and should use the provided `duplicates` list to return your solution.* - -(Hint: You might try importing a data structure you built during the week) +Six seconds is an eternity so you've been tasked with speeding up the code. Your goal is to use one of the data structures we built out over the course of this week in order to optimize and improve on the runtime so that it's more efficient than O(n²). +A follow-up question to think about: _*once you've used one of the data structures we implemented over the course of the week*_ in order to improve the runtime of the implementation, what other data structures (including ones from Python's standard library) are also possible candidates for improving the runtime of the implementation? #### Task 3. Reverse a Linked List @@ -93,7 +90,7 @@ While credit will be given for a functional solution, only optimal solutions wil | TASK | 1 - DOES NOT MEET Expectations | 2 - MEETS Expectations | 3 - EXCEEDS Expectations | SCORE | | ----- | ------- | ------- | ------- | -- | | Task 1. Implement a Ring Buffer Data Structure | Solution in `ring_buffer.py` DOES NOT run OR it runs but has multiple logical errors, failing 2 or more tests. | Solution in `ring_buffer.py` runs, but may have one or two logical errors; passes at least 5/6 tests (Note that each function in the test file that begins with `test` is a test). | Solution in `ring_buffer.py` has no syntax or logical errors and passes all tests (Note that each function in the test file that begins with `test` is a test). | | -| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds. | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution that exhibits the appropriate runtime. | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with an appropriate runtime. | | +| Task 2. Runtime Optimization | Student does NOT correctly identify the runtime of the starter code in `name.py` and is not able to optimize it to run in under 6 seconds using a data structure that was implemented during the week. | Student does not identify the runtime of the starter code in `name.py`, but optimizes it to run in under 6 seconds, with a solution that exhibits the appropriate runtime, using a data structure that was implemented during the week | Student does BOTH correctly identify the runtime of the starter code in `name.py` and optimizes it to run in under 6 seconds, with an appropriate runtime using a data structure that was implemented during the week. | | | Task 3. Reverse the contents of a Singly Linked List | Student's solution in `reverse.py` is failing one or more tests. | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests, BUT, the runtime of their solution is not optimal (requires looping through the list more than once). | Student's solution in `reverse.py` is able to correctly print out the contents of the Linked List in reverse order, passing all tests AND exhibits an appropriate runtime. | |