1. Trang chủ
  2. » Công Nghệ Thông Tin

Algorithms for programmers phần 8 ppt

21 254 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 21
Dung lượng 304,74 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

A strictly monotone sequence is a monotone sequence that has no identical pairs of elements.. The testturns out to be slightly easier: template int is_strictly_monotoneconst Type *f, ul

Trang 1

A strictly monotone sequence is a monotone sequence that has no identical pairs of elements The test

turns out to be slightly easier:

template <typename Type>

int is_strictly_monotone(const Type *f, ulong n)

// return

// +1 for strictly ascending order

// -1 for strictly descending order

A sequence is called convex if it starts with an ascending part and ends with a descending part A concave

sequence starts with a descending and ends with an ascending part Whether a monotone sequence isconsidered convex or concave again is a matter of convention (i.e you have the choice to consider the first

or the last element as extremum) Lacking a term that contains both convex and concave the followingroutine is called is_convex:

template <typename Type>

long is_convex(Type *f, ulong n)

//

// return

// +val for convex sequence (first rising then falling)

// -val for concave sequence (first falling then rising)

// else 0

//

// val is the (second) index of the first pair at the point

// where the ordering changes; val>=n iff seq is monotone

Trang 2

if ( k==n ) return s; // sequence is monotone

// check that the ordering does not change again:

if ( s>0 ) // was: ascending > descending

The test for strictly convex (or concave) sequences is:

template <typename Type>

long is_strictly_convex(Type *f, ulong n)

//

// return

// +val for strictly convex sequence

// (i.e first strictly rising then strictly falling)

// -val for strictly concave sequence

// (i.e first strictly falling then strictly rising)

// else 0

//

// val is the (second) index of the first pair at the point

// where the ordering changes; val>=n iff seq is strictly monotone

// check that the ordering does not change again:

if ( s>0 ) // was: ascending > descending

Trang 4

Selected combinatorical algorithms

This chapter presents selected combinatorical algorithms The generation of combinations, subsets, titions, and pairings of parentheses (as example for the use of ‘funcemu’) are treated here Permutationsare treated in a seperate chapter because of the not so combinatorical viewpoint taken with most of thematerial (especially the specific examples like the revbin-permutation) there

par-TBD: debruijn sequences via primitive polys possibly using bitengine

10.1 Offline functions: funcemu

Sometimes it is possible to find recursive algorithm for solving some problem that is not easily solvediteratively However the recursive implementations might produce the results in midst of its calling graph.When a utility class providing a the results one by one with some next call is required there is an apparentproblem: There is only one stack available for function calls1 We do not have offline functions.

As an example consider the following recursive code2

1 True for the majority of the programming languages.

2 given by Glenn Rhoads

152

Trang 5

template <typename Type>

class funcemu

{

public:

ulong tp_; // sTate stack Pointer

ulong dp_; // Data stack Pointer

ulong *t_; // sTate stack

Type *d_; // Data stack

ulong stpeek() const { return t_[tp_-1]; }

void stpeek(ulong &x) { x = t_[tp_-1]; }

void push(Type x, Type y) { push(x); push(y); }

void push(Type x, Type y, Type z) { push(x); push(y); push(z); }

void push(Type x, Type y, Type z, Type u)

{ push(x); push(y); push(z); push(u); }

void peek(Type &x) { x = d_[dp_-1]; }

void peek(Type &x, Type &y)

Trang 6

void poke(Type x, Type y)

#define PAREN 0 // initial state

fe_->pop(4); fe_->stpop(); // emu_return to caller

if ( fe_->more() ) goto redo;

return 0; // return from top level emu_call

Trang 7

10.2 Combinations in lexicographic order

The combinations of three elements out of six in lexicographic order are

Trang 8

x_[j]; // move down edge element

// and move rest of block to high end:

while ( ++j < k_ ) x_[j] = n_ - k_ + j;

return 1;

}

const ulong * data() { return x_; }

friend ostream & operator << (ostream &os, const comb_lex &x);

};

[FXT: class comb lex in comb/comblex.h]

The listing at the beginning of this section can then be produced by a simple fragment like

Trang 9

}

while ( comb.next() );

Cf [FXT: file demo/comblex-demo.cc]

10.3 Combinations in co-lexicographic order

The combinations of three elements out of six in co-lexicographic order are

Trang 10

x_[j]; // move edge element down

// attach rest of low block:

while ( 0!=j ) x_[j] = x_[j+1] - 1;

return 1;

}

const ulong * data() { return x_; }

friend ostream & operator << (ostream &os, const comb_colex &x);

};

[FXT: class comb colex in comb/combcolex.h]

For the connection between lex-order and colex-order see section 7.8

Usage is completely analogue to that of the class comb lex, cf [FXT: file demo/combcolex-demo.cc]

10.4 Combinations in minimal-change order

The combinations of three elements out of six in minimal-change order are

The algorithm used in the utility class [FXT: class comb minchange in comb/combminchange.h] is based

on inlined versions of the routines that were explained in the corresponding bitmagic section (7.12).class comb_minchange

