Skip to content

Commit ede96c1

Browse files
author
Albert Hu
authored
Merge pull request #21 from alberthu16/day27
Day 27: pascal's triangle
2 parents 3e135b2 + 3823071 commit ede96c1

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

day27/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
question of the day: https://codefights.com/challenge/szuSfd9RjD3jwKtwj
2+
3+
If we write out all the [binomial coefficients](https://en.wikipedia.org/wiki/Binomial_coefficient)
4+
`C(N, K)` for all `N ≤ 5`, here's what we'll get:
5+
6+
``` python
7+
N = 0: [1]
8+
N = 1: [1, 1]
9+
N = 2: [1, 2, 1]
10+
N = 3: [1, 3, 3, 1]
11+
N = 4: [1, 4, 6, 4, 1]
12+
N = 5: [1, 5, 10, 10, 5, 1]
13+
```
14+
15+
This set of lists is often referred to as [Pascal's Triangle](https://en.wikipedia.org/wiki/Pascal%27s_triangle).
16+
As we can see, 17 out of 21 numbers in it are not divisible by 5.
17+
18+
Given an integer num and a prime number, calculate the number of all the binomial coefficients for all i ≤ num that are not divisible by prime.
19+
20+
Example
21+
22+
For `num = 5` and `prime = 5`, the output should be
23+
24+
`countingBinomialCoefficient(num, prime) = 17`.
25+
26+
## Ideas
27+
28+
Brute force: Calculate Pascal's Triangle, row by row, and keep a counter on how many are
29+
not divisible by `prime`.
30+
31+
`O(n<sup>2</sup>)` runtime, `O(n)` space, where `n` is the number of binomial coefficients.
32+
33+
## Code
34+
35+
[Python](./countingBinomialCoefficient.py)
36+
37+
## Follow up
38+
39+
Too bad the brute force is too slow for calculations on like 10 million rows.
40+
Here's a trick: https://cjordan.github.io/2013/12/29/solving-project-euler-148/#fnref:3
41+
42+
FML math is hard
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
class BinomialCoefficient(object):
2+
def __init__(self):
3+
self.coefficients = {}
4+
self.notDivisible = {}
5+
6+
# returns the binomial expansion coefficient for TOTAL choose SUBGROUP
7+
# aka C(total, subgroup)
8+
def getBinomialCoefficient(self, total, subgroup):
9+
if (total, subgroup) in self.coefficients:
10+
return self.coefficients[(total, subgroup)]
11+
12+
if total == subgroup or subgroup == 0:
13+
self.coefficients[(total, subgroup)] = 1
14+
return 1
15+
16+
return self.getBinomialCoefficient(total-1, subgroup) + self.getBinomialCoefficient(total-1, subgroup-1)
17+
18+
# returns the number of coefficients in Pascal's triangle up to
19+
# the NUMth row of the triangle that are not divisible by PRIME
20+
def binomialCoefficientsNotDivisibleByPrime(self, num, prime):
21+
if num == 0:
22+
self.notDivisible[prime] = {0: 1}
23+
return 1
24+
25+
if prime in self.notDivisible and num in self.notDivisible[prime]:
26+
return self.notDivisible[prime][num]
27+
28+
notDivisibleThisRow = len([i for i in xrange(num+1) if self.getBinomialCoefficient(num, i) % prime != 0])
29+
30+
self.notDivisible[prime][num] = self.binomialCoefficientsNotDivisibleByPrime(num-1, prime) + notDivisibleThisRow
31+
return self.notDivisible[prime][num]
32+
33+
def testGetBinomialCoefficient(binomialCalculator):
34+
b = binomialCalculator
35+
36+
assert b.getBinomialCoefficient(0, 0) == 1
37+
38+
assert b.getBinomialCoefficient(1, 0) == 1
39+
assert b.getBinomialCoefficient(1, 1) == 1
40+
41+
assert b.getBinomialCoefficient(2, 0) == 1
42+
assert b.getBinomialCoefficient(2, 1) == 2
43+
assert b.getBinomialCoefficient(2, 2) == 1
44+
45+
assert b.getBinomialCoefficient(3, 0) == 1
46+
assert b.getBinomialCoefficient(3, 1) == 3
47+
assert b.getBinomialCoefficient(3, 2) == 3
48+
assert b.getBinomialCoefficient(3, 3) == 1
49+
50+
assert b.getBinomialCoefficient(4, 0) == 1
51+
assert b.getBinomialCoefficient(4, 1) == 4
52+
assert b.getBinomialCoefficient(4, 2) == 6
53+
assert b.getBinomialCoefficient(4, 3) == 4
54+
assert b.getBinomialCoefficient(4, 4) == 1
55+
56+
assert b.getBinomialCoefficient(5, 0) == 1
57+
assert b.getBinomialCoefficient(5, 1) == 5
58+
assert b.getBinomialCoefficient(5, 2) == 10
59+
assert b.getBinomialCoefficient(5, 3) == 10
60+
assert b.getBinomialCoefficient(5, 4) == 5
61+
assert b.getBinomialCoefficient(5, 5) == 1
62+
63+
def testCountBinomialCoefficientsNotDivisibleByPrime(binomialCalculator):
64+
b = binomialCalculator
65+
66+
# prime = 2
67+
assert b.binomialCoefficientsNotDivisibleByPrime(0, 2) == 1
68+
assert b.binomialCoefficientsNotDivisibleByPrime(1, 2) == 3
69+
assert b.binomialCoefficientsNotDivisibleByPrime(2, 2) == 5
70+
assert b.binomialCoefficientsNotDivisibleByPrime(3, 2) == 9
71+
assert b.binomialCoefficientsNotDivisibleByPrime(4, 2) == 11
72+
assert b.binomialCoefficientsNotDivisibleByPrime(5, 2) == 15
73+
74+
# prime = 5
75+
assert b.binomialCoefficientsNotDivisibleByPrime(0, 5) == 1
76+
assert b.binomialCoefficientsNotDivisibleByPrime(1, 5) == 3
77+
assert b.binomialCoefficientsNotDivisibleByPrime(2, 5) == 6
78+
assert b.binomialCoefficientsNotDivisibleByPrime(3, 5) == 10
79+
assert b.binomialCoefficientsNotDivisibleByPrime(4, 5) == 15
80+
assert b.binomialCoefficientsNotDivisibleByPrime(5, 5) == 17
81+
assert b.binomialCoefficientsNotDivisibleByPrime(6, 5) == 21
82+
83+
# prime = 7
84+
assert b.binomialCoefficientsNotDivisibleByPrime(5, 7) == 21
85+
86+
# BIG DATA
87+
# assert b.binomialCoefficientsNotDivisibleByPrime(999999999, 7) == 2129970655314432
88+
# assert b.binomialCoefficientsNotDivisibleByPrime(879799878, 17) == 6026990181372288
89+
# assert b.binomialCoefficientsNotDivisibleByPrime(879799878, 19) == 8480245105257600
90+
91+
def main():
92+
b = BinomialCoefficient()
93+
testGetBinomialCoefficient(b)
94+
testCountBinomialCoefficientsNotDivisibleByPrime(b)
95+
96+
if __name__ == "__main__":
97+
main()

0 commit comments

Comments
 (0)