CIS 554 Clojure 1: Exercises
Fall 2015, David Matuszek

# Purposes of this assignment

• To get you started programming in Clojure
• To get you familiar with Clojure syntax
• To get you familiar with the more important list functions.

# Details

Write and test the following functions. Please be sure to get the spelling and capitalization right, and the right number and types of parameters, in order to make testing them feasible.

These are mostly unrelated exercises, to give you some experience with Clojure syntax. The earlier ones depend on recursion, while the latter are best done using some of Clojure's second-order functions.

In some cases, for example reversing a list, you may find Clojure functions that already do exactly what you want. Please don't use them, but rather write the functions yourself.

Most of these functions are defined to work with lists, because my experience in Lisp has been almost entirely with lists. If your functions works with lists, they will probably also work with other kinds of sequences.

## First group

You don't need higher-order functions to program these, but if you see an opportunity to use them, go ahead. Generally, the purpose is to get you used to writing recursive functions the Clojure way.

`(atomic? v)`
Returns `true` if `v` is not any kind of a sequence (check with `seq?`), and `false` otherwise.
`(collatz n)`
Defined for positive integers `n`. If `n` is `1`, return `1`; else if `n` is even, return collatz(`n`/2); else return collatz(3`n` + 1). (Yes, this is just a complicated way to compute `1`.)
`(lookup key list-of-pairs)`
Given an S-expression `key` and a list of ```(key value)``` pairs, return the `value` that corresponds to the `key`, or `nil` if there is no such pair. You can assume that there is only one such pair.
`(my-count lst)`
Returns the number of "top level" elements in `lst`. For example, `(a (b c (d e)) f)` has 3 top level elements; `(b c (d e))` is a single top-level element. `(a b () d)` has 4 top-level elements.
`(count-all lst)`
Returns the total number of non-sequence elements in `lst`, at all levels. For example, `(a (b c () (25) nil) ())` has 5 non-sequence elements: `a`, `b`, `c`, `25`, and `nil`.
`(my-drop n lst)`
Returns the `lst` with the first `n` elements removed. For example, `(my-drop 3 '(a b c d e))` should return `(d e))`. If `n` is equal to or greater than the length of the list `lst`, return the empty list, `()`.
`(my-take n lst)`
Returns a list of the first `n` elements of `lst`. If `lst` has fewer than `n` elements, the result is just `lst`.
`(shallow-reverse lst)`
Reverses the elements of list `lst`. For example, the list `(1 2 (3 4)) `becomes the sequence ```((3 4) 2 1)```.
`(remove-duplicates lst)`
Removes duplicate elements of `lst`. For example, given `(1 2 3 1 4 1 2)`,``` remove-duplicates ```returns a sequence containing the elements ```(1 2 3 4)```, in some order.
`(my-flatten lst)`
Returns as value the sequence `lst `with all inner parentheses (or brackets) removed, returning a "flat" list of values. For example, if` lst` is `(1 (2 3) ( ) (( )) :a)`, the result should be `(1 2 3 :a)`. Hint: Use the predicate `list?`.
`(my-merge lst1 lst2)`
Given two lists of integers, where each list is in ascending order, merge them into a single list that is also in ascending order. For example, if `lst1` is `(3 7 12 19 19 25 30)` and `lst2` is `(4 7 10 12 20)`, the result should be `(3 4 7 7 10 12 12 19 19 20 25 30)`.
`(deep-reverse lst)`
Reverses the elements of `L` at all levels. For example, if `lst` is `(:a (:b :c (:d)) :e)`,``` deep-reverse``` should return `(:e ((:d) :c :b) :a)`.
`(eliminate value lst)`
Returns the sequence `lst` with all occurrences of the `value` removed, at all levels. For example, if `lst` is ```(:a :b (:b :c :d (:a (:b))) :e)```,``` (eliminate :b lst) ```should return```(:a (:c :d (:a ())) :e)```. Note that the `value` may be any value, for example, a sequence.

## Second group

These are all probably best done with higher-order functions, so please use them wherever they seem to work.

`(zap-gremlins text)`
Remove from the given text all invalid ASCII characters. (Valid characters are decimal 10 (linefeed), 13 (carriage return) and 32 through 126, inclusive. Hint: `filter`.
`(rot-13 text)`
Apply the rot-13 transformation to text. This is a simple encoding in which each letter is replaced by the letter 13 further along, end-around. Both uppercase and lowercase letters should be rotated; other characters should be unaffected. You may need the coercions ```(int ch)``` and `(char n)`. Hint: `map`.
`(sqrt n)`
Compute the square root of the positive number `n`, using Newton's method. That is, choose some arbitrary number, say 2, as the initial approximation` r `to the square root; then to get the next approximation, compute the average of` r `and``` n/r```. Continue until you have five significant digits to the right of the decimal point. Do this by taking an infinite series of approximations, `iterate`.
` (longest-collatz lo hi)`
The Collatz sequence eventually converges to 1. Find which starting value, in the range` lo `to` hi` (including both end points) takes the longest to converge. If two values take equally long to converge, return either value.
`(divisors-of n)`
For positive integer `n`, returns the divisors of `n`, other than 1 and `n` itself. For example, 12 has divisors (`2, 3, 4, 6)`. Hint: `mod` and `filter`.

## Unit testing

Write, in a separate file, unit tests for all your methods. Since we haven't talked about testing yet, here's a model for you to follow. Notice the use of `deftest` and `is`.

``````(ns user (:use clojure.test))

(deftest test-shallow-reverse
(is (= '(3 2 1) (shallow-reverse '(1 2 3))))
(is (= '(5 (3 4) 2 1) (shallow-reverse '(1 2 (3 4) 5))))
(is (= () (shallow-reverse ()))) )

(deftest test-deep-reverse
(is (= '(3 2 1) (deep-reverse '(1 2 3))))
(is (= '(5 (4 3) 2 1) (deep-reverse '(1 2 (3 4) 5))))
(is (= () (deep-reverse ()))) )

(run-tests)``````

# Due date:

Zip and turn in your` exercises.clj `and``` exercises-test.clj ```files by 6am, Wednesday September 23 As always, only files submitted to Canvas will be accepted. I do not accept assignments submitted by email.