Submit to: The "Bridge 1: Sorting (2025+)" assignment on the 111 -> 200
Gradescope.
Sorting collections of data is a common task in computing. Most programming languages provide built-in operators for sorting. As a programmer, you need to know how to use these functions. As a computer scientist, however, you should understand how these functions work under the hood.
There are multiple ways to sort a list. Here, we will look at three different methods. In general, a method of computing the answer to a specific problem is called an algorithm.
Below are descriptions of three common sorting algorithms: insertion sort, quicksort, and mergesort. You will implement each one of these algorithms. You may use any of the lists module functions (filter
, etc) in your code that you'd like, EXCEPT for the sort
function.
In each case, the goal is to sort a list of numbers into ascending (increasing) order.
Insertion sort follows the list template that we have discussed in class. Specifically, insertion-sort starts from the following code:
Task: Start with this template and use it to write a function that sorts a list into increasing order.
Note: Every year when we give this task, we get a bunch of solutions in which students write a program that sorts, but doesn't make use of the structure we have given you. For example, a function that searches for the smallest element in the rest and puts it on the front is NOT following the given structure. Your solution should be calling insertion sort directly on the rst (not some other list) as shown here.
Hints and guidance:
insertion-sort
correctly, insertion-sort(rst)
will result in a sorted list. What do you need to do with fst
so that the overall result is also a sorted list?Insertion sort is somewhat brute force: each element gets inserted into the partly sorted list one at a time. Quicksort tries to be more clever. It takes a single element (called the "pivot"), and splits the list into two sublists: one of the items that are smaller (or equal to) the pivot, and one of the items that are larger than the pivot. The algorithm sorts each of these sublists, then appends the sorted lists with the pivot in the middle.
Here's an image showing how the algorithm works. The pivot is the first element in each list (shaded in blue). The purple arrows show the lists of smaller and larger elements that get used in recursive calls. The green line shows how the elements end up ordered in the final list.
Here's a summary of the steps of the algorithm:
quicksort
(recursively) on each of the new lists.If the algorithm isn't yet clear to you, work out a couple of examples on paper, along the lines of the diagram we provided above, but this time using the first element of the list as the pivot. Don't try to write the code until the examples make sense to you. You do not have to turn in the examples.
Task: Write this function with header quicksort(lst :: List<Number>) -> List<Number>
. You may use maps and filters, or explicit recursion, as you wish.
Like Quicksort, Mergesort divides the list and sorts the pieces, but it uses a different splitting strategy. In mergesort, you sort by splitting a list in half by position, sorting each half, then merging the two sorted lists together. When the lists you have to sort have at most one element, there is no need to split and merge – you can just return the lists.
Here's a diagram showing an example (this is from the wikipedia page on mergesort).
Here's a summary of the steps of the algorithm:
The example uses arrays, but you will do this with lists and recursion in Pyret.
Task: Write this function with header mergesort(lst :: List<Number>) -> List<Number>
.
All three of the sorting algorithms were written to sort numbers into increasing order. But we can do other kinds of sorting too: numbers in decreasing order, strings in alphabetical order, words in order of decreasing length, and so on. Sorting is a general-purpose activity: shouldn't we be able to write a sort that handles any of these sorting tasks with a common core implementation?
Task: Pick any ONE of your three sorting implementations and adapt it so it can sort a list with any type of element according to any criterion that the user of your code chooses. In particular, you should end up with:
where any additional parameters needed to capture the criterion go in place of ???
(the list to sort should be the first parameter, you decide the rest).
You only need to provide three examples in your where
block. Each one needs to capture a different list-type/criterion combination.
Hints and details:
sort-general
, this is not what we're looking for. It might help to look back at summary-generator
for project 1, and the related lecture on functions as inputs, to think about how to customize a computation)In a block comment, write a few sentences about what you've learned from these bridge problems. Also mention any questions you have (if any) based on these exercises.
Turn in a file sorting-code.arr
with your code. You don't have to turn in diagrams you drew to understand the algorithms. Make sure you submit this to the the 111 -> 200
Gradescope, not the 111 Gradescope for this semester.
Information about the Autograder
After you submit your work, Gradescope will run our autograder tests and display the results. It is your responsibility to make sure that all nine autograder tests pass.
sorting-code.arr
and that the function names and inputs are exactly as asked for in the handout. This error can also happen if your code has erroneous recursion logic and runs on an infinite loop on one of our test inputs (then, the autograder runs out of memory and cannot give back results). Writing a thorough set of tests can help you diagnose and resolve this issue.The autograder runs our tests on your insertion sort, mergesort, and quicksort implementations. Getting a full autograder score does not guarantee that you passed the assignment – Milda will manually grade your sort-general
and look over your code to make sure that the sorting algorithms were implemented as described in the handout.