#!/usr/bin/perl -w

use 5.032;

my $N = 101;
my @datos;
my $s = 0;
for (0..$N-1){  # son 101 datos para una ecuación SUM $w_i * $datos_i = OBJETIVO
    push @datos, int (rand()*1234567);
    $s += $datos[-1];
}
say "Datos generados. Suma = $s";

### Comienzo de main
my $t1 = time();
my $eps = 0.000501;   # float
my @cand;
my $err;
my $k = 0;
my $point;
my $record = 9e99;
my @candidato;
my $objetivo = -555;
# $eps /= 2 until ($eps == 0); 


loop1:                          # un nuevo reinicio aleatorio     
@cand=();
push @cand, (rand()-0.5)/10000 for (0..$N-1);

loop2:                          # tras pequeña modificación, loop. Es el principal, porque llama al sub f()
$err = $objetivo - f(@cand);
say "$k OBJ = $objetivo -> $err";
    
if ( abs($err) < $record ){
    $record = abs($err);
    @candidato = @cand;
}

if (++$k % 1_000_000 == 0){
    @cand = @candidato;
    goto loop2;
}    

$point = int(rand()*$N);
if (abs($err) > $eps){              # significa $total > $sum  
    if ( $cand[$point] < 0 ){
	$cand[$point] += rand()/10000;
	goto loop2;
    }elsif ( $cand[$point] > 0 ){ 
	$cand[$point] -= rand()/10000;
	goto loop2; 
    }
}

# success!

say "\nError = $err";
say "No significative error. Solution reached.";
say time()-$t1, " seconds.";
exit 1;

sub f {
    my @w = @_;
    my $sum = 0;
    my $c = 0;
    for my $i (@w){
	$sum += $i * $datos[$c];
	$c++;
    }
    return $sum;
}

__END__

