-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathranker.py
More file actions
133 lines (103 loc) · 3.75 KB
/
ranker.py
File metadata and controls
133 lines (103 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python3
"""
@file ranker.py
@brief Ranking program.
@author Evan Elias Young
@date 2020-03-13
@date 2022-02-04
@copyright Copyright 2022 Evan Elias Young. All rights reserved.
"""
def get_total_rounds(num_options: int) -> int:
"""Determines the total rounds of ratings.
Arguments:
num_options {int} -- The number of options.
Returns:
int -- The number of rounds.
"""
return sum(range(1, num_options))
def get_better_option(opt1: str, opt2: str, ind1: int, ind2: int) -> int:
"""Determines the better option, given two.
Arguments:
opt1 {str} -- The first option.
opt2 {str} -- The second option.
ind1 {int} -- The first option's index.
ind2 {int} -- The second option's index.
Returns:
int -- The index of the bettwe option.
"""
print(f"{ind1 + 1:2} -- {opt1}")
print(f"{ind2 + 1:2} -- {opt2}")
choice: int = int(input(f"Which is better {ind1 + 1} or {ind2 + 1}:\n")) - 1
return choice
def rank_main(options: list[str]) -> list[int]:
"""Ranks the initial collection of options.
Arguments:
options {list[str]} -- The options to rank.
Returns:
list[int] -- The scores associated with each option.
"""
# The points associated with each option.
scores: list[int] = [0] * len(options)
for i, opt1 in enumerate(options):
for j, opt2 in enumerate(options):
# If the options are not the same and haven't already been compared.
if i != j and j > i:
choice: int = get_better_option(opt1, opt2, i, j)
scores[choice] += 1
return scores
def rank_ties(options: list[str], scores: list[int]) -> list[int]:
"""Ranks the ties within the options.
Arguments:
options {list[str]} -- The options to rank.
scores {list[int]} -- The scores associated with each option.
Returns:
list[int] -- The new scores with no ties.
"""
# While there are duplicate scores in the list.
while list(set(scores)) != sorted(scores):
for i, score1 in enumerate(scores):
for j, score2 in enumerate(scores):
# If the options are not the same and have the same score.
if i != j and score1 == score2:
choice: int = get_better_option(options[i], options[j], i, j)
scores[choice] += 1
return scores
def sort_scores(options: list[str], scores: list[int]) -> list[str]:
"""Sorts the options into the final comparison.
Arguments:
options {list[str]} -- The options to rank.
scores {list[int]} -- The scores associated with each option.
Returns:
list[int] -- The ranked items in order.
"""
# Zip the scores and the options together.
zipped_pairs: zip = zip(scores, options)
# Sort the zip.
sort = list(reversed([e for _, e in sorted(zipped_pairs)]))
return sort
def main() -> None:
"""The main of the program."""
# The options to rank.
user_options: list[str] = []
while True:
tmp: str = input("Option:\n")
if tmp == "":
break
user_options.append(tmp)
print()
# The points associated with each option.
user_scores: list[int] = rank_main(user_options)
print()
user_scores = rank_ties(user_options, user_scores)
print()
# Sort the zip.
sort = sort_scores(user_options, user_scores)
print("Rank -- Top 50% -- Score -- Name")
for i, opt in enumerate(sort):
print(
f'{i + 1:4} -- {("Y" if (len(user_options) - i) / len(user_options) > 0.5 else " "):^7} -- {user_scores[user_options.index(opt)]:5} -- {opt}'
)
if __name__ == "__main__":
print("Hello, Console!")
print()
main()