Skip to content

Instantly share code, notes, and snippets.

@nichanank
Last active February 21, 2021 09:09
Show Gist options
  • Save nichanank/9e35b1188019eb9513d322eec185ec12 to your computer and use it in GitHub Desktop.
Save nichanank/9e35b1188019eb9513d322eec185ec12 to your computer and use it in GitHub Desktop.
adapted version of bytebracket_scorer
"""
This is an adapted version of the original ByteBracket library https://gist.github.com/pursuingpareto/b15f1197d96b1a2bbc48 that was implemented to score a 63-game NCAA tournament
Whitepaper: https://drive.google.com/file/d/0BxHbbgrucCx2N1MxcnA1ZE1WQW8/view
"""
import random
def score(bracket, results, filt,
teams_remaining, blacklist, round_num=0):
"""
Recursively calculates the score of a prediction
bracket against a results bracket.
- bracket
A bitstring representing a prediction bracket. For
a 64 game tournament this would be 63 bits.
- results
A bitstring representing the actual outcome of
a tournament.
- filt
With the exception of the first round in a tournament,
its not possible to score a round by just comparing
the bits in bracket to the bits in results. For example,
correctly predicting the championship game requires not
only the correct bit for that game, but also the correct
prediction for all the games the tournament winner had
won before the final round.
The filt parameter is a one time pre-computed bitstring
used to indicate which games in a round must be
correctly predicted in order to correctly predict
successive games. For a 64 game tournament filt would
contain 62 bits.
if we have a four game brakcet
- teams_remaining
This is a recursive function where each call
represents another tournament round.
teams_remaining gives the number of teams left in the
tournament as of this function call.
- blacklist
This parameter is a sequence of N bits where N is
the number of games in the current round. It uses
the accuracy of predictions from previous rounds to
"remember" which games are possible to correctly
predict. When calling the score function initially
these bits should all be set to 1.
- round_num
A number representing the current round. For a 64 team
tournament this would take the values 0,1,2,3,4, and 5
"""
# First check if there is a winner
if teams_remaining == 1 :
return 0
# 1. get points for THIS round
# compute constants for round
num_games = int(teams_remaining / 2)
round_mask = 2 ** num_games - 1 # all bits set to 0 except the bits corresponding to the current round
# the current round is encoded in num_games
# least significant bits. Likewise for results and filter
round_predictions = bracket & round_mask
round_results = results & round_mask
round_filter = filt & round_mask
# The overlap between the prediction bits and the
# results bits is calculated by XORing the two and
# then flipping the bits remaining.
overlap = ~(round_predictions ^ round_results)
# blacklist tells you to not count scores with wrong predictions in previous rounds. decrease the number of 1s in overlap
# In all rounds except the first, overlap will tend
# to overestimate a bracket's correctness. This is
# corrected by ANDing the overlap with the blacklist
scores = overlap & blacklist
# the points for this round are calculated by counting
# the number of 1s in the scores bitstring and then
# multiplying by 2 ^ round_num (this multiplication
# is used to weigh predictions in later rounds more
# heavily than earlier rounds)
points = popcount(scores) << round_num
# 2. remember stuff based on where you were correct
# with the points calculated we can now use the pre-computed filter to figure out which of these predictions may impact future predictions
# round filter tells you what matters for subsequent rounds
relevant_scores = scores & round_filter
# For each pair of games in this round, look for a 1 in either of the bits to compute the blacklist for the next round.
# in the next round, adjacent bits are playing against eachother
even_bits, odd_bits = get_odds_and_evens_32(relevant_scores)
blacklist = even_bits | odd_bits
# 3. update variables for the next recursive call
bracket = bracket >> num_games
results = results >> num_games
filt = filt >> num_games
# print "----------------"
# print "Round score: " + str(points)
# print "----------------"
return points + score(bracket, results, filt,
int(teams_remaining / 2), blacklist, round_num + 1)
def score_group_stage(bracket, results):
# 1. split prediction and results brackets into separate arrays of its odd and even elements
bracketEvens, bracketOdds = get_odds_and_evens_64(bracket)
resultsEvens, resultsOdds = get_odds_and_evens_64(results)
# 2. find the overlap between the odd and even elements of prediction and results
evensOverlap = ~(bracketEvens ^ resultsEvens)
oddsOverlap = ~(bracketOdds ^ resultsOdds)
# 3. find the overall overlap by ANDing the even and odds overlap
# both the even and odd elements have to match for the player to score a point
overlap = evensOverlap & oddsOverlap
# 4. count the number of 1s in the overlap
scores = popcount_32(overlap)
return scores
def get_odds_and_evens_8(bits):
"""
Separates the even and odd bits by repeatedly
shuffling smaller segments of a bitstring.
"""
tmp = (bits ^ (bits >> 1)) & 0x22; # 00100010
bits ^= (tmp ^ (tmp << 1));
tmp = (bits ^ (bits >> 2)) & 0x0c; # 00001100
bits ^= (tmp ^ (tmp << 2));
evens = bits >> 4
odds = bits % 0x10
return evens, odds
def get_odds_and_evens_16(bits):
"""
Separates the even and odd bits by repeatedly
shuffling smaller segments of a bitstring.
"""
tmp = (bits ^ (bits >> 1)) & 0x2222; # 0010001000100010
bits ^= (tmp ^ (tmp << 1));
tmp = (bits ^ (bits >> 2)) & 0x0c0c; # 0000110000001100
bits ^= (tmp ^ (tmp << 2));
tmp = (bits ^ (bits >> 4)) & 0x00f0; # 0000000011110000
bits ^= (tmp ^ (tmp << 4));
evens = bits >> 8
odds = bits % 0x100
return evens, odds
def get_odds_and_evens_32(bits):
"""
Separates the even and odd bits by repeatedly
shuffling smaller segments of a bitstring.
"""
tmp = (bits ^ (bits >> 1)) & 0x22222222; # 00100010001000100010001000100010
bits ^= (tmp ^ (tmp << 1));
tmp = (bits ^ (bits >> 2)) & 0x0c0c0c0c; # 00001100000011000000110000001100
bits ^= (tmp ^ (tmp << 2));
tmp = (bits ^ (bits >> 4)) & 0x00f000f0; # 00000000111100000000000011110000
bits ^= (tmp ^ (tmp << 4));
tmp = (bits ^ (bits >> 8)) & 0x0000ff00; # 00000000000000001111111100000000
bits ^= (tmp ^ (tmp << 8));
evens = bits >> 16
odds = bits % 0x10000
return evens, odds
def get_odds_and_evens_64(bits):
"""
Separates the even and odd bits by repeatedly
shuffling smaller segments of a bitstring.
"""
tmp = (bits ^ (bits >> 1)) & 0x2222222222222222; # 0010001000100010001000100010001000100010001000100010001000100010
bits ^= (tmp ^ (tmp << 1));
tmp = (bits ^ (bits >> 2)) & 0x0c0c0c0c0c0c0c0c; # 0000110000001100000011000000110000001100000011000000110000001100
bits ^= (tmp ^ (tmp << 2));
tmp = (bits ^ (bits >> 4)) & 0x00f000f000f000f0; # 0000000011110000000000001111000000000000111100000000000011110000
bits ^= (tmp ^ (tmp << 4));
tmp = (bits ^ (bits >> 8)) & 0x0000ff000000ff00; # 0000000000000000111111110000000000000000000000001111111100000000
bits ^= (tmp ^ (tmp << 8));
tmp = (bits ^ (bits >> 16)) & 0x00000000ffff0000; # 0000000000000000000000000000000011111111111111110000000000000000
bits ^= (tmp ^ (tmp << 16));
evens = bits >> 32
odds = bits % 0x100000000
return evens, odds
def get_odds_and_evens_96(bits):
"""
Separates the even and odd bits by repeatedly
shuffling smaller segments of a bitstring.
"""
tmp = (bits ^ (bits >> 1)) & 0x222222222222222222222222; # 001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010
bits ^= (tmp ^ (tmp << 1));
tmp = (bits ^ (bits >> 2)) & 0x0c0c0c0c0c0c0c0c0c0c0c0c; # 000011000000110000001100000011000000110000001100000011000000110000001100000011000000110000001100
bits ^= (tmp ^ (tmp << 2));
tmp = (bits ^ (bits >> 4)) & 0x000000f000f000f000f000f0; # 000000001111000000000000111100000000000011110000000000001111000000000000111100000000000011110000
bits ^= (tmp ^ (tmp << 4));
tmp = (bits ^ (bits >> 8)) & 0x0000ff000000ff000000ff00; # 000000000000000011111111000000000000000000000000111111110000000000000000000000001111111100000000
bits ^= (tmp ^ (tmp << 8));
tmp = (bits ^ (bits >> 16)) & 0x00000000ffff000000000000; # 000000000000000000000000000000001111111111111111000000000000000000000000000000000000000000000000
bits ^= (tmp ^ (tmp << 16));
tmp = (bits ^ (bits >> 24)) & 0x000000000000ffffff000000; # 000000000000000000000000000000000000000000000000111111111111111111111111000000000000000000000000
bits ^= (tmp ^ (tmp << 24));
# tmp = (bits ^ (bits >> 32)) & 0x0000000000000000ffffffff; # 000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111
# bits ^= (tmp ^ (tmp << 32));
evens = bits >> 38
odds = bits % 0x1000000000000
return evens, odds
def get_odds_and_evens_128(bits):
"""
Separates the even and odd bits by repeatedly
shuffling smaller segments of a bitstring.
"""
tmp = (bits ^ (bits >> 1)) & 0x22222222222222222222222222222222; # 00100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010
bits ^= (tmp ^ (tmp << 1));
tmp = (bits ^ (bits >> 2)) & 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c; # 00001100000011000000110000001100000011000000110000001100000011000000110000001100000011000000110000001100000011000000110000001100
bits ^= (tmp ^ (tmp << 2));
tmp = (bits ^ (bits >> 4)) & 0x00f000f000f000f000f000f000f000f0; # 00000000111100000000000011110000000000001111000000000000111100000000000011110000000000001111000000000000111100000000000011110000
bits ^= (tmp ^ (tmp << 4));
tmp = (bits ^ (bits >> 8)) & 0x0000ff000000ff000000ff000000ff00; # 00000000000000001111111100000000000000000000000011111111000000000000000000000000111111110000000000000000000000001111111100000000
bits ^= (tmp ^ (tmp << 8));
tmp = (bits ^ (bits >> 16)) & 0x00000000ffff000000000000ffff0000; # 00000000000000000000000000000000111111111111111100000000000000000000000000000000000000000000000011111111111111110000000000000000
bits ^= (tmp ^ (tmp << 16));
tmp = (bits ^ (bits >> 32)) & 0x0000000000000000ffffffff00000000; # 00000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111100000000000000000000000000000000
bits ^= (tmp ^ (tmp << 32));
evens = bits >> 64
odds = bits % 0x10000000000000000
return evens, odds
def popcount_8(i):
"""
Counts the number of 1s in an 8-bit bitstring.
"""
i = i - ((i >> 1) & 0x55)
i = (i & 0x33) + ((i >> 2) & 0x33)
i = (i + (i >> 4)) & 0x0f
return ((i * 0x01) & 0xff)
def popcount_16(i):
"""
Counts the number of 1s in a 16-bit bitstring.
"""
i = i - ((i >> 1) & 0x5555)
i = (i & 0x3333) + ((i >> 2) & 0x3333)
i = (i + (i >> 4)) & 0x0f0f
return ((i * 0x0101) & 0xffff) >> 8
def popcount_32(i):
"""
Counts the number of 1s in a 32-bit bitstring.
"""
i = i - ((i >> 1) & 0x55555555)
i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
i = (i + (i >> 4)) & 0x0f0f0f0f
return ((i * 0x01010101) & 0xffffffff) >> 24
def popcount_48(i):
"""
Counts the number of 1s in a 48-bit bitstring.
"""
i = i - ((i >> 1) & 0x555555555555)
i = (i & 0x333333333333) + ((i >> 2) & 0x333333333333)
i = (i + (i >> 4)) & 0x0f0f0f0f0f0f
return ((i * 0x010101010101) & 0xffffffffffff) >> 40
def popcount_64(i):
"""
Counts the number of 1s in a 64-bit bitstring.
"""
i = i - ((i >> 1) & 0x5555555555555555)
i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333)
i = (i + (i >> 4)) & 0x0f0f0f0f0f0f0f0f
return ((i * 0x0101010101010101) & 0xffffffffffffffff) >> 56
def popcount_96(i):
"""
Counts the number of 1s in a 96-bit bitstring.
"""
i = i - ((i >> 1) & 0x555555555555555555555555)
i = (i & 0x333333333333333333333333) + ((i >> 2) & 0x333333333333333333333333)
i = (i + (i >> 4)) & 0x0f0f0f0f0f0f0f0f0f0f0f0f
return ((i * 0x010101010101010101010101) & 0xffffffffffffffffffffffff) >> 88
def popcount(x):
"""
Counts the number of 1s in a bitstring.
"""
x -= (x >> 1) & 0x5555555555555555
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333)
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f
return ((x * 0x0101010101010101) & 0xffffffffffffffff ) >> 56
# this function can be slow since it would only be called once
# when the tournament is over.
def make_mask_binary(results, teams_remaining):
future_rounds = results & (2 ** (teams_remaining/2) - 1)
mask = ""
for res in bin(future_rounds)[2:]: # count from second MSB
# if lower team wins, only care about lower team
if res == "0":
mask += "01"
else:
mask += "10"
mask = mask[::-1]
return int(mask, 2)
def make_test(bracket, results, N=64):
blacklist = int("1" * (N/2), 2)
filt = make_mask_binary(results, N)
return blacklist, filt
def test_ncaa_scoring():
results = int("1" * 63, 2)
bracket = int("1" * 63, 2)
blacklist, filt = make_test(bracket, results)
assert score(bracket, results, filt, 64, blacklist) == 192
bracket = int("0" * 31 + "1" * 32, 2)
blacklist, filt = make_test(bracket, results)
assert score(bracket, results, filt, 64, blacklist) == 32
bracket = int("1" * 15 + "0" * 16 + "1" * 32, 2)
blacklist, filt = make_test(bracket, results)
assert score(bracket, results, filt, 64, blacklist) == 32
bracket = int("1" * 15 + "01" * 8 + "1" * 32, 2)
blacklist, filt = make_test(bracket, results)
assert score(bracket, results, filt, 64, blacklist) == (192 - 2*8)
bracket = int("1" * 15 + "10" * 8 + "1" * 32, 2)
blacklist, filt = make_test(bracket, results)
assert score(bracket, results, filt, 64, blacklist) == (32 + 2*8)
for _ in range(10):
s = ""
for i in range(63):
s += random.choice(["1", "0"])
bracket = int(s, 2)
results = bracket
assert score(bracket, results, filt, 64, blacklist) == 192
print "ncaa 64-team bracket tests pass"
def test_knockout_stage_scoring():
print "Scenario: perfect bracket"
print "Calculation: (4*2) + (2*4) + (1*8)"
results = int("1111111", 2)
bracket = int("1111111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 24
print "Scenario: all of first round correct, all of second round correct, last round incorrect"
print "Calculation: (4*2) + (2*4) + 0"
bracket = int("0" + "11" + "1111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 16
print "Scenario: all of first round correct, half of second round correct, last round correct (doens't count)"
print "Calculation: (4*2) + (1*4)"
bracket = int("1" + "10" + "1111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 12
print "Scenario: all of first round correct, half of second round correct, last round correct (counts)"
print "Calculation: (4*2) + (1*4) + (1*8)"
bracket = int("1" + "01" + "1111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 20
print "Scenario: all of first round correct, none of subsequent rounds correct"
print "Calculation: (4*2) + 0 + 0"
bracket = int("0" * 3 + "1" * 4, 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 8
print "Scenario: half of first round correct, none of subsequent rounds correct"
print "Calculation: (2*2) + 0 + 0"
bracket = int("0" * 3 + "10" * 2, 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 4
print "Scenario: half of first round correct, all subsequent rounds correct (counts)"
print "Calculation: (2*2) + (2*4) + (1*8)"
bracket = int("1" + "11" + "0101", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 20
print "Scenario: half of first round correct, all subsequent rounds correct (doesn't count)"
print "Calculation: (2*2) + 0 + 0"
bracket = int("1" + "11" + "1010", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 4
print "Scenario: 3/4 of first round correct, none of subsequent rounds correct"
print "Calculation: (3*2) + 0 + 0"
bracket = int("0" + "00" + "0111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 6
print "Scenario: 3/4 of first round correct, all second round correct, last round incorrect"
print "Calculation: (3*2) + (2*4) + 0"
bracket = int("0" + "11" + "0111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 14
print "Scenario: 3/4 of first round correct, half of second round correct, last round incorrect"
print "Calculation: (3*2) + (1*4) + 0"
bracket = int("0" + "01" + "0111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 10
print "Scenario: 3/4 of first round correct, half of second round correct, last round correct (doesn't count)"
print "Calculation: (3*2) + (1*4) + 0"
bracket = int("1" + "10" + "0111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 10
print "Scenario: 3/4 of first round correct, half of second round correct, last round correct (counts)"
print "Calculation: (3*2) + (1*4) + (1*8)"
bracket = int("1" + "01" + "0111", 2)
blacklist, filt = make_test(bracket, results, 8)
final_score = score(bracket, results, filt, 8, blacklist, 1)
print "---------"
print "Total: " + str(final_score)
print "---------\n"
assert final_score == 18
for _ in range(10):
s = ""
for i in range(7):
s += random.choice(["1", "0"])
bracket = int(s, 2)
results = bracket
final_score = score(bracket, results, filt, 8, blacklist, 1)
assert final_score == 24
for _ in range(100):
s = ""
r = ""
for i in range(7):
s += random.choice(["1", "0"])
for j in range(7):
r += random.choice(["1", "0"])
bracket = int(s, 2)
results = int(r, 2)
final_score = score(bracket, results, filt, 8, blacklist, 1)
# all possible scores are even numbers between 0 and 24
assert 0 <= final_score <= 24 and final_score % 2 == 0
print "knockout stage tests pass"
def test_get_odds_and_evens_8():
for _ in range(10):
test_case = ""
expected_odds = ""
expected_evens = ""
expected = 0
for i in range(8):
next_bit = random.choice(["1", "0"])
if i % 2 != 0:
expected_evens += next_bit
else:
expected_odds += next_bit
test_case += next_bit
(test_odds, test_evens) = get_odds_and_evens_8(int(test_case, 2))
# add padding as python automatically truncates leading 0s in binary
padding_odds = "0" * (len(expected_odds) - len(bin(test_odds)[2:]))
padding_evens = "0" * (len(expected_evens) - len(bin(test_evens)[2:]))
assert padding_odds + bin(test_odds)[2:] == expected_odds
assert padding_evens + bin(test_evens)[2:] == expected_evens
print "get_odds_and_evens_8 tests pass"
def test_get_odds_and_evens_16():
for _ in range(10):
test_case = ""
expected_odds = ""
expected_evens = ""
expected = 0
for i in range(16):
next_bit = random.choice(["1", "0"])
if i % 2 != 0:
expected_evens += next_bit
else:
expected_odds += next_bit
test_case += next_bit
(test_odds, test_evens) = get_odds_and_evens_16(int(test_case, 2))
# add padding as python automatically truncates leading 0s in binary
padding_odds = "0" * (len(expected_odds) - len(bin(test_odds)[2:]))
padding_evens = "0" * (len(expected_evens) - len(bin(test_evens)[2:]))
assert padding_odds + bin(test_odds)[2:] == expected_odds
assert padding_evens + bin(test_evens)[2:] == expected_evens
print "get_odds_and_evens_16 tests pass"
def test_get_odds_and_evens_32():
for _ in range(10):
test_case = ""
expected_odds = ""
expected_evens = ""
expected = 0
for i in range(32):
next_bit = random.choice(["1", "0"])
if i % 2 != 0:
expected_evens += next_bit
else:
expected_odds += next_bit
test_case += next_bit
(test_odds, test_evens) = get_odds_and_evens_32(int(test_case, 2))
# add padding as python automatically truncates leading 0s in binary
padding_odds = "0" * (len(expected_odds) - len(bin(test_odds)[2:]))
padding_evens = "0" * (len(expected_evens) - len(bin(test_evens)[2:]))
assert padding_odds + bin(test_odds)[2:] == expected_odds
assert padding_evens + bin(test_evens)[2:] == expected_evens
print "get_odds_and_evens_32 tests pass"
def test_get_odds_and_evens_64():
for _ in range(10):
test_case = ""
expected_odds = ""
expected_evens = ""
expected = 0
for i in range(64):
next_bit = random.choice(["1", "0"])
if i % 2 != 0:
expected_evens += next_bit
else:
expected_odds += next_bit
test_case += next_bit
(test_odds, test_evens) = get_odds_and_evens_64(int(test_case, 2))
# add padding as python automatically truncates leading 0s in binary
padding_odds = "0" * (len(expected_odds) - len(bin(test_odds)[2:]))
padding_evens = "0" * (len(expected_evens) - len(bin(test_evens)[2:]))
assert padding_odds + bin(test_odds)[2:] == expected_odds
assert padding_evens + bin(test_evens)[2:] == expected_evens
print "get_odds_and_evens_64 tests pass"
def test_get_odds_and_evens_96():
for _ in range(10):
test_case = ""
expected_odds = ""
expected_evens = ""
expected = 0
for i in range(96):
next_bit = random.choice(["1", "0"])
if i % 2 != 0:
expected_evens += next_bit
else:
expected_odds += next_bit
test_case += next_bit
(test_odds, test_evens) = get_odds_and_evens_96(int(test_case, 2))
# add padding as python automatically truncates leading 0s in binary
padding_odds = "0" * (len(expected_odds) - len(bin(test_odds)[2:]))
padding_evens = "0" * (len(expected_evens) - len(bin(test_evens)[2:]))
print expected_evens
print bin(test_evens)[2:]
print expected_odds
print bin(test_odds)[2:]
# print expected_evens
# print padding_evens + bin(test_evens)[2:]
# print expected_odds
# print padding_odds + bin(test_odds)[2:]
assert padding_odds + bin(test_odds)[2:] == expected_odds
assert padding_evens + bin(test_evens)[2:] == expected_evens
print "get_odds_and_evens_96 tests pass"
def test_get_odds_and_evens_128():
for _ in range(10):
test_case = ""
expected_odds = ""
expected_evens = ""
expected = 0
for i in range(128):
next_bit = random.choice(["1", "0"])
if i % 2 != 0:
expected_evens += next_bit
else:
expected_odds += next_bit
test_case += next_bit
(test_odds, test_evens) = get_odds_and_evens_128(int(test_case, 2))
# add padding as python automatically truncates leading 0s in binary
padding_odds = "0" * (len(expected_odds) - len(bin(test_odds)[2:]))
padding_evens = "0" * (len(expected_evens) - len(bin(test_evens)[2:]))
assert padding_odds + bin(test_odds)[2:] == expected_odds
assert padding_evens + bin(test_evens)[2:] == expected_evens
print "get_odds_and_evens_128 tests pass"
def test_popcount_8():
for _ in range(10):
test_case = ""
expected = 0
for i in range(8):
next_bit = random.choice(["1", "0"])
if next_bit == "1":
expected += 1
test_case += next_bit
assert popcount_8(int(test_case, 2)) == expected
print "popcount_8 tests pass"
def test_popcount_16():
for _ in range(10):
test_case = ""
expected = 0
for i in range(16):
next_bit = random.choice(["1", "0"])
if next_bit == "1":
expected += 1
test_case += next_bit
assert popcount_16(int(test_case, 2)) == expected
print "popcount_16 tests pass"
def test_popcount_32():
for _ in range(10):
test_case = ""
expected = 0
for i in range(32):
next_bit = random.choice(["1", "0"])
if next_bit == "1":
expected += 1
test_case += next_bit
assert popcount_32(int(test_case, 2)) == expected
print "popcount_32 tests pass"
def test_popcount_48():
for _ in range(10):
test_case = ""
expected = 0
for i in range(48):
next_bit = random.choice(["1", "0"])
if next_bit == "1":
expected += 1
test_case += next_bit
assert popcount_48(int(test_case, 2)) == expected
print "popcount_48 tests pass"
def test_popcount_64():
for _ in range(10):
test_case = ""
expected = 0
for i in range(64):
next_bit = random.choice(["1", "0"])
if next_bit == "1":
expected += 1
test_case += next_bit
assert popcount_64(int(test_case, 2)) == expected
print "popcount_64 tests pass"
def test_popcount_96():
for _ in range(10):
test_case = ""
expected = 0
for i in range(96):
next_bit = random.choice(["1", "0"])
if next_bit == "1":
expected += 1
test_case += next_bit
assert popcount_96(int(test_case, 2)) == expected
print "popcount_96 tests pass"
def test_group_stage_scoring():
for _ in range(10):
test_bracket = ""
test_result = ""
expected_score = 0
for i in range(32):
next_result = random.choice(["10", "01", "11"])
next_bracket = random.choice(["10", "01", "11"])
if next_bracket == next_result:
expected_score += 1
test_bracket += next_bracket
test_result += next_result
test_score = score_group_stage(int(test_bracket, 2), int(test_result, 2))
assert test_score == expected_score
print "group stage tests pass"
test_popcount_8()
test_popcount_16()
test_popcount_32()
test_popcount_48()
test_popcount_64()
test_popcount_96()
test_get_odds_and_evens_8()
test_get_odds_and_evens_16()
test_get_odds_and_evens_32()
test_get_odds_and_evens_64()
# test_get_odds_and_evens_96()
test_get_odds_and_evens_128()
test_ncaa_scoring()
test_group_stage_scoring()
test_knockout_stage_scoring()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment