# Conference: Week 3

#### Table Of Contents

### ML!

- What are the big ideas?

### 1. List Reverse

Here is some start code for the problems this week: week-3-starter.sml

Without using any built-in SML functions, write an SML function

`list -> 'a list rev : 'a `

that takes a list `l`

as an argument and returns a list of the elements of `l`

in the reversed order. Once you have implemented the function, you should get the following behavior at the SML prompt:

```
1,2,3,4];
- rev [val it = [4,3,2,1] : int list
"a","b","c","d"];
- rev [val it = ["d","c","b","a"] : string list
```

```
fun rev nil = nil
| rev (x::xs) = rev(xs) @ [x];
```

### 2. Palindromes

A palindrome is a word that reads the same from left-to-right and right-to-left. Write an SML function

`string -> bool isPalindrome : `

that takes a string w and returns true if the string is a palindrome and false otherwise. You may want to use the SML function `explode`

, which takes a `string`

and returns a `char list`

containing the individual characters of the string. Once you have implemented the function, you should get the following behavior at the SML prompt:

```
"malayalam";
- isPalindrome val it = true : bool
"myxomatosis";
- isPalindrome val it = false : bool
```

```
fun isPalindrome(m) =
let val e = explode(m) in
rev(e) = eend;
```

### 3. Digital Roots and Additive Persistence

Write an SML function

`int -> int list digits : `

that takes a non-negative integer \(n\) as an argument and returns the list of digits of \(n\) in the order in which they appear in \(n\):

```
3124;
- digits val it = [3,1,2,4] : int list
352663;
- digits val it = [3,5,2,6,6,3] : int list
```

Now write an SML function

`int list -> int listAdd : `

that takes an integer list \(l\) and returns the sum of the elements of \(l\):

```
1,2,3,4];
- listAdd [val it = 10 : int
1,~2,3,5];
- listAdd [val it = 7 : int
```

Consider the process of taking a number, adding its digits, then adding the digits of the number derived from it, etc., until the remaining number has only one digit. The number of additions required to obtain a single digit from a number \(n\) is called the additive persistence of \(n\), and the digit obtained is called the digital root of \(n\). For example, the sequence obtained from the starting number \(9876\) is \(9876 \rightarrow 30 \rightarrow 3\), so \(9876\) has an additive persistence of \(2\) and a digital root of \(3\). Write two SML functions

```
int -> int
additivePersistence : int -> int digitalRoot :
```

that take integer arguments \(n\) and return respectively the additive persistence and the digital root of \(n\):

```
9876;
- additivePersistence val it = 2 : int
9876;
- digitalRoot val it = 3 : int
```

*There are two ways to do this. Write two completely separate functions, or since they will be very similar, write one function that computes both the additivePersistance and digitalRoot and returns those two values as a tuple. Then additivePersistance and digitalRoot are one-line functions that just call the helper and extract the appropriate value.*

```
fun digits n =
if n < 10 then [n]
else (digits (n div 10)) @ [n mod 10];
fun listAdd nil = 0
| listAdd (x::xs) = listAdd(xs) + x;
fun persistanceAndRoots n =
let val sum = listAdd(digits n) in
if (sum < 10) then (1, sum)
else
let val (ap, root) = persistanceAndRoots(sum) in
1, root)
(ap + end
end;
fun additivePersistence n = #1(persistanceAndRoots(n));
fun digitalRoot n = #2(persistanceAndRoots(n));
```

### 4. List Cleaning

Without using any built-in SML functions, write a function

`list -> ''a list clean: ''a `

that takes a list `l`

and returns the list of elements of `l`

with the duplicates, i.e. second, third, etc. occurrences, removed, and where the remaining elements appear in the same order as in `l`

. Once you have implemented the function, you should get the following behavior at the SML prompt:

```
1,6,2,4,12,2,13,6,9];
- clean [val it = [1,6,2,4,12,13,9] : int list
```

You’ll probably want to use our `contains`

function from lecture:

```
fun contains x nil = false
orelse contains x ys; | contains x (y::ys) = x = y
```

```
fun contains x nil = false
orelse contains x ys;
| contains x (y::ys) = x = y
fun cleanList list =
(* keep *first* occurence of each element in cleaned *)
let fun helper cleaned nil = cleaned
| helper cleaned (x::xs) = if (contains x cleaned) then helper xs cleaned
else x :: (helper xs x::cleaned)
in
list
helper nil end;
```

Alternative that’s less efficient but more expedient to write:

```
fun contains x nil = false
orelse contains x ys;
| contains x (y::ys) = x = y
fun cleanList list =
(* keep *last* occurence of each element *)
let fun helper nil = nil
if (contains x xs) then helper xs
| helper (x::xs) = else x::(helper xs)
in
list)))
rev(helper(rev(end;
```