Re: help with simplifying program
by BrowserUk (Pope) on May 24, 2013 at 05:36 UTC

That makes no sense?
Each of your inner loops is limited to the value of the preceding loop counter1, so can never attain a value that would trigger your condition.
Ie. $x is limited to $w1, so $x can never become equal to $w + $s for any value of $s, unless $s was 1 or less, but your $s loop start from 1 and increases.
In other words; your unless condition will always be false, and so it is doing nothing (except consuming cycles).
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks  Silence betokens consent  Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
 [reply] 

 [reply] [d/l] [select] 
Re: help with simplifying program
by tobyink (Abbot) on May 24, 2013 at 05:38 UTC

Untested, but makes sense to me...
foreach my $w (3..100) {
foreach my $x (2..$w1) {
foreach my $y (1..$x1) {
foreach my $z (0..$y1) {
next if ($z$y==$y$x and $y$x==$x$w);
...;
}
}
}
}
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow>new>name
 [reply] [d/l] 
Re: help with simplifying program
by snoopy (Deacon) on May 24, 2013 at 05:50 UTC

Hi There,
I'm not sure, if the unless condition is actually filtering anything:
use strict;
my $n1;
my $n2;
foreach my $w (3..100) {
foreach my $x (2..$w1) {
foreach my $y (1..$x1) {
foreach my $z (0..$y1) {
foreach my $s (1..20) {
$n1++;
unless ( $x == $w + $s
&& $y == $x + $s
&& $z == $y + $s ) {
$n2++;
}
}
}
}
}
}
print "n1: $n1\n";
print "n2: $n2\n";
Output:
n1: 81658500
n2: 81658500
 [reply] [d/l] [select] 
Re: help with simplifying program
by hdb (Prior) on May 24, 2013 at 08:40 UTC

From your description I take you want (w, x, y, z) such that 0 <= z < y < x < w <= 100 and not wx == xy == yz. In order to achieve this I would parametrize the loops using the differences dwx = wx, dxy = xy, dyz = yz.
use strict;
use warnings;
my $n = 5; # should be 100
my $c1 = my $c2 = 0;
for my $w (3..$n) {
for my $dwx (1..$w2) {
my $x = $w  $dwx;
for my $dxy (1..$x1) {
my $y = $x  $dxy;
for my $dyz (1..$y) {
my $z = $y  $dyz;
$c1++;
next unless $dwx != $dxy or $dxy != $dyz;
$c2++;
print "$w $x $y $z\n";
}
}
}
}
print "Found $c2 out of $c1 combinations\n";
UPDATE: Changes next unless... for better readibility.
 [reply] [d/l] [select] 

next unless $dwx != $dxy and $dxy != $dyz;
otherwise you will not get all of the valid combinations  [reply] [d/l] [select] 

next if $dwx == $dxy and $dxy == $dyz;
which I should have used in the first place.
 [reply] [d/l] [select] 

Re: help with simplifying program
by BillKSmith (Priest) on May 24, 2013 at 14:19 UTC

 [reply] 

# $lep means smallest nonzero root in the interval [0, $rep]
# $rep means right endpoint of the interval [0, $rep]
my $lep = int 1;
my $rep = int 100;
foreach my $x ($lep+2 .. $rep ) {
foreach my $y ($lep+1 .. $x1 ) {
foreach my $z ($lep .. $y1 ) {
foreach my $s (1..$rep/4) {
unless ($y == $x + $s && $z == $y + $s ) {
# assigns a truth value to whether or not it is wi
+thin 0.0001 of an integer (1=true, 0=false)
sub is_approximately_an_integer {
my $eps = 0.0001;
while( my $w = shift ) {
# need to use "round", "int" does not work!
return 0 if abs( $wround($w) ) > $eps;
}
return 1
}
}
}
push @wants,
map { { join(', ', $x, $y, $z) => $_ } }
grep { is_approximately_an_integer( @$_ ) } [
poly_roots(
poly_derivative(
# expanded form of x*(x  $x)*(x  $y)*(x
+ $z)
1, $x  $y  $z, $x*$y + $x*$z + $y*$z, 
+$x*$y*$z, 0
)
)
];
}
}
}
 [reply] [d/l] 

Oops, I was slightly wrong. Combinations will only replace three of your loops. You still have to select the applicable combinations.
use Algorithm::Combinatorics qw(combinations);
my $lep = int 1;
my $rep = int 100;
my $iter = combinations( [$lep+2 ..$rep], 3 );
while (my $c = $iter>next) {
my ($x, $y, $z) = @$c;
foreach my $s (1..$rep/4) {
# as before
}
}
 [reply] [d/l] 

use strict;
use warnings;
use Algorithm::Combinatorics qw(combinations);
my $rep = 5; # should be 100
my @data = 0..$rep;
my $iter = combinations( \@data, 4 );
while( my $p = $iter>next ) {
my ( $z, $y, $x, $w ) = @$p;
next unless $w2*$x+$y or $x2*$y+$z;
print "$w, $x, $y, $z\n";
}
 [reply] [d/l] 
