#!/usr/bin/perl -w

use 5.034;

my @films = "a".."z";              # $z = scalar @films
my $N = scalar @films;
my $voters = 10_000; 
my $size_l = 10;              # really $size_lists compressed mode      
my @vote_lists;

for my $i (0..$voters-1) {          # voters of the academy ---> $i
    for my $j (0..$size_l-1) {      # ballot list ---> $j
	$vote_lists[$i][$j] = int (rand() * $N);
    }
}

# TRAMPA!!! para determinar si calcula bien:
for my $j (0..$size_l-1){
    for my $i (0..$voters-1){
	if ( $films[ $vote_lists[$i][$j] ] =~ /x/ ){          # una probabilidad de más para 0 = "a": en vez de 1/$z son 2/$z
	    $vote_lists[$i][$j] = 0;
	}
    }
}

################ hasta aquí datos supuestos

my @sum;    
my $max = 0;    
my $min;
my @tabu;
my $round = -1;
my @empate;

do {
    @empate = ();
    $round++;
    $min = $voters+1;
loop:    for my $i (0..$voters-1){
	if ($round == 1){
	    for my $j (0 .. $size_l-1){
		$sum[ $vote_lists[$i][$j] ]++;
	    }
	}else{	
	    for my $j (0 .. $size_l-2){    # Si en cada ronda se elimina uno, las iteraciones no pueden ser mayores al tamaño de la lista.
		for my $k (@tabu){         # Es decir, si se elimina al último de una lista, ese votante no puede elegir a otro.
		    if ($vote_lists[$i][$j] == $k){
			$sum[ $vote_lists[$i][$j+1] ]++;
			next loop;
		    }else{
			# yet counted
		    }
		}
	    }        
	}
    }
    for my $z (0 .. $N-1){
	next unless defined $sum[$z];    
	if ($sum[$z] > $max){
	    $max = $sum[$z];
	}elsif ($sum[$z] < $min){
	    $min = $sum[$z];
	}
    }
    for my $z (0 .. $N-1){
	next unless defined $sum[$z];
	if ($sum[$z] == $max){
	    push @empate, $z;
	}
	if ($sum[$z] == $min){       # aquí no hay problema y si hay empate se eliminan varios
	     push @tabu, $z;
	}
    }
    
    print "Round $round -> result $max\n";    # 0j0, según mi interpretación, si suman los votos de los rechazados, puede haber $sum > $voters 
    
}until ($max / $voters >= 0.5);

for my $z (0.. $N-1){
    next unless defined $sum[$z];
    if ($sum[$z] == $max && scalar(@empate) == 1){
	say "In the round $round...";
	say "And the Oscar goes to $z -> $films[$z] with $max votes";
    }elsif ($sum[$z] == $max && scalar(@empate) > 1){
	say "Wow! TIE! in the round $round...";
	for my $k (@empate){
	    say "And the Oscar goes to $k -> $films[$k] with $max votes";
	}
    }
}
say "";
exit 2;    
    
    
__END__
  
El sistema de votación por lista de preferencias dicen que 
  es de lo mejor. Es el sistema electoral de algún sitio USA y el de los Oscar.

Ranked choice voting (RCV) makes democracy more fair and functional.
  It works in a variety of contexts. It is a simple change that can have a big impact.
  
RCV is a way to ensure elections are fair for all voters.
  It allows voters the option to rank candidates in order of preference: one, two, three, and so forth.
  
If your vote cannot help your top choice win, your vote counts for your next choice.
  
If a candidate receives more than half of the first choices in races where voters elect one winner,
  that candidate wins, just like in a single-choice election. However, if there is no majority winner
  after counting first choices, the race is decided by an "instant runoff." The candidate with the fewest
  votes is eliminated, and voters who picked that candidate as ‘number 1’ will have their votes count for
  their next choice.
  
This process continues until there’s a majority winner or a candidate won with more than half of the vote.

IRV - Instant-runoff voting has notably high resistance to tactical voting but less to strategic nomination.

https://en.wikipedia.org/wiki/Instant-runoff_voting#Resistance_to_strategy
  
