Assignment 2 solutions

Sun Sep 23

(1) slice

We learned about built-in functions take and drop. Use them to write a function slice i k xs, where i and k are integer positions and xs is a list. It should return a list containing the elements of xs between positions i and k (including i, but excluding k). If k <= i or if i is out of bounds, make sure it returns an empty list.

Here are some examples:

ghci> slice 3 6 [0,0,0,1,2,3,0,0,0]
[1,2,3]
ghci> slice 2 2 [1,2,3,4]
[]
ghci> slice 2 3 [1,2,3,4]
[3]
ghci> slice 2 10 [1,2,3,4]
[3,4]
ghci> slice 10 15 [1,2,3,4]
[]
ghci> slice 3 2 [1,2,3,4]
[]

Solutions

Tests

(2) rotate

Write a function rotate that ‘rotates’ a list to the left by n places. My solution uses take, drop, and the list concatenation operator, ++. The following transcript gives some examples of rotate:

ghci> rotate 0 []
[]
ghci> rotate 2 [1,2,3,4,5]
[3,4,5,1,2]
ghci> rotate 5 "abracadabra"
"adabraabrac"

The behavior of the function is unspecified if the n is negative or larger than the size of the list.

Solution

That version works for all the test cases initially provided in the assignment, but we might like it to continue to rotate around if n is greater than the length of the list. In class, we explored a few ways to do that:

Tests

(3) atEvenIndices

Write a recursive function atEvenIndices that takes a list and returns a list that retains the elements at positions 0, 2, 4, etc. — alternating elements. The best way to understand is by example:

ghci> atEvenIndices [1..10]
[1,3,5,7,9]
ghci> atEvenIndices ["Alice", "Bob", "Carl"]
["Alice","Carl"]
ghci> atEvenIndices "university"
"uiest"
ghci> atEvenIndices "trail"
"tal"
ghci> atEvenIndices []
[]
ghci> atEvenIndices [pi]
[3.141592653589793]

Hint: This function actually has two base cases: the empty list, and the list containing just a single element.

Solution

Tests

(4) atOddIndices

This is much like the previous function, but retains the elements at positions 1, 3, 5, etc. That is, it skips the first element but retains alternating elements after that. If you like, you may use the function atEvenIndices to define atOddIndices (but you would have to copy/paste its definition into this question). Some examples:

ghci> atOddIndices [1..10]
[2,4,6,8,10]
ghci> atOddIndices ["Alice", "Bob", "Carl"]
["Bob"]
ghci> atOddIndices "university"
"nvriy"
ghci> atOddIndices "trail"
"ri"
ghci> atOddIndices []
[]
ghci> atOddIndices [pi]
[]

Solution

Tests

(5) countOccurrences

For this problem, you’ll write a list-processing function that consumes a list, but just produces an integer. It should count how many times a particular element appears in a list. Here are some examples:

ghci> countOccurences 5 [1..10]
1
ghci> countOccurences 5 [1,5,2,5,3,5,7,5]
4
ghci> countOccurences 'a' "abracadabra"
5
ghci> countOccurences 'o' "xylophone"
2

You can either write it recursively by pattern-matching on the list, or you can use a combination of existing functions.

Solution

I created two versions of this function. The first one is recursive and directly pattern-matches on the list structure:

The second solution uses length, filter, and an operator section of (==).

You could also write that using a list comprehension with a Boolean predicate:

Tests

Here is a generic set of test cases that can be applied to either solution.

(6) dropFirstLast

Write a function dropFirstLast that takes a list and returns a list containing the same elements in the same order except for the first and last elements. If the list has fewer than three elements, the result should be the empty list. I recommend coding this in terms of drop, take, and length. You also could use the slice function you wrote previously, but you’d have to copy/paste its definition here. Examples:

ghci> dropFirstLast [1..10]
[2,3,4,5,6,7,8,9]
ghci> dropFirstLast "smiley"
"mile"
ghci> dropFirstLast [2,4,6]
[4]
ghci> dropFirstLast "xs"
""
ghci> dropFirstLast "x"
""
ghci> dropFirstLast []
[]

Solution

Tests