def problem113(): DIGITS = 100 increasing = eulerlib.binomial(DIGITS + 9, 9) - 1 decreasing = eulerlib.binomial(DIGITS + 10, 10) - (DIGITS + 1) flat = DIGITS * 9 ans = increasing + decreasing - flat return ans
def problem106(): SET_SIZE = 12 def catalan(n): return eulerlib.binomial(n * 2, n) // (n + 1) ans = sum( eulerlib.binomial(SET_SIZE, i * 2) * (eulerlib.binomial(i * 2, i) // 2 - catalan(i)) for i in range(2, SET_SIZE // 2 + 1)) return ans
def explore(remain, limit, history): if remain == 0: hist = list(history) while len(hist) < num_colors: hist.append(0) histogram = [0] * (balls_per_color + 1) for _ in hist: histogram[_] += 1 count = math.factorial(num_colors) for _ in histogram: count = divide_exactly(count, math.factorial(_)) for _ in hist: count *= eulerlib.binomial(balls_per_color, _) distinctcolors = len(history) numerator[0] += count * distinctcolors elif len(history) < num_colors: for i in range(min(limit, remain), 0, -1): history.append(i) explore(remain - i, i, history) history.pop()
def problem053(): """ There are exactly ten ways of selecting three from five, 12345: 123, 124, 125, 134, 135, 145, 234, 235, 245, and 345 In combinatorics, we use the notation, ^5C[3] = 10. In general, ^nC[r] = n! ,where r ≤ n, n! = n×(n−1)×...×3×2×1, and 0! = 1. r!(n−r)! It is not until n = 23, that a value exceeds one-million: ^23C[10] = 1144066. How many, not necessarily distinct, values of ^nC[r], for 1 ≤ n ≤ 100, are greater than one-million? """ ans = sum(1 for n in range(1, 101) for k in range(0, n + 1) if eulerlib.binomial(n, k) > 1000000) return ans
def problem323(): SIZE = 32 DECIMALS = 10 assert SIZE >= 0 assert DECIMALS >= 0 # Calculate the answer expect = [fractions.Fraction(0)] for n in range(1, SIZE + 1): temp = sum(eulerlib.binomial(n, k) * expect[k] for k in range(n)) expect.append((2**n + temp) / (2**n - 1)) ans = expect[-1] # Round the fraction properly. This is the pedantically # correct version of doing "{:.10f}".format(float(ans)) assert ans >= 0 scaled = ans * 10**DECIMALS whole = scaled.numerator // scaled.denominator frac = scaled - whole assert 0 <= frac < 1 HALF = fractions.Fraction(1, 2) if frac > HALF or (frac == HALF and whole % 2 == 1): whole += 1 temp = str(whole) if DECIMALS == 0: return temp temp = temp.zfill(DECIMALS + 1) return "{}.{}".format(temp[:-DECIMALS], temp[-DECIMALS:])
def problem015(): """ Starting in the top left corner of a 2×2 grid, and only being able to move to the right and down, there are exactly 6 routes to the bottom right corner. How many such routes are there through a 20×20 grid? p_015.gif This is a classic combinatorics problem. To get from the top left corner to the bottom right corner of an N*N grid, it involves making exactly N moves right and N moves down in some order. Because each individual down or right move is indistinguishable, there are exactly 2N choose N (binomial coefficient) ways of arranging these moves. """ return eulerlib.binomial(40, 20)
def problem203(): # Collect unique numbers in Pascal's triangle numbers = set(eulerlib.binomial(n, k) for n in range(51) for k in range(n + 1)) maximum = max(numbers) # Prepare list of squared primes primes = eulerlib.list_primes(eulerlib.sqrt(maximum)) primessquared = [p * p for p in primes] def is_squarefree(n): for p2 in primessquared: if p2 > n: break if n % p2 == 0: return False return True # Sum up the squarefree numbers ans = sum(n for n in numbers if is_squarefree(n)) return ans
def problem267(): # Heuristic sampling algorithm. # At level 1 we test {1/2}. At level 2 we test {1/4, 3/4}. # At level 3 we test {1/8, 3/8, 5/8, 7/8}. Et cetera. TRIALS = 1000 maxindex = -1 prevchangelevel = 1 level = 1 while level - prevchangelevel <= 8: scaler = 0.5**level for i in range(1, 1 << level, 2): index = calc_billionaire_probability(i * scaler, TRIALS) if index > maxindex: maxindex = index prevchangelevel = level level += 1 # Calculate the cumulative probability: binomialSum = sum (n choose k) for 0 <= k < maxIndex binomialsum = sum(eulerlib.binomial(TRIALS, i) for i in range(maxindex)) return round_to_decimal(fractions.Fraction(binomialsum, 1 << TRIALS), 12)
def problem493(): """ :return: """ num_colors = 7 balls_per_color = 10 num_picked = 20 decimals = 9 numerator = [0] def explore(remain, limit, history): if remain == 0: hist = list(history) while len(hist) < num_colors: hist.append(0) histogram = [0] * (balls_per_color + 1) for _ in hist: histogram[_] += 1 count = math.factorial(num_colors) for _ in histogram: count = divide_exactly(count, math.factorial(_)) for _ in hist: count *= eulerlib.binomial(balls_per_color, _) distinctcolors = len(history) numerator[0] += count * distinctcolors elif len(history) < num_colors: for i in range(min(limit, remain), 0, -1): history.append(i) explore(remain - i, i, history) history.pop() explore(num_picked, balls_per_color, []) denominator = eulerlib.binomial(num_colors * balls_per_color, num_picked) ans = fractions.Fraction(numerator[0], denominator) return float(format_fraction(ans, decimals))
def catalan(n): return eulerlib.binomial(n * 2, n) // (n + 1)
def test_binomial(input_n, input_k, expected_output): output = eulerlib.binomial(input_n, input_k) print(output) assert output == expected_output