X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=appendix-a6.git;a=blobdiff_plain;f=stv;h=47984e80dc4bdb286f8d2f271d4e3701e7089b72;hp=762da6359ed848ee63833b25f827df381ec128c6;hb=83ac3d9b8d6e365ca3f7083db8f37034456da0be;hpb=530e6a27004910679481ad4a8e52f4beca643c32 diff --git a/stv b/stv index 762da63..47984e8 100755 --- a/stv +++ b/stv @@ -6,7 +6,9 @@ use strict; use utf8; use autodie; -use bigrat; +#use bigrat; +use Data::Dumper; +use List::Util qw(sum); use List::MoreUtils qw(nsort_by); # vote is @@ -20,6 +22,8 @@ our @allvotes; our $places = shift @ARGV; die unless $places eq ($places + 0); +open DEBUG, ">.stv.log" or die $!; + while (<>) { next if m/^\w+$/; m/^(\w+) ([A-Z]+)$/ or die "$_ ?"; @@ -60,7 +64,6 @@ our %sorted; # $sorted{$firstpref}{Votes} = [ $vote, ... ] # $sorted{$firstpref}{Cand} = $firstpref # $sorted{$firstpref}{Total} = $totalweight -our @sorted; # values same as %sorted our @surpluses; # values same as %sorted our @exhausted; # votes @@ -79,15 +82,48 @@ sub equalpiles ($@) { my $s = $sorted[0]; my $eqtotal = $s->{Total}; my $count = 0; - while ($count < @$sorted && $sorted[$count]{Total} == $eqtotal) { + while ($count < @sorted && $sorted[$count]{Total} == $eqtotal) { printf "%7s %10s\n", $how, $sorted[$count]{Cand}; $count++; } - + return @sorted[ 0 .. $count-1 ]; +} + +sub historically_prefer ($@) { + my ($signum, @choices) = @_; + + return $choices[0] if @choices < 2; + + my $compare = sub { + foreach my $sr (@stagerecord) { + my $d = $sr->{ $a->{Cand} } <=> $sr->{ $b->{Cand} }; + return $d * $signum if $d; + } + return 0; + }; + + @choices = sort $compare, @choices; + $a = $choices[0]; + my $numequal = 0; + for (;;) { + last unless $numequal >= @choices; + $b = $choices[$numequal]; + last if $compare->(); + } + + die 'random choice unimplemented' if $numequal > 1; + return $choices[0]; +} for (;;) { $stage++; + print DEBUG "#################### $stage ####################\n", + Data::Dumper->Dump( +[ \@stagerecord, \@elected, \@unsorted, \%sorted, \@surpluses, \%continuing ], +[qw( _@stagerecord _@elected _@unsorted _%sorted _@surpluses _%continuing )] + ); + while (my $vote = shift @unsorted) { my ($firstpref) = grep { $continuing{$_} } @{ $vote->{Prefs} }; if (!defined $firstpref) { @@ -158,11 +194,11 @@ for (;;) { printf "%7s %10s\n", 'derate', $s->{Cand}, pr $derate; foreach my $vote (@{ $s->{Votes} }) { - votelog $vote, "elected $s->{Cand}, derated $weightmult"; + votelog $vote, "elected $s->{Cand}, derated $derate"; $vote->{Weight} /= $derate; } push @surpluses, $s; - delete %sorted{ $s->{Cand} }; + delete $sorted{ $s->{Cand} }; delete $continuing{ $s->{Cand} }; $sort_update->(); @@ -200,8 +236,8 @@ for (;;) { printf "%7s %10s\n", 'ELIM', $c; my $votes = $s->{Votes}; votelog $_, "failed to stop $c elimination" foreach @$votes; - delete %continuing{$c}; - delete %sorted{$c}; + delete $continuing{$c}; + delete $sorted{$c}; push @unsorted, @$votes; }