The Amateur Extra test is 50 questions, multiple choice, with 4 answers per question. A passing grade is 35 or more. A few minutes of programming this morning, even before I had any coffee yielded that the **exact** probability of passing was:

4677523340461106447 ------------------------------ 158456325028528675187087900672

or about 1 in 33.9 billion.

This wasn’t that interesting of a question, but to solve it, I hacked up a quick but limited implementation of rational arithmetic in Python. I was wondering if there was a better way to implement this in Python so overloading would “just work”. I didn’t know how, and the problem was simple enough, so I didn’t try. Here’s my solution.

#!/usr/bin/env python def gcd(a, b): if (a < b): a, b = b, a while b != 0: a, b = b, a%b return a class Rational: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return "[%d / %d]" % (self.a, self.b) def pow(self, p): return Rational(pow(self.a, p), pow(self.b, p)) def mult(self, r): tmpa = self.a * r.a ; tmpb = self.b * r.b ; d = gcd(tmpa, tmpb) return Rational(tmpa//d, tmpb//d) def imult(self, i): tmpa = self.a * i ; tmpb = self.b ; d = gcd(tmpa, tmpb) return Rational(tmpa//d, tmpb//d) def add(self, r): tmpa = self.a * r.b + r.a * self.b tmpb = self.b * r.b d = gcd(tmpa, tmpb) return Rational(tmpa//d, tmpb//d) p = Rational(1, 4) q = Rational(3, 4) def fact(n): c = 1 while n > 1: c = c * n n = n - 1 return c def comb(a, b): return fact(a)/(fact(b)*fact(a-b)) total = Rational(0, 1) for t in range(35, 51): x = p.pow(t).mult(q.pow(50-t)).imult(comb(50, t)) total = total.add(x) print "Exact probability is", total print "Only about 1 in", total.b // total.a, "will pass"