Advertisement
Kchewz

Untitled

Mar 29th, 2019
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.55 KB | None | 0 0
  1. Pycharm error where it is running hidden in the background
  2. du -d 1
  3. rm -rf ./Pycharm.../
  4.  
  5. rm -rf .PyCharmCE2013.2/system
  6.  
  7. TO IMPORT FILE INTO PYCHARM PYTHON CONSOLE:
  8. from timsort import *
  9.  
  10. FOR EXAM, IF YOU ARE ABLE TO EXPLAIN TO YOURSELF WHAT YOU WROTE, YOU WILL BE FINE. I RECOMMEND REDOING LABS, GOING OVER PAST EXAMS WITH YOUR FRIENDS (show them utm past exams repo), REDOING PREPS, GOING OVER ASSIGNMENTS AND REDOING THE MIDTERM.
  11. --------------------------------------------------------------------------------------------------------------------------
  12. Todays lab is more of a coding challenge. In lecture you probably covered none mutable sorting algorithms like bubble or selection sort which just return a new list. Now we are strictly working with a mutating algorithm Mergesort actually mutates the list.
  13.  
  14. This lab is rather difficult and Bogdan left in the TA notes most students will not get passed the Third task. Thus feel free to complete the first two tasks and attempt the fifth one because they are the shortest (in terms of code) and I believe the most important takeaways for this lab. OR if youd like, feel free to study for this or other exams it really doesnt matter. I will take up task 1, 2 , 5 and maybe 3 at the end but for now, please feel free to work on whatever youd like. There is still a quiz at the end.
  15.  
  16. TASK 1:------------------------------------------------
  17. The hardest part of understanding task 1 is understanding what a "run" is, so lets cover this together.
  18. """
  19. >>> find_runs([1, 4, 7, 10, 2, 5, 3, -1])
  20. [(0, 4), (4, 6), (6, 7), (7, 8)]
  21. >>> find_runs([0, 1, 2, 3, 4, 5])
  22. [(0, 6)]
  23. >>> find_runs([10, 4, -2, 1])
  24. [(0, 1), (1, 2), (2, 4)]
  25. """
  26.  
  27. What does this output mean? It goes through the indexes of sorted arrays within the list. Each starts at index X and go up to the index that is still sorted but remember its not inclusive.
  28.  
  29. def find_runs(lst: list) -> List[Tuple[int, int]]:
  30. runs = []
  31.  
  32. # Keep track of the start and end points of a run.
  33. run_start = 0
  34. run_end = 1
  35. while run_end < len(lst):
  36. # How can you tell if a run should continue?
  37. # How can you tell if a run is over?
  38. if lst[run_end - 1] <= lst[run_end]:
  39. run_end += 1
  40. else:
  41. # Once a run is over, make sure you add it to runs!
  42. runs.append((run_start, run_end))
  43. run_start = run_end
  44. run_end += 1
  45.  
  46. # Append the last run
  47. runs.append((run_start, run_end))
  48. return runs
  49.  
  50. So where were doing here is starting at the first index. We keep iterating our run_end index counter until we reach an element that is out of order. Once its out of order, we append our tuple of indexes including the index we started at and the index we went up to but not including. Now we reset the run_start by making it the current end of the run we ended and iterate plus to begin the next iteration. Once the loop finishes, we will need to append the final run without going out of range so we manually add the last element to the latest run.
  51.  
  52. TASK 2:------------------------------------------------
  53. So now that we have a list of numbers and the list of runs (that is a list of sorted indexes), we want to simple merge all the indexed tuples into one final list. So if we take the example in the doctest:
  54. lst = [1, 4, 7, 10, 2, 5, 3, -1]
  55. This will produce the runs [(0, 4), (4, 6), (6, 7), (7, 8)] which if we were to break up into individual sub lists, we have [1,4,7,10] and [2, 5] and [3] and [-1]
  56. So we want to build a function that will merge this 4 sublists into a single list that will output
  57. [-1,1,2,3,4,5,7,10]
  58. def timsort(lst: list) -> None:
  59. runs = find_runs(lst)
  60.  
  61. # Treat runs as a stack and repeatedly merge the top two runs
  62. # When the loop ends, the only run should be the whole list.
  63. # HINT: you should be able to use the "merge" function provided
  64. # in this file.
  65.  
  66. while len(runs) > 1:
  67. mid1, end = runs.pop()
  68. start, mid2 = runs.pop()
  69.  
  70. _merge(lst, start, mid1, end)
  71. runs.append((start, end))
  72.  
  73. So what we are doing is applying the mergesort function onto the indexes we are given, one at a time. So when we can our list of tuples of indexes from find_runs, we essentially parse through those runs, getting the indexes needed to call mergesort(). So lets go through the first iteration together. If we have the runs [(0, 4), (4, 6), (6, 7), (7, 8)], we want to perform two pops. Why? Because the _merge() function sort needs 3 arguments, the starting index, the middle index and the ending index. So from these two tuples that we popped from the end of runs [(6, 7), (7 ,8)], what should be our 3 indexes? It should be start at index 6, 7 is our middle index and 8 is our end index. So with those values, we can simply call _merge() to mutate out list. Now I mentioned we keep creating a new tuple each time we call _merge() and we need to update runs everytime we finishing executing _merge() so thus, we create a new tuple with the starting and ending indexes we used and append that to runs to it can be used for the next iteration.
  74.  
  75. If you wanted to, you could have also done pop(0) or any other alternative where you are working with the first or front of the list of runs, it would still work the same. What the code is doing algorithmically is calling mergesort on two tuples, creating a new one, then calling mergesort on the newly created tuple and the next tuple in runs and so on till all indexes have been properly merge sorted.
  76.  
  77. TASK 3:------------------------------------------------
  78. def find_runs2(lst: list) -> List[Tuple[int, int]]:
  79. runs = []
  80.  
  81. # Keep track of the start and end points of a run.
  82. run_start = 0
  83. run_end = 1
  84.  
  85. # Hint: this is similar to find_runs, except
  86. # you'll need to keep track of whether the "current run"
  87. # is ascending or descending.
  88. asc = None
  89.  
  90. while run_end < len(lst):
  91. if asc is None:
  92. # Figure out if the run is ascending or descending
  93. # Note: a better approach would make the = case
  94. # not set asc, so that we can make [3, 3, 2] one run
  95. asc = lst[run_end - 1] <= lst[run_end]
  96. run_end += 1
  97. elif asc and lst[run_end - 1] <= lst[run_end]:
  98. # Continue an ascending run
  99. run_end += 1
  100. elif not asc and lst[run_end - 1] >= lst[run_end]:
  101. # Continue a descending run
  102. run_end += 1
  103. else:
  104. # Once a run is over, make sure you add it to runs!
  105. runs.append((run_start, run_end))
  106.  
  107. # If the run was descending, reverse it.
  108. if asc is False:
  109. lst[run_start:run_end] = reversed(lst[run_start:run_end])
  110.  
  111. run_start = run_end
  112. run_end += 1
  113. asc = None
  114.  
  115. # Append the last run. The check is necessary because the last run
  116. # detected in the loop might already have ended at the end of the list.
  117. if run_end == len(lst):
  118. runs.append((run_start, run_end))
  119.  
  120. # If the run was descending, reverse it.
  121. if asc is False:
  122. lst[run_start:run_end] = reversed(lst[run_start:run_end])
  123.  
  124. return runs
  125. TASK 4:------------------------------------------------
  126.  
  127. TASK 5:------------------------------------------------
  128. For this task, your code should work the exact same are the given _merge() function so you can create doctests where you have an unsorted list and given the index 0 and len(lst) -1, (your start and end indexes) you new _merge2() function should be able to sort the list.
  129.  
  130. def _merge2(lst: list, start: int, mid: int, end: int) -> None:
  131. """Sort the items in lst[start:end] in non-decreasing order.
  132.  
  133. Precondition: lst[start:mid] and lst[mid:end] are sorted.
  134. """
  135. # Store the "A" run in a temporary list.
  136. temp = lst[start:mid]
  137. left = 0
  138. right = mid
  139. curr = start # Current position in lst to fill in.
  140.  
  141. while left < len(temp) and right < end:
  142. if temp[left] < lst[right]:
  143. lst[curr] = temp[left]
  144. left += 1
  145. else:
  146. lst[curr] = lst[right]
  147. right += 1
  148. curr += 1
  149.  
  150. # Copy over remaining elements
  151. lst[curr:curr + len(temp) - left] = temp[left:]
  152.  
  153. So what _merge2() is doing is pretty silly because by the PreCondition, we assume already that the inputted list is not entirely sorted but, its sorted in two separate halves. For example the input would could have would be something like [1,3,5,7,2,4,6,8] right? We have a list that is not in sorted order but it has two halves where the [start:mid] list is the list [1,3,5,7] and the [mid:end] list is the list [2,4,6,8]. So what we are trying to do is manually merge the two lists by overriding our already existing list. Ignoring code, what we are trying to is create a duplicate of the first half list, in our case [1,3,5,7] then we want to iterate through all the indexes in both lists and make that comparison. So we start at the front of both lists, we have [1,3,5,7] and [2,4,6,8]. Looking at our duplicate of [start:mid], we compare [1] with [2], see that 1 < 2 so we set the first index in our list to [1]. Moving onto the next index, we compare [3] with [2], see that 2 < 3 so we set the second index in our list to [2] and so on. The confusing part I believe it how we are mutating the same list we are working on, not returning a new list. You can use temporary lists if you would like, but thats part of the challenge. If we were to do this csc108 style, we would create a new list and compare values between the two lists. So you would have something like this:
  154.  
  155. lst1 = [1,3,5,7]
  156. lst2 = [2,4,6,8]
  157. result = []
  158. leftindex = 0
  159. rightindex = 0
  160. for i in range(len(lst1)):
  161. if lst1[rightindex] > lst2[leftindex]:
  162. result.append(lst1[rightindex])
  163. rightindex++;
  164. else:
  165. result.append(lst2[leftindex])
  166. leftindex++;
  167. return result + [rest of the remaining lst]
  168.  
  169.  
  170. And we reach the end of our lists, since we dont always know what the length of the sublists are, we need to append all the remaining elements. So say we had the lists [1,3,5,7] and [2,4,6,8,10,12,14], our while loop will only iterate through the first 4 indexes (obviously because if we tried to iterate to the fifth index of the first sublist, we would be thrown an error), then if our code is successfully done in the while loop, we should have the result list of [1,2,3,4,5,6,7,8] and we are left with a sublist [10,12,14] so since we know that this list is sorted by the precondition, we can simply append it to our resulting list to get the value [1,2,3,4,5,6,7,8,10,12,14].
  171. TASK 6:------------------------------------------------
  172.  
  173. ---------------------------------------------------------------------------------------------------------------------------
  174. Quiz 11:
  175. def remove_duplicates(lst):
  176. """Return a sorted list containing the same values as <lst>, but without duplicates.
  177.  
  178. Precondition: <lst> is sorted.
  179.  
  180. @type lst: list
  181. @rtype list
  182.  
  183. >>> remove_duplicates([1, 2, 2, 2, 3, 10, 10, 20])
  184. [1, 2, 3, 10, 20]
  185. """
  186. new_lst = []
  187. prev_item = None
  188. for item in lst:
  189. if item != prev_item:
  190. new_lst.append(item)
  191. prev_item = item
  192. return new_lst
  193.  
  194.  
  195. Know the property that the list is sorted. So we can check that every item is not equal to the next item, and thus we can append it to our new list. Noticed I said NEW LIST because this function is non-mutating the inputted list, we need to create a new one. HOMEWORK: TRY TO MAKE THIS FUNCTION WORK ON THE ON THE LIST THATS PASSED IN. IE DONT RETURN A NEW LIST, RETURN THE SAME ONE.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement