Sorting
Insertion sort
- to insert an element i into an already sorted list l, simply
walk down the list until we find an item greater than or equal
to i---then put i into the list; and
- given an unsorted list, insert each element into the recursive result of sorting the list.
Exercise: 2 stars, standard (insert_sorted)
First, let's write a function that inserts a number into a list that is already sorted ascending. Before you start writing the code, decide what each of the following expressions should evaluate to.insert_sorted 5 [] = ???
insert_sorted 5 [10] = ???
insert_sorted 5 [1;6;0]
Fixpoint insert_sorted (i:nat) (l: list nat) : list nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Exercise: 1 star, standard (sort)
Now write the sorting function: given an arbitrary list of nats, you should return a sorted list. Use insert_sorted. Be sure to test it out on a variety of inputs!
Fixpoint sort (l: list nat) : list nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Compute (sort [10;9;8;7;6;5;4;3;2;1]).
Compute (sort [3;1;4;1;5;9;2;6;5;3;5]).
(* ===> 1;1;2;3;3;4;5;5;5;6;9 *)
Compute (insert_sorted 7 [1; 3; 4; 8; 12; 14; 18]).
(* ===> 1; 3; 4; 7; 8; 12; 14; 18 *)
Compute (sort [3;1;4;1;5;9;2;6;5;3;5]).
(* ===> 1;1;2;3;3;4;5;5;5;6;9 *)
Compute (insert_sorted 7 [1; 3; 4; 8; 12; 14; 18]).
(* ===> 1; 3; 4; 7; 8; 12; 14; 18 *)
What makes a sort correct?
Definition l0 : list nat := [].
Definition l1 : list nat := [1; 2; 3].
Definition l2 : list nat := [2; 1; 3].
Definition l3 : list nat := [5].
Definition l4 : list nat := [5; 5; 5; 1; 2; 1; 2].
Definition l1 : list nat := [1; 2; 3].
Definition l2 : list nat := [2; 1; 3].
Definition l3 : list nat := [5].
Definition l4 : list nat := [5; 5; 5; 1; 2; 1; 2].
The easiest way to not be a sort is to have the wrong type. Sorts
should take lists to lists!
Next, a sort should return a list that, is, well, sorted.
The returned list shouldn't miss any elements from the input list,
either!
Definition const_empty_list (l : list nat) : list nat := [].
Definition head_only (l : list nat) : list nat :=
match l with
| [] ⇒ []
| h :: _ ⇒ [h]
end.
Definition head_only (l : list nat) : list nat :=
match l with
| [] ⇒ []
| h :: _ ⇒ [h]
end.
Elements that weren't in the input list shouldn't appear!
Exercise: 2 stars, standard (remove_all)
Complete the definition of remove_all. Running remove_all n l should return a list that is the same as l, but with no occurrences of n.
Fixpoint remove_all (n : nat) (l : list nat) : list nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Exercise: 2 stars, standard (unique)
Complete the definition of unique, where unique l should compute the unique elements of l in the same order, i.e., it should return a list (a) with no duplicate elements and (b) doesn't do any other reordering.
Fixpoint unique (l : list nat) : list nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Identifying sortedness
- It takes a list and returns another list, sorted ascending.
- The output list is a permutation of the input list, i.e., the elements of the output list are just a rearrangement of the input elements, with no additions or deletions.
Exercise: 3 stars, standard (is_sorted)
Complete is_sorted, which should return true when l is sorted.match [1;2;3;4;5] with
| ...
| h1::((h2::t2) as t1) ⇒ ... (h1=1; h2=2; t2 = [3;4;5]; t1 = [2;3;4;5])
Fixpoint is_sorted (l : list nat) : bool (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Exercise: 4 stars, standard (is_permutation_of)
Write a function is_permutation_of : list nat → list nat → bool that returns true when the first list is a permutation of the second. (Though if l1 is a permutation of l2, then l2 is a permuation of l1---the property is symmetric.)
Fixpoint is_permutation_of (l1 : list nat) (l2 : list nat) : bool (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Write at least ten test cases---at least five in each list---that
exercise is_permutation_of.
Definition permutation_true_tests : list (list nat × list nat) := [(* FILL IN HERE *)
].
Definition permutation_false_tests : list (list nat × list nat) := [(* FILL IN HERE *)
].
].
Definition permutation_false_tests : list (list nat × list nat) := [(* FILL IN HERE *)
].
This should compute to true.
Compute (allb (map (fun (p:(list nat × list nat)) ⇒ let (x,y) := p in is_permutation_of x y) permutation_true_tests))
&& (allb (map (fun (p:(list nat × list nat)) ⇒ let (x,y) := p in negb (is_permutation_of x y)) permutation_false_tests)).
☐
&& (allb (map (fun (p:(list nat × list nat)) ⇒ let (x,y) := p in negb (is_permutation_of x y)) permutation_false_tests)).
☐
(* 2022-01-12 10:20 *)