September Morn Update

This commit is contained in:
Ingy döt Net 2019-09-12 10:33:56 -07:00
parent 4e2d22a71d
commit aac6731f2c
6856 changed files with 141342 additions and 21127 deletions

View file

@ -0,0 +1 @@
--- {}

View file

@ -0,0 +1,176 @@
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <ostream>
#include <set>
#include <vector>
template<typename T>
std::ostream& print(std::ostream& os, const T& src) {
auto it = src.cbegin();
auto end = src.cend();
os << "[";
if (it != end) {
os << *it;
it = std::next(it);
}
while (it != end) {
os << ", " << *it;
it = std::next(it);
}
return os << "]";
}
typedef std::map<std::string, int> Map;
typedef Map::value_type MapEntry;
void standardRank(const Map& scores) {
std::cout << "Standard Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 1;
for (auto value : list) {
int temp = rank;
for (auto& e : scores) {
if (e.second == value) {
std::cout << temp << " " << value << " " << e.first.c_str() << std::endl;
rank++;
}
}
}
std::cout << std::endl;
}
void modifiedRank(const Map& scores) {
std::cout << "Modified Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 0;
for (auto value : list) {
rank += std::count_if(scores.begin(), scores.end(), [value](const MapEntry& e) { return e.second == value; });
for (auto& e : scores) {
if (e.second == value) {
std::cout << rank << " " << value << " " << e.first.c_str() << std::endl;
}
}
}
std::cout << std::endl;
}
void denseRank(const Map& scores) {
std::cout << "Dense Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 1;
for (auto value : list) {
for (auto& e : scores) {
if (e.second == value) {
std::cout << rank << " " << value << " " << e.first.c_str() << std::endl;
}
}
rank++;
}
std::cout << std::endl;
}
void ordinalRank(const Map& scores) {
std::cout << "Ordinal Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 1;
for (auto value : list) {
for (auto& e : scores) {
if (e.second == value) {
std::cout << rank++ << " " << value << " " << e.first.c_str() << std::endl;
}
}
}
std::cout << std::endl;
}
void fractionalRank(const Map& scores) {
std::cout << "Ordinal Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 0;
for (auto value : list) {
double avg = 0.0;
int cnt = 0;
for (auto& e : scores) {
if (e.second == value) {
rank++;
cnt++;
avg += rank;
}
}
avg /= cnt;
for (auto& e : scores) {
if (e.second == value) {
std::cout << std::setprecision(1) << std::fixed << avg << " " << value << " " << e.first.c_str() << std::endl;
}
}
}
std::cout << std::endl;
}
int main() {
using namespace std;
map<string, int> scores{
{"Solomon", 44},
{"Jason", 42},
{"Errol", 42},
{"Gary", 41},
{"Bernard", 41},
{"Barry", 41},
{"Stephen", 39}
};
standardRank(scores);
modifiedRank(scores);
denseRank(scores);
ordinalRank(scores);
fractionalRank(scores);
return 0;
}

View file

