function rankedVote
% rankedVote  Demonstrate rank voting

% -- Votes for 10 items -- generated with randperm(10)
%    In actual use, each voter would list the items in
%    rank order from most desirable to least desirable.
jane = [6, 3, 7, 8, 5, 1, 2, 4, 9, 10];
dean = [6, 1, 7, 4, 9, 5, 8, 3, 10, 2];
randy = [2, 10, 8, 9, 1, 5, 7, 6, 3, 4];
tori = [2, 10, 4, 5, 3, 8, 7, 1, 6, 9];
jamal = [5, 2, 1, 7, 6, 8, 9, 10, 3, 4];

% -- Combine votes into one matrix
V = [jane; dean; randy; tori; jamal];

fprintf('\n\nResults for first matrix of votes\n')
ranking(V);

% -- Repeat with multi-voting model.  Suppose each voter
%    Had a total of 10 votes to spread over 3 items
jane  = [1 1 1 1 2 2 3 3 3 3];
dean  = [1 2 2 2 2 2 3 3 3 3];
randy = [2 2 2 1 1 1 1 3 3 3];
tori  = [1 1 3 3 3 3 3 2 2 2];
jamal = [1 2 2 2 2 2 2 2 3 3];

% -- Combine votes into one matrix
V = [jane; dean; randy; tori; jamal];

fprintf('\n\nResults for second matrix of votes\n')
ranking(V);

end

% ----------------

function [vout,Rout] = ranking(V)
% ranking  Compute ranked scores from a voting matrix
%
% Synopsis:  ranking(V)
%            votes = ranking(V)
%            [votes,R] = ranking(V)
%
% Input:  V = voting matrix.  Each row in V contains preferences of a voter
%             The row contains the numbers of items in rank order.  For
%             example, if voter 1 prefers items 1, 2, 3 in the order
%             2, 3, 1, then V(1,:) = [2 3 1]
%
% Output: votes 

n = max(max(V));   %  Number of items to vote for = largest number in V
nv = size(V,2);    %  Total number of votes       
R = zeros(n,nv);   %  Matrix to store ranks
scores = zeros(n,1);

% -- Loop over columns of V.  First column is first place
%    weight is in reduced order of preference
%      1st place: weight = ni  (number of items)
%      2nd place: weight = ni-1
%      3rd place: weight = ni-2 etc.

for j = 1:nv             %  Loop over columns in V = # votes per voter
  weight = nv - (j-1);   %  Weight assigned to this column
  for i = 1:n
    itot = length( find(V(:,j)==i) );
    if ~isempty(itot)
      scores(i) = scores(i) + itot*weight;
      R(i,j) = itot;
    end
  end
end

fprintf('\nitem   score\n');

[scores,irank] = sort(scores,1,'descend');
for i = 1:n
  fprintf('%3d     %4d\n',irank(i),scores(i));
end

fprintf('\nVoting matrix\n')
displayTable(V,'Voter','Item')

fprintf('\nRanked score matrix\n')
displayTable(R,'Item','Counts at each rank:')

if nargout>0, vout = [irank scores];  end
if nargout>1, Rout = R;      end

end

% -----------
function displayTable(X,rowLabel,colLabel)
% displayTable  Print a table of small integers.  Small means <= 99

if nargin<2, rowLabel='rows';     end
if nargin<3, colLabel='columns';  end

rowLabelWidth = length(rowLabel) + 2 + 2;
rowLabelSpace = repmat(' ',1,rowLabelWidth);
fprintf('%s   %s\n',rowLabelSpace,colLabel);
rowLabelFormat = sprintf('%s %%2d |',rowLabel);
fprintf('%s ',rowLabelSpace);

[m,n] = size(X);
fprintf('%3d',1:n)
fprintf('\n%s+',rowLabelSpace)
for j=1:n
  fprintf('---');
end
fprintf('\n')
for i = 1:m
  fprintf(rowLabelFormat,i);
  for j = 1:n
    fprintf('%3d',X(i,j));
  end
  fprintf('\n')
end

end

