[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[MacPerl] prograMing: CompleteIndexSet



I wrote:
>I have a every interesting
>academic-type programing problem involving array generation, and am
>interested to see creative results. 

Doesn't looks like there's whole lot of interest in this problem. Anyway, here's some codes to satisfy those perl-holic.

The algorithm used for CompleteIndexSet is from Rick Delaney <rick.delaney@shaw.wave.ca>.

#------------------------
#!perl -w

use strict;
#_____ MinimumIndexSet _____ _____

=pod

B<MinimumIndexSet>

MinimumIndexSet([index1,index2,...]) returns a modified version of input in which indexes that can be inferred from other indexes are deleted. Indexes are of the form [n1,n2,n3,...] where the n are non-negative integers.

Related: CompleteIndexSet, FullArrayIndexSet.


Example:

 MinimumIndexSet([[1], [2], [3], [2, 3], [2, 2], [2, 3, 7], [3, 1]])
 #returns [[2, 3, 7], [3, 1]].

=cut

# implementation note:
# definition: Suppose {a,b,c,d} is one index. It is redundant if MemberQ[givenIndexes,{a,b,c,x$_/;x$ > d}|{a,b,c,x$_/;x$ >= d,__}], and if the index is {}, then it is redundant if MemberQ[givenIndexes,{__}].
# algorithm used: exactly same as LeafIndexSet except _leafIndexQ is replaced by _inferableIndexQ.

# Dependent functions: _inferableIndexQ.

# misc notes: this function needs heavy testing. xxxxx

sub MinimumIndexSet ($) {
my @indexList = @{$_[0]};

my $count = 1;
my $ref_currentIndex;
my $ref_currentElement;
OUTER: while ($count < scalar @indexList) {
$ref_currentIndex = $indexList[-$count];
	INNER: for (my $i = scalar(@indexList) -$count -1; $i >= 0; $i--) {
	$ref_currentElement = $indexList[$i];
	
	if (_inferableIndexQ($ref_currentElement,$ref_currentIndex))
	{splice(@indexList,$i,1); next INNER;}
	elsif (_inferableIndexQ($ref_currentIndex,$ref_currentElement))
	{splice(@indexList,-$count,1); next OUTER;};
	};
$count++;
};

return \@indexList;
};

#_____ CompleteIndexSet _____ _____

=pod

B<CompleteIndexSet>

CompleteIndexSet([index1,index2,...]) returns a modified version of argument in which indexes that are implied by givens are inserted. The elements in the result list is arbitrary ordered, and without duplicates.

Related: MinimumIndexSet, FullArrayIndexSet, IndexSetSort.

Example:

The empty array [] in the result represents the index for the root node.

 IndexSetSort( CompleteIndexSet( [[2, 1]] ) );
 #returns [[],[0],[1],[2],[2,0],[2,1]].

 IndexSetSort( CompleteIndexSet( [[2, 1], [3]] ) );
 #returns [[],[0],[1],[2],[3],[2,0],[2,1]].

 IndexSetSort( CompleteIndexSet( [[2, 1], [3], [3]] ) );
 #returns [[],[0],[1],[2],[3],[2,0],[2,1]].

 IndexSetSort( CompleteIndexSet( [[3, 3], [4]] ) );
 #returns [[],[0],[1],[2],[3],[4],[3,0],[3,1],[3,2],[3,3]].

 IndexSetSort( CompleteIndexSet( [[3, 3], [1, 1], [4]] ) );
 #returns [[],[0],[1],[2],[3],[4],[1,0],[1,1],[3,0],[3,1],[3,2],[3,3]].

=cut

# implementation note:
# some description:
# Suppose one of the given index is {a,b,c,d}. If the last digit is not 0, then generate {a,b,c,d-1}. If the last digit is 0, then generate {a,b,c}. Add the new element into a result list. Now take new element as input and repeat the process until it becomes {}. Now do the above with every given index. Now eliminate duplicates and {} in the result list. The result is as desired.

# Dependent functions: (none)

# misc notes: this function needs heavy testing. This function's time complexity can also be improved by first generate a minimum index set, and use a smart algorithm to avoid generating repeatitions (without even checking for existance). xxxxx


sub CompleteIndexSet ($) {
	my @indexList = @{$_[0]};

	my %indexListHash;
	foreach my $elem (@indexList) {$indexListHash{"@{$elem}"} = $elem;};

    foreach my $ref_index (@indexList) {
        my @index = @{$ref_index};
	LOOP1: while (@index) {
			if ($index[-1]-- == 0) {pop(@index);};
			if (exists $indexListHash{"@index"}) {last LOOP1;};
			$indexListHash{"@index"} = [@index];
		};
	};
	return [values %indexListHash];
};


# _inferableIndexQ($indexA,$indexB) returns 1 if $indexB implies $indexA. Suppose indexA = {a,b,c,d}. Then it is inferable if MatchQ[indexB, {a,b,c,x$_/;x$ > d}|{a,b,c,x$_/;x$ >= d,__}]. If indexA == indexB, we also say it's inferable.
# $indexA and B must have the form [n1,n2,...], where n_i is non-negative integer.
# Examples: the following are all true:
# _inferableIndexQ([3,2],[3,2]);
# _inferableIndexQ([3,2],[3,3]);
# _inferableIndexQ([3,2],[3,2,0]);
# _inferableIndexQ([3,2],[3,2,2,4]);
# the following are false:
# _inferableIndexQ([3,2],[4]);
# _inferableIndexQ([3,2],[3,1]);
# _inferableIndexQ([3,2],[3,1,5]);

sub _inferableIndexQ ($$) {
my @indexA = @{$_[0]};
my @indexB = @{$_[1]};

# if length of indexA is greater then indexB, then indexA is not inferable.
if (scalar @indexA > scalar @indexB) {return 0};

# if the first few of indexA are not the same as indexB, then indexA is not inferable.
foreach my $i (0 .. $#indexA -1) {if ($indexA[$i] != $indexB[$i]) {return 0;};};

if ($indexA[-1] <= $indexB[$#indexA]) {return 1;};

return 0;
};

#------------------------

 Xah, xah@best.com
 http://www.best.com/~xah/PageTwo_dir/more.html
 "YOU! stop bad cencorship NOW: http://www.cdt.org/ "



***** Want to unsubscribe from this list?
***** Send mail with body "unsubscribe" to mac-perl-request@iis.ee.ethz.ch