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

From HaskellWiki
Jump to navigation Jump to search
m (Make it clear that rnd_permu also uses System.Random)
(53 intermediate revisions by 17 users not shown)
Line 1: Line 1:
 
__NOTOC__
 
__NOTOC__
   
These are Haskell translations of [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html Ninety Nine Lisp Problems].
+
This is part of [[H-99:_Ninety-Nine_Haskell_Problems|Ninety-Nine Haskell Problems]], based on [https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/ Ninety-Nine Prolog Problems] and [http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html 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 21 ==
   
  +
Insert an element at a given position into a list.
<Problem description>
 
   
<pre>
 
 
Example:
 
Example:
<example in lisp>
 
   
  +
<pre>
Example in Haskell:
 
  +
* (insert-at 'alfa '(a b c d) 2)
<example in Haskell>
 
  +
(A ALFA B C D)
 
</pre>
 
</pre>
   
  +
Example in Haskell:
Solution:
 
 
<haskell>
 
<haskell>
  +
P21> insertAt 'X' "abcd" 2
<solution in haskell>
 
  +
"aXbcd"
 
</haskell>
 
</haskell>
   
  +
[[99 questions/Solutions/21 | Solutions]]
<description of implementation>
 
  +
 
  +
 
== Problem 22 ==
 
== Problem 22 ==
   
 
Create a list containing all integers within a given range.
 
Create a list containing all integers within a given range.
   
<pre>
 
 
Example:
 
Example:
Example:
 
* (range 4 9)
 
(4 5 6 7 8 9)
 
   
  +
<pre>
Example in Haskell:
 
  +
* (range 4 9)
Prelude> [4..9]
 
[4,5,6,7,8,9]
+
(4 5 6 7 8 9)
 
</pre>
 
</pre>
   
  +
Example in Haskell:
Solution:
 
  +
 
<haskell>
 
<haskell>
range x y = [x..y]
+
Prelude> range 4 9
  +
[4,5,6,7,8,9]
 
</haskell>
 
</haskell>
   
  +
[[99 questions/Solutions/22 | Solutions]]
Since there's already syntactic sugar for ranges, there's usually no reason to define a function like 'range' in Haskell.
 
  +
 
 
== Problem 23 ==
 
== Problem 23 ==
   
  +
Extract a given number of randomly selected elements from a list.
<Problem description>
 
   
<pre>
 
 
Example:
 
Example:
<example in lisp>
 
   
  +
<pre>
Example in Haskell:
 
  +
* (rnd-select '(a b c d e f g h) 3)
<example in Haskell>
 
  +
(E D A)
 
</pre>
 
</pre>
   
  +
Example in Haskell:
Solution:
 
  +
 
<haskell>
 
<haskell>
  +
Prelude System.Random>rnd_select "abcdefgh" 3 >>= putStrLn
<solution in haskell>
 
  +
eda
 
</haskell>
 
</haskell>
   
  +
[[99 questions/Solutions/23 | Solutions]]
<description of implementation>
 
  +
 
  +
 
== Problem 24 ==
 
== Problem 24 ==
   
  +
Lotto: Draw N different random numbers from the set 1..M.
<Problem description>
 
   
<pre>
 
 
Example:
 
Example:
<example in lisp>
 
   
  +
<pre>
Example in Haskell:
 
  +
* (rnd-select 6 49)
<example in Haskell>
 
  +
(23 1 17 33 21 37)
 
</pre>
 
</pre>
   
  +
Example in Haskell:
Solution:
 
  +
 
<haskell>
 
<haskell>
  +
Prelude System.Random>diff_select 6 49
<solution in haskell>
 
  +
Prelude System.Random>[23,1,17,33,21,37]
 
</haskell>
 
</haskell>
   
  +
[[99 questions/Solutions/24 | Solutions]]
<description of implementation>
 
  +
 
  +
 
== Problem 25 ==
 
== Problem 25 ==
   
  +
Generate a random permutation of the elements of a list.
<Problem description>
 
   
<pre>
 
 
Example:
 
Example:
<example in lisp>
 
   
  +
<pre>
Example in Haskell:
 
  +
* (rnd-permu '(a b c d e f))
<example in Haskell>
 
  +
(B A D C E F)
 
</pre>
 
</pre>
   
  +
Example in Haskell:
Solution:
 
  +
 
<haskell>
 
<haskell>
  +
Prelude System.Random>rnd_permu "abcdef"
<solution in haskell>
 
  +
Prelude System.Random>"badcef"
 
</haskell>
 
</haskell>
   
  +
[[99 questions/Solutions/25 | Solutions]]
<description of implementation>
 
  +
 
  +
 
== Problem 26 ==
 
== Problem 26 ==
   
 
(**) Generate the combinations of K distinct objects chosen from the N elements of a list
 
(**) 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
 
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.
 
well-known binomial coefficients). For pure mathematicians, this result may be great. But we want to really generate all the possibilities in a list.
   
<pre>
 
 
Example:
 
Example:
  +
  +
<pre>
 
* (combinations 3 '(a b c d e f))
 
* (combinations 3 '(a b c d e f))
 
((A B C) (A B D) (A B E) ... )
 
((A B C) (A B D) (A B E) ... )
  +
</pre>
   
 
Example in Haskell:
 
Example in Haskell:
  +
  +
<haskell>
 
> combinations 3 "abcdef"
 
> combinations 3 "abcdef"
 
["abc","abd","abe",...]
 
["abc","abd","abe",...]
</pre>
+
</haskell>
   
  +
[[99 questions/Solutions/26 | Solutions]]
Solution:
 
<haskell>
 
-- 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
 
   
  +
== Problem 27 ==
-- Using list comprehensions
 
combinations :: Int -> [a] -> [[a]]
 
combinations 0 _ = [ [] ]
 
combinations n xs = [ y:ys | y:xs' <- tails xs
 
, ys <- combinations (n-1) xs']
 
   
  +
Group the elements of a set into disjoint subsets.
-- 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)
 
</haskell>
 
   
  +
a) In how many ways can a group of 9 people work in 3 disjoint subgroups of 2, 3 and 4 persons? Write a function that generates all the possibilities and returns them in a list.
== Problem 27 ==
 
   
  +
Example:
<Problem description>
 
   
 
<pre>
 
<pre>
  +
* (group3 '(aldo beat carla david evi flip gary hugo ida))
  +
( ( (ALDO BEAT) (CARLA DAVID EVI) (FLIP GARY HUGO IDA) )
  +
... )
  +
</pre>
  +
  +
b) Generalize the above predicate in a way that we can specify a list of group sizes and the predicate will return a list of groups.
  +
 
Example:
 
Example:
<example in lisp>
 
   
  +
<pre>
Example in Haskell:
 
  +
* (group '(aldo beat carla david evi flip gary hugo ida) '(2 2 5))
<example in Haskell>
 
  +
( ( (ALDO BEAT) (CARLA DAVID) (EVI FLIP GARY HUGO IDA) )
  +
... )
 
</pre>
 
</pre>
   
  +
Note that we do not want permutations of the group members; i.e. ((ALDO BEAT) ...) is the same solution as ((BEAT ALDO) ...). However, we make a difference between ((ALDO BEAT) (CARLA DAVID) ...) and ((CARLA DAVID) (ALDO BEAT) ...).
Solution:
 
  +
  +
You may find more about this combinatorial problem in a good book on discrete mathematics under the term "multinomial coefficients".
  +
  +
Example in Haskell:
  +
 
<haskell>
 
<haskell>
  +
P27> group [2,3,4] ["aldo","beat","carla","david","evi","flip","gary","hugo","ida"]
<solution in haskell>
 
  +
[[["aldo","beat"],["carla","david","evi"],["flip","gary","hugo","ida"]],...]
  +
(altogether 1260 solutions)
  +
  +
27> group [2,2,5] ["aldo","beat","carla","david","evi","flip","gary","hugo","ida"]
  +
[[["aldo","beat"],["carla","david"],["evi","flip","gary","hugo","ida"]],...]
  +
(altogether 756 solutions)
 
</haskell>
 
</haskell>
   
  +
[[99 questions/Solutions/27 | Solutions]]
<description of implementation>
 
 
== Problem 28 ==
 
   
<Problem description>
 
   
<pre>
 
Example:
 
<example in lisp>
 
   
  +
== Problem 28 ==
Example in Haskell:
 
<example in Haskell>
 
</pre>
 
   
  +
Sorting a list of lists according to length of sublists
Solution:
 
<haskell>
 
<solution in haskell>
 
</haskell>
 
   
  +
a) We suppose that a list contains elements that are lists themselves. The objective is to sort the elements of this list according to their length. E.g. short lists first, longer lists later, or vice versa.
<description of implementation>
 
 
== Problem 29 ==
 
   
  +
Example:
<Problem description>
 
   
 
<pre>
 
<pre>
  +
* (lsort '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))
Example:
 
  +
((O) (D E) (D E) (M N) (A B C) (F G H) (I J K L))
<example in lisp>
 
  +
</pre>
   
 
Example in Haskell:
 
Example in Haskell:
<example in Haskell>
 
</pre>
 
   
Solution:
 
 
<haskell>
 
<haskell>
  +
Prelude>lsort ["abc","de","fgh","de","ijkl","mn","o"]
<solution in haskell>
 
  +
Prelude>["o","de","de","mn","abc","fgh","ijkl"]
 
</haskell>
 
</haskell>
   
  +
b) Again, we suppose that a list contains elements that are lists themselves. But this time the objective is to sort the elements of this list according to their <b>length frequency</b>; i.e., in the default, where sorting is done ascendingly, lists with rare lengths are placed first, others with a more frequent length come later.
<description of implementation>
 
 
== Problem 30 ==
 
   
  +
Example:
<Problem description>
 
   
 
<pre>
 
<pre>
  +
* (lfsort '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))
Example:
 
  +
((i j k l) (o) (a b c) (f g h) (d e) (d e) (m n))
<example in lisp>
 
  +
</pre>
   
 
Example in Haskell:
 
Example in Haskell:
<example in Haskell>
 
</pre>
 
   
Solution:
 
 
<haskell>
 
<haskell>
  +
lfsort ["abc", "de", "fgh", "de", "ijkl", "mn", "o"]
<solution in haskell>
 
  +
["ijkl","o","abc","fgh","de","de","mn"]
 
</haskell>
 
</haskell>
   
  +
[[99 questions/Solutions/28 | Solutions]]
<description of implementation>
 
  +
 
  +
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]

Revision as of 20:23, 3 March 2014


This is part of Ninety-Nine Haskell Problems, based on Ninety-Nine Prolog Problems and Ninety-Nine Lisp Problems.

Problem 21

Insert an element at a given position into a list.

Example:

* (insert-at 'alfa '(a b c d) 2)
(A ALFA B C D)

Example in Haskell:

P21> insertAt 'X' "abcd" 2
"aXbcd"

Solutions


Problem 22

Create a list containing all integers within a given range.

Example:

* (range 4 9)
(4 5 6 7 8 9)

Example in Haskell:

Prelude> range 4 9
[4,5,6,7,8,9]

Solutions

Problem 23

Extract a given number of randomly selected elements from a list.

Example:

* (rnd-select '(a b c d e f g h) 3)
(E D A)

Example in Haskell:

Prelude System.Random>rnd_select "abcdefgh" 3 >>= putStrLn
eda

Solutions


Problem 24

Lotto: Draw N different random numbers from the set 1..M.

Example:

* (rnd-select 6 49)
(23 1 17 33 21 37)

Example in Haskell:

Prelude System.Random>diff_select 6 49
Prelude System.Random>[23,1,17,33,21,37]

Solutions


Problem 25

Generate a random permutation of the elements of a list.

Example:

* (rnd-permu '(a b c d e f))
(B A D C E F)

Example in Haskell:

Prelude System.Random>rnd_permu "abcdef"
Prelude System.Random>"badcef"

Solutions


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",...]

Solutions


Problem 27

Group the elements of a set into disjoint subsets.

a) In how many ways can a group of 9 people work in 3 disjoint subgroups of 2, 3 and 4 persons? Write a function that generates all the possibilities and returns them in a list.

Example:

* (group3 '(aldo beat carla david evi flip gary hugo ida))
( ( (ALDO BEAT) (CARLA DAVID EVI) (FLIP GARY HUGO IDA) )
... )

b) Generalize the above predicate in a way that we can specify a list of group sizes and the predicate will return a list of groups.

Example:

* (group '(aldo beat carla david evi flip gary hugo ida) '(2 2 5))
( ( (ALDO BEAT) (CARLA DAVID) (EVI FLIP GARY HUGO IDA) )
... )

Note that we do not want permutations of the group members; i.e. ((ALDO BEAT) ...) is the same solution as ((BEAT ALDO) ...). However, we make a difference between ((ALDO BEAT) (CARLA DAVID) ...) and ((CARLA DAVID) (ALDO BEAT) ...).

You may find more about this combinatorial problem in a good book on discrete mathematics under the term "multinomial coefficients".

Example in Haskell:

P27> group [2,3,4] ["aldo","beat","carla","david","evi","flip","gary","hugo","ida"]
[[["aldo","beat"],["carla","david","evi"],["flip","gary","hugo","ida"]],...]
(altogether 1260 solutions)

27> group [2,2,5] ["aldo","beat","carla","david","evi","flip","gary","hugo","ida"]
[[["aldo","beat"],["carla","david"],["evi","flip","gary","hugo","ida"]],...]
(altogether 756 solutions)

Solutions


Problem 28

Sorting a list of lists according to length of sublists

a) We suppose that a list contains elements that are lists themselves. The objective is to sort the elements of this list according to their length. E.g. short lists first, longer lists later, or vice versa.

Example:

* (lsort '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))
((O) (D E) (D E) (M N) (A B C) (F G H) (I J K L))

Example in Haskell:

Prelude>lsort ["abc","de","fgh","de","ijkl","mn","o"]
Prelude>["o","de","de","mn","abc","fgh","ijkl"]

b) Again, we suppose that a list contains elements that are lists themselves. But this time the objective is to sort the elements of this list according to their length frequency; i.e., in the default, where sorting is done ascendingly, lists with rare lengths are placed first, others with a more frequent length come later.

Example:

* (lfsort '((a b c) (d e) (f g h) (d e) (i j k l) (m n) (o)))
((i j k l) (o) (a b c) (f g h) (d e) (d e) (m n))

Example in Haskell:

lfsort ["abc", "de", "fgh", "de", "ijkl", "mn", "o"]
["ijkl","o","abc","fgh","de","de","mn"]

Solutions