Fall 2023 Haskell Exam

Problem 1

An arithmetic sequence is one in which the jump between numbers is constant. Write pure function isArithmetic that accepts a 3-tuple of Int as its sole parameter. It returns true if and only if the sequence is arithmetic. (But note that a conditional expression is entirely unnecessary here.) For example:

> isArithmetic (0, 2, 4)
True
> isArithmetic (9, 9, 9)
True
> isArithmetic (21, 15, 9)
True
> isArithmetic (0, 7, 10)
False

Problem 2

Write pure function singles that accepts a list of String and Int tuples. Each tuple names an item and how many times it occurs. The function returns a flat list in which each item occurs the specified number of times. For example:

> singles [("tear", 2), ("lock of hair", 1)]
["tear", "tear", "lock of hair"]

Builtin functions concat and replicate are useful here.

Problem 3

Write pure function wordogram that reports how many times words of various lengths appear in a list of words. It accepts two parameters in the following order:

It returns a list of tuples whose first element is the corresponding word length and whose second element is the number of words of that length in the list. For example:

> wordogram [5, 2, 1, 3, 6] ["Art", "is", "a", "lie", "that", "makes", "us", "realize", "truth"]
[(5, 2), (2, 2), (1, 1), (3, 2), (6, 0)]

There are two 5-letters words: makes and truth. There are two 2-letters words: is and us. There is one 1-letter word: a. There are two 3-letters words: Art and lie. There are zero 6-letter words.

Problem 4

Some data is circular, like colors on a color wheel and directions on a compass. Using data, define Color and Direction with the variants shown on these wheels:

Have the types implement Show and Eq.

The variants on these wheels have opposites. We'd like a uniform way of finding a variant's opposite. Define a typeclass named Opposable that imposes a pure function named opposite. Given a variant, it returns its opposite. Make Color and Direction instances of this typeclass. Then we can make calls like these:

> opposite NW
SE
> opposite E
W
> opposite Red
Green
> opposite Green
Red

Problem 5

Write a main that reads in the file whose path is passed as a command line argument. The file contains a bunch of numbers, one per line. Print the five biggest numbers to standard output in descending order. For example, suppose a file has these lines:

234.28
4568.52
567.98
3324.63
45.34
905.07
294.35
2456.56

When given this file, your program produces this output:

4568.52
3324.63
2456.56
905.07
567.98

Problem 6

A file on disk is a one-dimensional sequence of characters. For example:

I'm still trying everything\nTo keep you looking at me\n

The sequence is indexed by a single 0-based Int. The first m is at index 2, the first linefeed is at index 27, and the T at index 28.

Such sequences are often read and split into a list of lines. For example:

["I'm still trying everything", "To keep you looking at me"]

Characters in the two-dimensional lines list are indexed by a row and column, both 0-based. Write pure function indexToPair that accepts a one-dimensional index as an Int and a list of String. The function returns the row and column at which the character occurs—as a tuple. For example, these two calls find the row-column pairs of the first m, the first linefeed, and T:

> indexToPair 2 ["I'm still trying everything", "To keep you looking at me"]
Just (0, 2)
> indexToPair 27 ["I'm still trying everything", "To keep you looking at me"]
Just (0, 27)
> indexToPair 28 ["I'm still trying everything", "To keep you looking at me"]
Just (1, 0)

Assume each line ends in a linefeed character (\n). Return the tuple as a Maybe that is Nothing if the index isn't valid. Writing a recursive helper function is fair game and probably a good idea.