@ -1,72 +1,89 @@
import Data.List (groupBy, sort, intercalate)
import Data.List (groupBy, sortBy, intercalate)
type Item = (Int, String)
type ItemList = [Item]
type ItemGroups = [ItemList]
type RankItem a = (a, Int, String)
type RankItemList a = [RankItem a]
type Item = (Int, String)
type ItemList = [Item]
type ItemGroups = [ItemList]
type RankItem a = (a, Int, String)
type RankItemList a = [RankItem a]
-- make sure the input is ordered and grouped by score
prepare :: ItemList -> ItemGroups
prepare = groupBy gf . reverse . sort
where gf (a, _) (b, _) = a == b
prepare = groupBy gf . sortBy (flip compare)
where
gf (a, _) (b, _) = a == b
-- give an item a rank
rank :: Num a => a -> Item -> RankItem a
rank
:: Num a
=> a -> Item -> RankItem a
rank n (a, b) = (n, a, b)
-- ranking methods
standard, modified, dense, ordinal :: ItemGroups -> RankItemList Int
standard = ms 1 where
standard = ms 1
where
ms _ [] = []
ms n (x:xs) = map (rank n) x ++ ms (n + length x) xs
ms n (x:xs) = (rank n <$> x) ++ ms (n + length x) xs
modified = md 1 where
modified = md 1
where
md _ [] = []
md n (x:xs) = let l = length x
nl = n + l
nl1 = nl - 1
in map (rank nl1) x ++ md (n + l) xs
md n (x:xs) =
let l = length x
nl = n + l
nl1 = nl - 1
in (rank nl1 <$> x) ++ md (n + l) xs
dense = md 1 where
dense = md 1
where
md _ [] = []
md n (x:xs) = map (rank n) x ++ md (n + 1) xs
ordinal = zipWith rank [1..] . concat
ordinal = zipWith rank [1 ..] . concat
fractional :: ItemGroups -> RankItemList Double
fractional = mf 1.0 where
fractional = mf 1.0
where
mf _ [] = []
mf n (x:xs) = let l = length x
o = take l [n ..]
ld = fromIntegral l
a = sum o / ld
in map (rank a) x ++ mf (n + ld) xs
mf n (x:xs) =
let l = length x
o = take l [n ..]
ld = fromIntegral l
a = sum o / ld
in map (rank a) x ++ mf (n + ld) xs
-- sample data
test :: ItemGroups
test = prepare
test =
prepare
[ (44, "Solomon")
, (42, "Jason")
, (42, "Errol")
, (41, "Garry")
, (41, "Bernard")
, (41, "Barry")
, (39, "Stephen") ]
, (39, "Stephen")
]
-- print rank items nicely
nicePrint :: Show a => String -> RankItemList a -> IO ()
nicePrint
:: Show a
=> String -> RankItemList a -> IO ()
nicePrint xs items = do
putStrLn xs
mapM_ np items
putStr "\n"
where np (a, b, c) = putStrLn $ intercalate "\t" [show a, show b, c]
putStrLn xs
mapM_ np items
putStr "\n"
where
np (a, b, c) = putStrLn $ intercalate "\t" [show a, show b, c]
main :: IO ()
main = do
nicePrint "Standard:" $ standard test
nicePrint "Modified:" $ modified test
nicePrint "Dense:" $ dense test
nicePrint "Ordinal:" $ ordinal test
nicePrint "Fractional:" $ fractional test
nicePrint "Standard:" $ standard test
nicePrint "Modified:" $ modified test
nicePrint "Dense:" $ dense test
nicePrint "Ordinal:" $ ordinal test
nicePrint "Fractional:" $ fractional test

View file

