Document

Combinatorial Functions
Recursion for problem solving
cs7120 (Prasad)
L10-COMB-FN
1
Enumerating Initial segments (prefixes)
inits [1,2,3] = [[],[1],[1,2],[1,2,3]]
inits [2,3] = [ [], [2], [2,3] ]
fun inits
[]
=
[[]]
| inits (x::xs) =
[]:: (map (fn ys => x::ys)
(inits xs)
);
fun inits
| inits
cs7120 (Prasad)
[]
xs
=
[[]]
= (inits (init xs))@[xs];
L10-COMB-FN
2
Enumerating Subsequences
subseq [2,3] =
[[],[2],[3],[2,3]];
subseq [1,2,3] =
[[], [1],[2],[3], [1,2],[1,3],[2,3],[1,2,3] ];
fun subseq [] = [[]]
| subseq (x::xs) =
let val ss = subseq xs
in ss@(map (fn ys => x::ys) ss)
end;
cs7120 (Prasad)
L10-COMB-FN
3
Enumerating permutations
perms [2]
= [[2]]
perms [1,2] = [[1,2], [2,1]]
perms [0,1,2] = [[0,1,2],[1,0,2],[1,2,0], [0,2,1],[2,0,1],[2,1,0]]
fun interleave x
[]
= [[x]]
| interleave x (y::ys) = (x::y::ys) ::
(map(fn xs=>y::xs)(interleave x ys));
fun perms
[]
= [[]]
| perms (x::xs) =
foldr (op @) []
(map (interleave x) (perms xs)) ;
cs7120 (Prasad)
L10-COMB-FN
4
List partitions
• The list of non-empty lists [L1,L2,…,Lm]
forms a list-partition of a list L iff
concat [L1,L2,…,Lm] = L
[1,2]
-> [[[1,2]], [[1],[2]]]
[0,1,2] -> [ [[0,1,2]],
[[0,1],[2]],
[[0],[1,2]],
[[0],[1],[2]] ]
cs7120 (Prasad)
L10-COMB-FN
5
Counting problem
fun cnt_lp 0 = 0
| cnt_lp 1 = 1
| cnt_lp n = 2 * (cnt_lp (n-1));
(* cnt_lp n = 2^(n-1) for n > 0 *)
Property:
=
cnt_lp (length xs)
(length (list_partition xs))
cs7120 (Prasad)
L10-COMB-FN
6
Constructing List Partitions
fun lp
[]
=
[]
| lp (x::[])
= [ [[x]] ]
| lp (y::x::xs) =
let val aux = lp (x::xs) in
(map (fn ss => [y]::ss) aux)
@
(map (fn ss => (y::(hd ss))
:: (tl ss)) aux)
end;
cs7120 (Prasad)
L10-COMB-FN
7
Set partition
• The set of (non-empty) sets [s1,s2,…,sm] forms
a set partition of s iff the sets si’s are
collectively exhaustive and pairwise-disjoint.
• E.g., set partitions of {1,2,3} ->
{
{{1,2,3}},
{ {1}, {2,3}},
{{1,2}, {3}},
{{2}, {1,3}},
{ {1},{2},{3}}
}
(Cf. list partition, number partition, etc.)
cs7120 (Prasad)
L10-COMB-FN
8
Divide and Conquer
m-partition of
{1,2,3}
1 occurring with
with a part in
m-partition of
{2,3}
solitary part {1}::
(m-1)-partition of
{2,3}
2-partitions of {1,2,3}
=
{ { {1},{2,3}} }
U
{ {{1,2},{3} } , { {2},{1,3} } }
cs7120 (Prasad)
L10-COMB-FN
9
Counting problem
fun cnt_m_sp 1 n = 1
| cnt_m_sp m n =
if
m > n
then 0
else if m = n then 1
else (cnt_m_sp (m-1) (n-1)) +
(m * (cnt_m_sp m (n-1)));
• Dependency (visualization)
– Basis: Row 1 and diagonal (Half-plane inapplicable)
– Recursive step: Previous row, previous column
cs7120 (Prasad)
L10-COMB-FN
10
(cont’d)
upto 3 6 = [3,4,5,6]
fun upto m n =
if
(m > n) then []
else if (m = n) then [m]
else m:: upto (m+1) n;
fun cnt_sp n =
foldr (op +) 0
(map (fn m => cnt_m_sp m n)
(upto 1 n));
cs7120 (Prasad)
L10-COMB-FN
11
Constructing set partitions
fun set_parts s =
foldr (op@) []
( map (fn m => (m_set_parts m s))
(upto 1 (length s)) );
fun ins_all e
[]
= []
| ins_all e (s::ss) =
(((e::s)::ss) ::
( map (fn ts => s :: ts)
(ins_all e ss) ) );
cs7120 (Prasad)
L10-COMB-FN
12
fun m_set_parts 1 s = [[s]]
| m_set_parts m (s as hs::ts)=
let val n = (length s) in
if m > n then []
else if m = n then
[foldr (fn (e,ss)=>[e]::ss ) [] s]
else let
val p1 = (m_set_parts (m-1) ts)
val p2 = (m_set_parts m ts)
in
(map (fn ss => [hs]::ss) p1)
@
(foldr (op@) [](map (ins_all hs) p2 ))
end
end;
cs7120 (Prasad)
L10-COMB-FN
13