Problems? Is your data what you think it is? PerlMonks

Re^2: Algorithm for cancelling common factors between two lists of multiplicands

by ikegami (Pope)
 on Aug 08, 2005 at 20:42 UTC ( #482024=note: print w/replies, xml ) Need Help??

If the solution in my earlier node doesn't return what you want, this surely will:
```use Math::BigInt ();

*gcd = \&Math::BigInt::bgcd;

sub embiggen {
local \$_ = @_ ? \$_[0] : \$_;
return Math::BigInt->new(\$_);
}

my @a = ( 10, 20, 33, 45, 60 );
my @b = ( 2, 5, 10, 12, 16, 23, 45 );

# my %a = map { \$_ => 1 } @a;
# my %b = map { \$_ => 1 } @b;
#
# my @c = map embiggen,
#         grep { !\$b{\$_} }
#         @a;
#
# my @d = map embiggen,
#         map { Math::BigInt->new(\$_) }
#         grep { !\$a{\$_} }
#         @b;

my @c = @a;
my @d = @b;

foreach my \$c (@c) {
foreach my \$d (@d) {
my \$gcd = gcd(\$c, \$d);
\$c /= \$gcd;
\$d /= \$gcd;
}
}

@c = grep { \$_ != 1 } @c;
@d = grep { \$_ != 1 } @d;
or this messier but potentially faster alternative:
```use Math::BigInt       ();
use Math::Big::Factors ();

*gcd    = \&Math::BigInt::bgcd;
*factor = \&Math::Big::Factors::factors_wheel;

sub embiggen {
local \$_ = @_ ? \$_[0] : \$_;
return Math::BigInt->new(\$_);
}

my @a = ( 10, 20, 33, 45, 60 );
my @b = ( 2, 5, 10, 12, 16, 23, 45 );

# my %a = map { \$_ => 1 } @a;
# my %b = map { \$_ => 1 } @b;
#
# my @c = map embiggen,
#         grep { !\$b{\$_} }
#         @a;
#
# my @d = map embiggen,
#         grep { !\$a{\$_} }
#         @b;

my @c = @a;
my @d = @b;

my %c_factors;

foreach my \$c_idx (0..\$#c) {
my @c_factors = factor(\$c[\$c_idx]);
foreach my \$c_factor (@c_factors) {
push(@{\$c_factors{\$c_factor}}, \$c_idx);
}
}

foreach my \$d (@d) {
my @d_factors = factor(\$d);
foreach my \$d_factor (@d_factors) {
next unless \$c_factors{\$d};
next unless @{\$c_factors{\$d}};

my \$c_idx = shift(@{\$c_factors{\$d}});
\$c[\$c_idx] /= \$d_factor;
\$d         /= \$d_factor;
}
}

@c = grep { \$_ != 1 } @c;
@d = grep { \$_ != 1 } @d;
Both untested.

Replies are listed 'Best First'.
Re^3: Algorithm for cancelling common factors between two lists of multiplicands
by sk (Curate) on Aug 08, 2005 at 22:43 UTC
Update I wrote this when we were trying to figure out the exact output. Not relevant anymore

Your first should work correctly. Did not read the second one yet. One thing you want to note when you test this code is that the result will not match exactly what BrowserUk had coz the cancellation process is kind of subjective when done by humans as opposed to computers

take for example if i have 15 * 3 * 12 / 9 * 17

then I could either do 5 * 12/17 or 15 * 4/17

I guess the final solution should match product of the elements in the array

Another thing, you might get a tiny little benefit if you check for the elements == 1 inside the loop construct and pop them out. I am not sure if that is even possible.

BTW, i think you can add next if \$c == 1 or \$d == 1; to avoid computing gcd's on 1's.

-SK

Create A New User
Node Status?
node history
Node Type: note [id://482024]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (14)
As of 2019-10-18 12:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
In 2019 the site I miss most is:

Results (45 votes). Check out past polls.

Notices?