@ -0,0 +1,182 @@
MODULE RankingMethods;
FROM FormatString IMPORT FormatString;
FROM RealStr IMPORT RealToFixed;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
PROCEDURE WriteCard(c : CARDINAL);
VAR buf : ARRAY[0..15] OF CHAR;
BEGIN
FormatString("%c", buf, c);
WriteString(buf)
END WriteCard;
TYPE Entry = RECORD
name : ARRAY[0..15] OF CHAR;
score : CARDINAL;
END;
PROCEDURE OrdinalRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i : CARDINAL;
BEGIN
WriteString("Ordinal Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
FOR i:=0 TO HIGH(entries) DO
FormatString("%c\t%c\t%s\n", buf, i + 1, entries[i].score, entries[i].name);
WriteString(buf)
END;
WriteLn
END OrdinalRanking;
PROCEDURE StandardRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i,j : CARDINAL;
BEGIN
WriteString("Standard Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
j := 1;
FOR i:=0 TO HIGH(entries) DO
FormatString("%c\t%c\t%s\n", buf, j, entries[i].score, entries[i].name);
WriteString(buf);
IF entries[i+1].score < entries[i].score THEN
j := i + 2
END
END;
WriteLn
END StandardRanking;
PROCEDURE DenseRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i,j : CARDINAL;
BEGIN
WriteString("Dense Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
j := 1;
FOR i:=0 TO HIGH(entries) DO
FormatString("%c\t%c\t%s\n", buf, j, entries[i].score, entries[i].name);
WriteString(buf);
IF entries[i+1].score < entries[i].score THEN
INC(j)
END
END;
WriteLn
END DenseRanking;
PROCEDURE ModifiedRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i,j,count : CARDINAL;
BEGIN
WriteString("Modified Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
i := 0;
j := 1;
WHILE i < HIGH(entries) DO
IF entries[i].score # entries[i+1].score THEN
FormatString("%c\t%c\t%s\n", buf, i+1, entries[i].score, entries[i].name);
WriteString(buf);
count := 1;
FOR j:=i+1 TO HIGH(entries)-1 DO
IF entries[j].score # entries[j+1].score THEN
BREAK
END;
INC(count)
END;
j := 0;
WHILE j < count-1 DO
FormatString("%c\t%c\t%s\n", buf, i+count+1, entries[i+j+1].score, entries[i+j+1].name);
WriteString(buf);
INC(j)
END;
i := i + count - 1
END;
INC(i)
END;
FormatString("%c\t%c\t%s\n\n", buf, HIGH(entries)+1, entries[HIGH(entries)].score, entries[HIGH(entries)].name);
WriteString(buf)
END ModifiedRanking;
PROCEDURE FractionalRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..32] OF CHAR;
i,j,count : CARDINAL;
sum : REAL;
BEGIN
WriteString("Fractional Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
sum := 0.0;
i := 0;
WHILE i <= HIGH(entries) DO
IF (i = HIGH(entries) - 1) OR (entries[i].score # entries[i+1].score) THEN
RealToFixed(FLOAT(i+1),1,buf);
WriteString(buf);
FormatString("\t%c\t%s\n", buf, entries[i].score, entries[i].name);
WriteString(buf)
ELSE
sum := FLOAT(i);
count := 1;
j := i;
WHILE entries[j].score = entries[j+1].score DO
sum := sum + FLOAT(j + 1);
INC(count);
INC(j)
END;
FOR j:=0 TO count-1 DO
RealToFixed(sum/FLOAT(count)+1.0,1,buf);
WriteString(buf);
FormatString("\t%c\t%s\n", buf, entries[i+j].score, entries[i+j].name);
WriteString(buf)
END;
i := i + count - 1
END;
INC(i)
END
END FractionalRanking;
(* Main *)
TYPE EA = ARRAY[0..6] OF Entry;
VAR entries : EA;
BEGIN
entries := EA{
{"Solomon", 44},
{"Jason", 42},
{"Errol", 42},
{"Garry", 41},
{"Bernard", 41},
{"Barry", 41},
{"Stephen", 39}
};
OrdinalRanking(entries);
StandardRanking(entries);
DenseRanking(entries);
ModifiedRanking(entries);
FractionalRanking(entries);
ReadChar
END RankingMethods.

View file

@ -7,7 +7,7 @@ my @scores =
Barry => 41,
Stephen => 39;
sub tiers (@s) { @s.classify(*.value).pairs.sort.reverse.map: { [.value».key] } }
sub tiers (@s) { @s.classify(*.value).pairs.sort.reverse.map: { .value».key } }
sub standard (@s) {
my $rank = 1;
@ -38,8 +38,8 @@ sub fractional (@s) {
}
}
say "Standard:"; .say for standard @scores;
say "\nModified:"; .say for modified @scores;
say "\nDense:"; .say for dense @scores;
say "\nOrdinal:"; .say for ordinal @scores;
say "\nFractional:"; .say for fractional @scores;
say "Standard:"; .perl.say for standard @scores;
say "\nModified:"; .perl.say for modified @scores;
say "\nDense:"; .perl.say for dense @scores;
say "\nOrdinal:"; .perl.say for ordinal @scores;
say "\nFractional:"; .perl.say for fractional @scores;

View file

@ -0,0 +1,68 @@
my %scores = (
'Solomon' => 44,
'Jason' => 42,
'Errol' => 42,
'Garry' => 41,
'Bernard' => 41,
'Barry' => 41,
'Stephen' => 39
);
sub tiers {
my(%s) = @_; my(%h);
push @{$h{$s{$_}}}, $_ for keys %s;
@{\%h}{reverse sort keys %h};
}
sub standard {
my(%s) = @_; my($result);
my $rank = 1;
for my $players (tiers %s) {
$result .= "$rank " . join(', ', sort @$players) . "\n";
$rank += @$players;
}
return $result;
}
sub modified {
my(%s) = @_; my($result);
my $rank = 0;
for my $players (tiers %s) {
$rank += @$players;
$result .= "$rank " . join(', ', sort @$players) . "\n";
}
return $result;
}
sub dense {
my(%s) = @_; my($n,$result);
$result .= sprintf "%d %s\n", ++$n, join(', ', sort @$_) for tiers %s;
return $result;
}
sub ordinal {
my(%s) = @_; my($n,$result);
for my $players (tiers %s) {
$result .= sprintf "%d %s\n", ++$n, $_ for sort @$players;
}
return $result;
}
sub fractional {
my(%s) = @_; my($result);
my $rank = 1;
for my $players (tiers %s) {
my $beg = $rank;
my $end = $rank += @$players;
my $avg = 0;
$avg += $_/@$players for $beg .. $end-1;
$result .= sprintf "%3.1f %s\n", $avg, join ', ', sort @$players;
}
return $result;
}
print "Standard:\n" . standard(%scores) . "\n";
print "Modified:\n" . modified(%scores) . "\n";
print "Dense:\n" . dense(%scores) . "\n";
print "Ordinal:\n" . ordinal(%scores) . "\n";
print "Fractional:\n" . fractional(%scores) . "\n";

View file

@ -0,0 +1,55 @@
function ties(sequence scores)
sequence t = {}, -- {start,num} pairs
tdx = repeat(0,length(scores))
integer last = -1
for i=1 to length(scores) do
integer this = scores[i][1]
if this=last then
t[$][2] += 1
else
t = append(t,{i,1})
end if
tdx[i] = length(t)
last = this
end for
-- eg {{{1,1},{2,2},{4,3},{7,1}},
-- {1,2,2,3,3,3,4}}
return {t,tdx}
end function
enum STANDARD, -- eg {1,2,2,4,4,4,7}
MODIFIED, -- eg {1,3,3,6,6,6,7}
DENSE, -- (==tdx)
ORDINAL, -- eg {1,2,3,4,5,6,7}
FRACTION, -- {1,2.5,2.5,5,5,5,7}
METHODS = $
function rank(integer i, method, sequence t, tdx)
integer idx = tdx[i],
{tx,tn} = t[idx]
switch method
case STANDARD: return tx
case MODIFIED: return tx+tn-1
case DENSE : return idx
case ORDINAL : return i
case FRACTION: return tx+(tn-1)/2
end switch
end function
constant scores = {{44, "Solomon"},
{42, "Jason"},
{42, "Errol"},
{41, "Garry"},
{41, "Bernard"},
{41, "Barry"},
{39, "Stephen"}}
sequence {t,tdx} = ties(scores)
printf(1," score name standard modified dense ordinal fractional\n")
for i=1 to length(scores) do
sequence ranks = repeat(0,METHODS)
for method=1 to METHODS do
ranks[method] = rank(i,method,t,tdx)
end for
printf(1,"%5d %-7s %6g %8g %6g %6g %9g\n",scores[i]&ranks)
end for