Skip to content

Instantly share code, notes, and snippets.

@Noble-Mushtak
Created January 15, 2021 03:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Noble-Mushtak/2fc50b2c7321e857e75f0fa5cec889de to your computer and use it in GitHub Desktop.
Save Noble-Mushtak/2fc50b2c7321e857e75f0fa5cec889de to your computer and use it in GitHub Desktop.
Calculate the place corresponding to every possible score in the Putnam 2019 competition
"""
Usage: python3 calc_putnam_places.py [score]
If score is not provided,
the script prints the place corresponding to every score
any Putnam competitor got in the Putnam 2019 competition.
If score is provided and is an integer,
the script prints the place corresponding to that score.
"""
import sys
# Copy and pasted from page 4 of https://www.maa.org/sites/default/files/pdf/Putnam/2019/AnnouncementOfWinners2019.pdf
raw_rank_table = """120 1 90 19 68 41 53 84.5 38 192 24 384 10 1088.5
119 2.5 89 20 67 43.5 52 86.5 37 199 23 403 9 1235.5
117 4 87 21 66 45 51 90.5 36 206 22 436 8 1368
103 5 85 22 65 47 50 101 35 212 21 478.5 7 1483
102 6 82 23 64 49 49 114 34 218.5 20 532 6 1558
101 7.5 81 24 63 51 48 122 33 227 19 585.5 5 1606.5
100 9 80 26.5 62 53.5 47 126.5 32 236.5 18 627 4 1680.5
99 10 79 29.5 61 56.5 45 129.5 31 249.5 17 667 3 1831.5
98 11 76 31 60 61.5 44 133.5 30 276 16 698 2 2103
97 12.5 75 32 59 67 43 138 29 306.5 15 722 1 2447.5
95 14 73 33 58 73 42 143.5 28 327.5 14 758.5 0 3428
94 15.5 72 34.5 57 77 41 153 27 344.5 13 807.5
92 17 71 37 56 79 40 168 26 360 12 879
91 18 69 39 54 82 39 183.5 25 371.5 11 970"""
def ordinal_suffix(num):
"""
Returns suffix of num, which is expected to be a non-negative integer
"""
num %= 100
if 4 <= num <= 20:
return "th"
if (num % 10) == 1:
return "st"
if (num % 10) == 2:
return "nd"
if (num % 10) == 3:
return "rd"
return "th"
def as_ordinal(num):
"""
Given non-negative integer num,
output a string representation of num as an ordinal number
"""
return str(num)+ordinal_suffix(num)
def main(raw_rank_table, given_score=None):
"""
Given raw_rank_table, the score-rank correspondence of Putnam scores,
output the places that correspond to each score.
If given_score is an integer rather than None,
output the place corresponding to score
"""
rank_table = [None]*121
tokens = (token for token in raw_rank_table.split())
while True:
try:
score = int(next(tokens))
except StopIteration:
break
rank_table[score] = float(next(tokens))
place_table = {}
prev_place = 0
for score, rank in reversed(list(enumerate(rank_table))):
if rank == None: continue
"""
All the people who got score of _score_
represent the people in places prev_place+1 to cur_place, inclusive.
We want the average of their places to be _rank_, so:
(prev_place+1 + cur_place) // 2 == rank
Then, solve for cur_place.
"""
cur_place = int(2*rank-prev_place-1)
place_table[score] = cur_place
prev_place = cur_place
printed_something = False
prev_place = 0
for score, place in reversed(sorted(place_table.items(), key=lambda tpl: tpl[0])):
if given_score == None or given_score == score:
if place == prev_place+1:
print(f"If your score was { score }, you came in { as_ordinal(place) } place")
else:
print(f"If your score was { score }, you tied for { as_ordinal(place) } place")
printed_something = True
prev_place = place
# If nothing was printed, then output error message:
if not printed_something:
print(f"No one got a score of { given_score }")
if __name__ == "__main__":
if len(sys.argv) > 1:
try:
score = int(sys.argv[1])
except ValueError:
print(f"\"{ sys.argv[1] }\" is not an integer")
sys.exit(1)
else:
score = None
main(raw_rank_table, score)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment