#!/usr/local/bin/perl

use 5.040.3;

# Vamos a suponer que se trata de simular una combinación física o química
# que no es binaria. La tentación sería usar base 3 pero habría una ida y
# venida del número ternario a la combinación.

# Siguiente paso: más posibilidades, 5

my @fiveit = (-2, -1, 0, 1, 2);   # OBJETIVO: características, pueden ser texto ACGT

my $size = scalar @fiveit;

my @info;  # una lista o cadena de @fiveit de longitud $n

my @flag;  # una lista de enteros no negativos sobre el número de veces
           # que se ha pasado por encima de $info[$n] siendo éste un @fiveit

my $n = 1023;   # ejemplo 0 .. 1023

say "El espacio de combinaciones es ", scalar(@fiveit) ** ($n+1);

my @pos;  # será lo más parecido al ternario. Posición [0|1|2] del @fiveit
          # en $info[$n] = $fiveit[ $pos[$n] ]
          # Pero la cosa es tratar de golpe a todo el @fiveit de $n, que se
          # puede hacer de uno en uno o todo
          # Se elige todo. Se hace en sub grupo {} y se devuelve 3 @info
          # en su debido orden, y se incrementa $flag[$n]

# INICIALIZACIÓN

my $tmp = 0;
for (0 .. $n){
    $tmp = int(rand() * scalar(@fiveit));      # 0,1,2, 3, 4 
    $pos[$_] = $tmp;
    $info[$_] = $fiveit[ $tmp ];              # -2,-1,0,1,2 las carcterísticas deseadas
}


# EXPERIMENTACIÓN

my $ITER = 1_000_000;
my $t0 = time();

for (1 .. $ITER){
        
    my $i = rnd();

    my @ii = grupo($i);    # primera forma de uso

    my @R;
    my $c = 0;
    for (@ii){
	$info[$i] = $_;
	$R[$c] = experiment( rnd() );    # el rnd() se refiere a 0 .. $n
	$c++;
    }
    
    # elegir un escalar
    
    my $sum = 0;
    for (@R){
	print "$_ ";
	$sum += $_;
    }       
    say " -> $sum";
}

say "\nSe ha tardado ", time()-$t0, " segundos en hacer $ITER iteraciones\n";

exit 3;


sub grupo {
    my $i = shift;
    my $j = $pos[$i];
    
    my @rdo;
    for (1 .. $size){
	$rdo[$_-1] = $fiveit[ ++$j % $size ];
    }
#    my $r2 = $fiveit[ ++$j % $size ];
#    my $r3 = $fiveit[ ++$j % $size ];   # la vuelta completa a @trit
#    my $r4 = $fiveit[ ++$j % $size ];
#    my $r5 = $fiveit[ ++$j % $size ];   # la vuelta completa a @fiveit
    
    warn "Error de paridad" if ( $j % $size != $pos[$i] );

#    my (@info1, @info2, @info3) = (@info, @info, @info);   # aux       
#    ($info1[$i], $info2[$i], $info3[$i]) = ($r1, $r2, $r3);
    
    if (wantarray()){
	$flag[$i]++;     # para un uso estadístico no fijado
	return @rdo;     # lista rdo normal
    }else{
	$pos[$i] = ++$j % $size;	# esto es duda, porque es sólo si se quiere avanzar una pos
	return $rdo[0];                 # pero que es local a $i, y solo una modificación 
    }                                   # de manera que NO USADO en main()
}

sub experiment {
    my $i = shift;    
    # hacer algo con esta @info particular
    return $info[$i];   # ejemplo: la parte recientemente modificada
}

sub rnd {
    return int (rand()*($n+1));
}