{

public:

ulong n_; // number of elements to choose from

ulong k_; // number of elements of subsets

ulong igc_bits_;

ulong bits_;

ulong igc_last_;

ulong igc_first_;

Trang 11

void sync_x() // aux

// Sync bits into array and

// set sw1_ and sw2_

{

ulong tbits = gray_code( igc_bits_ );

ulong sw = bits_ ^ tbits;

Trang 12

10.5 Combinations in alternative minimal-change order

There is more than one minimal-change order Consider the sequence of bitsets generated in section 7.12:alternative orderings that have the minimal-change property are e.g described by 1) the sequence witheach word reversed or, more general 2) every permutation of the bits 3) the sequence with its bits negated4) cyclical rotations of (1) (3)

Here we use the negated and bit-reversed sequence for

³

n−k n

´:

Trang 13

The interesting feature is that the last combination is identical to the first shifted left by one This makes

it easy to generate the subsets of a set with n elements in monotonic minchange order by concatenating the sequences for k = 1, 2, , n.

The usage of the utility class [FXT: class comb alt minchange in comb/combaltminchange.h] is tical to that of the ”standard” minchage-order

iden-The above listing can be produced via

10.6 Subsets in lexicographic order

The (nonempty) subsets of a set of five elements enumerated in lexicographic order are:

Clearly there are 2n subsets (including the empty set) of an n-element set.

The corresponding utility class is not too complicated

class subset_lex

{

protected:

ulong *x; // subset data

ulong n; // number of elements in set

Trang 14

ulong k; // index of last element in subset

// number of elements in subset == k+1

// Generate next subset

// Return number of elements in subset

// Return zero if current == last

{

if ( x[k] == n-1 ) // last element is max ?

{

if ( 0==k ) { return 0; } // note: user has to call first() again

k; // remove last element

x[k]++; // increase last element

// Generate previous subset

// Return number of elements in subset

// Return zero if current == first

{

if ( k == 0 ) // only one lement ?

{

if ( x[0]==0 ) { return 0; } // note: user has to call last() again

x[0] ; // decr first element

[FXT: class subset lex in comb/subsetlex.h]

One can generate the list at the beginning of this sections by a code fragment like:

Trang 15

cout << " #=" << setw(2) << num << ": ";

print_set_as_bitset(" ", sl.data(), num, n);

print_set(" ", sl.data(), num);

cout << endl;

}

while ( (num = sl.next()) );

cf [FXT: file demo/subsetlex-demo.cc]

10.7 Subsets in minimal-change order

The subsets of a set with 5 elements in minimal-change order:

Generation is easy, for a set with n elements go through the binary gray codes of the numbers from 1 to

2n−1 and sync the bits into the array to be used:

class subset_minchange

{

protected:

ulong *x; // current subset as delta-set

ulong n; // number of elements in set

ulong num; // number of elements in current subset

ulong chg; // element that was chnged with latest call to next()

ulong idx;

ulong maxidx;

Trang 16

const ulong * data() const { return x; }

ulong get_change() const { return chg; }

const ulong current() const { return idx; }

const ulong *x = sm.data();

ulong num, idx = 0;

do

{

num = sm.next(); // omit empty set

++idx;

cout << setw(2) << idx << ": ";

// print as bit set:

for (ulong k=0; k<n; ++k) cout << (x[k]?’1’:’.’);

Trang 17

10.8 Subsets ordered by number of elements

Sometimes it is useful to generate all subsets ordered with respect to the number of elements, that isstarting with the 1-element subsets, continuing with 2-element subsets and so on until the full set is

reached For that purpose one needs to generate the combinations of 1 form n, 2 from n and so on.

There are of course many orderings of that type, practical choices are limited by the various generatorsfor combinations one wants to use Here we use the colex-order for the combinations:

const ulong *x = so.data();

ulong num, idx = 0;

do

{

num = so.next();

++idx;

cout << setw(2) << idx << ": ";

// print as bit set:

for (ulong k=0; k<n; ++k) cout << (x[k]?’1’:’.’);

Trang 18

10.9 Subsets ordered with shift register sequences

A curious sequence of all subsets of a given set can be generated using a binary de Bruijn (or shift register) sequence, that is a cyclical sequence of zeros and ones that contains each n-bit word once In the following example (where n = 5) the empty places of the subsets are included to make the nice

by shifting it to the right and inserting the current element from the SRS

The utility class [FXT: class subset debruijn in comb/subsetdebruijn.h] uses [FXT: class debruijn

in comb/debruijn.h] (which in turn uses [FXT: class prime string in comb/primestring.h]).The list above was created via

Trang 19

The utility class is

ulong i_; // level in iterative search

long *pv_; // values into which to partition

ulong *pc_; // multipliers for values

ulong pci_; // temporary for pc_[i_]

long *r_; // rest

long ri_; // temporary for r_[i_]

long x_; // value to partition

void init(ulong x); // reset state

ulong next(); // generate next partition

ulong next_func(ulong i); // aux

ulong count(ulong x); // count number of partitions

ulong count_func(ulong i); // aux

void dump() const;

int check(ulong i=0) const;

};

[FXT: class partition in comb/partition.h]

The algorithm to count the partitions is to assign to the first bucket a multiple c0· p0 ≤ x of the first set element p0 If c0· p0 = x we already found a partition, else if c0· p0 < x solve the problem for

Trang 21

if ( 0==r_[i] ) // valid partition found

The routines can easily adapted to the generation of partitions satisfying certain restrictions, e.g

parti-tions into unequal parts (i.e c i ≤ 1).

Cf [FXT: file demo/partition-demo.cc]

Ngày đăng: 09/08/2014, 12:22