# Difference between revisions of "99 questions/21 to 28"

(Problem 22) |
(→Problem 26) |
||

Line 122: | Line 122: | ||

Solution: |
Solution: |
||

<haskell> |
<haskell> |
||

+ | -- Import the 'tails' function |
||

+ | -- > tails [0,1,2,3] |
||

+ | -- [[0,1,2,3],[1,2,3],[2,3],[3],[]] |
||

import Data.List (tails) |
import Data.List (tails) |
||

+ | -- The implementation first checks if there's no more elements to select, |
||

+ | -- if so, there's only one possible combination, the empty one, |
||

+ | -- otherwise we need to select 'n' elements. Since we don't want to |
||

+ | -- select an element twice, and we want to select elements in order, to |
||

+ | -- avoid combinations which only differ in ordering, we skip some |
||

+ | -- unspecified initial elements with 'tails', and select the next element, |
||

+ | -- also recursively selecting the next 'n-1' element from the rest of the |
||

+ | -- tail, finally consing them together |
||

+ | |||

+ | -- Using list comprehensions |
||

+ | combinations :: Int -> [a] -> [[a]] |
||

+ | combinations 0 _ = [ [] ] |
||

+ | combinations n xs = [ y:ys | y:xs' <- tails xs |
||

+ | , ys <- combinations (n-1) xs'] |
||

+ | |||

+ | -- Alternate syntax, using 'do'-notation |
||

combinations :: Int -> [a] -> [[a]] |
combinations :: Int -> [a] -> [[a]] |
||

combinations 0 _ = do return [] |
combinations 0 _ = do return [] |
||

Line 130: | Line 149: | ||

return (y:ys) |
return (y:ys) |
||

</haskell> |
</haskell> |
||

− | |||

− | This implementation uses the (lazy) list monad to express nondeterministic choice |
||

== Problem 27 == |
== Problem 27 == |

## Revision as of 08:50, 12 December 2006

These are Haskell translations of Ninety Nine Lisp Problems.

If you want to work on one of these, put your name in the block so we know someone's working on it. Then, change n in your block to the appropriate problem number, and fill in the <Problem description>,<example in lisp>,<example in Haskell>,<solution in haskell> and <description of implementation> fields.

## Problem 21

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>

## Problem 22

Create a list containing all integers within a given range.

Example: Example: * (range 4 9) (4 5 6 7 8 9) Example in Haskell: Prelude> [4..9] [4,5,6,7,8,9]

Solution:

```
range x y = [x..y]
```

Since there's already syntactic sugar for ranges, there's usually no reason to define a function like 'range' in Haskell.

## Problem 23

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>

## Problem 24

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>

## Problem 25

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>

## Problem 26

(**) Generate the combinations of K distinct objects chosen from the N elements of a list In how many ways can a committee of 3 be chosen from a group of 12 people? We all know that there are C(12,3) = 220 possibilities (C(N,K) denotes the well-known binomial coefficients). For pure mathematicians, this result may be great. But we want to really generate all the possibilities in a list.

Example: * (combinations 3 '(a b c d e f)) ((A B C) (A B D) (A B E) ... ) Example in Haskell: > combinations 3 "abcdef" ["abc","abd","abe",...]

Solution:

```
-- Import the 'tails' function
-- > tails [0,1,2,3]
-- [[0,1,2,3],[1,2,3],[2,3],[3],[]]
import Data.List (tails)
-- The implementation first checks if there's no more elements to select,
-- if so, there's only one possible combination, the empty one,
-- otherwise we need to select 'n' elements. Since we don't want to
-- select an element twice, and we want to select elements in order, to
-- avoid combinations which only differ in ordering, we skip some
-- unspecified initial elements with 'tails', and select the next element,
-- also recursively selecting the next 'n-1' element from the rest of the
-- tail, finally consing them together
-- Using list comprehensions
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = [ [] ]
combinations n xs = [ y:ys | y:xs' <- tails xs
, ys <- combinations (n-1) xs']
-- Alternate syntax, using 'do'-notation
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = do return []
combinations n xs = do y:xs' <- tails xs
ys <- combinations (n-1) xs'
return (y:ys)
```

## Problem 27

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>

## Problem 28

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>

## Problem 29

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>

## Problem 30

<Problem description>

Example: <example in lisp> Example in Haskell: <example in Haskell>

Solution:

```
<solution in haskell>
```

<description of implementation>