-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
mippolito
committed
Feb 14, 2017
1 parent
19d3d95
commit 52cc360
Showing
11 changed files
with
408 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
import itertools | ||
import random | ||
from collections import deque | ||
|
||
H = True | ||
T = False | ||
HT = (H, T) | ||
|
||
|
||
def _to_letters(seq): | ||
return ''.join("H" if s else "T" for s in seq) | ||
|
||
|
||
def counter_seq(seq): | ||
""" | ||
Returns the counter-sequence for the given sequence | ||
""" | ||
assert len(seq) == 3 | ||
return not seq[1], seq[0], seq[1] | ||
|
||
|
||
def play_match(seqA, seqB): | ||
""" | ||
Plays a single match between two sequences. | ||
Returns the winner. | ||
""" | ||
seq = deque(maxlen=3) | ||
|
||
for _ in xrange(3): | ||
seq.append(random.choice(HT)) | ||
|
||
while True: | ||
lseq = tuple(seq) | ||
if seqA == lseq: return seqA | ||
if seqB == lseq: return seqB | ||
|
||
seq.append(random.choice(HT)) | ||
|
||
|
||
def evaluate_prob(seqA, seqB, N=10000): | ||
""" | ||
Plays N matches between the two sequencies returning the total amount of won rounds | ||
""" | ||
victories = {seqA: 0, seqB: 0} | ||
for _ in xrange(N): | ||
winner = play_match(seqA, seqB) | ||
victories[winner] += 1 | ||
|
||
return victories | ||
|
||
|
||
all_starts = itertools.product(HT, repeat=3) | ||
counters = {s: counter_seq(s) for s in all_starts} | ||
|
||
|
||
if __name__ == '__main__': | ||
|
||
N = int(1e6) | ||
for expected_loser, expected_winner in counters.iteritems(): | ||
|
||
victories = evaluate_prob(expected_loser, expected_winner, N) | ||
prob = float(victories[expected_winner]) / N | ||
|
||
print "{} lost to {} {}% of the time".format( | ||
_to_letters(expected_loser), | ||
_to_letters(expected_winner), | ||
prob * 100) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
""" | ||
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. | ||
Find the sum of all the multiples of 3 or 5 below 1000. | ||
Answer: | ||
233168 | ||
""" | ||
|
||
|
||
import itertools | ||
from utilities import lower_than | ||
|
||
|
||
LIMIT=1000 | ||
ANSWER=233168 | ||
|
||
|
||
def multiples(n): | ||
""" | ||
Yields all the multiples of n (to infinity) | ||
""" | ||
for i in itertools.count(start=1): | ||
yield i*n | ||
|
||
threes = itertools.takewhile(lower_than(LIMIT), multiples(3)) | ||
fives = itertools.takewhile(lower_than(LIMIT), multiples(5)) | ||
|
||
# It's important to have a set here as there are numbers that are divisible by both 3 and 5 | ||
# If you don't use a set these numbers are counted twice and the answer is not correct | ||
answer = sum(set(itertools.chain(threes, fives))) | ||
assert answer == ANSWER | ||
|
||
print answer | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
from utilities import lower_than | ||
from itertools import count, imap, takewhile | ||
|
||
from functools import lru_cache | ||
|
||
limit = 1e6 | ||
|
||
|
||
@lru_cache | ||
def collatz_len(n): | ||
|
||
if n == 1: | ||
return 1 | ||
else: | ||
return 1 + collatz_len((3*n + 1) if (n % 2) else (n / 2)) | ||
|
||
|
||
answer = max(imap(collatz_len, takewhile(lower_than(limit), count(start=1))), key=lambda t: t[1]) | ||
print(answer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
""" | ||
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: | ||
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... | ||
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. | ||
""" | ||
|
||
import itertools | ||
from utilities import lower_than, fibonacci | ||
|
||
|
||
LIMIT = 4e6 | ||
|
||
seq = itertools.takewhile(lower_than(LIMIT), fibonacci()) | ||
answer = sum(itertools.ifilter(lambda n: (n % 2) == 0, seq)) | ||
|
||
print answer | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. | ||
For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, | ||
which means that 28 is a perfect number. | ||
A number n is called deficient if the sum of its proper divisors is less than n | ||
and it is called abundant if this sum exceeds n. | ||
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written | ||
as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown | ||
that all integers greater than 28123 can be written as the sum of two abundant numbers. | ||
However, this upper limit cannot be reduced any further by analysis even though it is known | ||
that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit. | ||
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers. | ||
""" | ||
|
||
import utilities | ||
|
||
smallest_abn = 12 | ||
upper_limit = 28123 | ||
|
||
cache = {n: (n == smallest_abn) for n in xrange(smallest_abn + 1)} | ||
|
||
|
||
def is_abundant(n): | ||
try: | ||
return cache[n] | ||
except KeyError: | ||
retval = (sum(utilities.divisors(n, only_proper=True)) > n) | ||
cache[n] = retval | ||
return retval | ||
|
||
|
||
def is_sum_of_abundants(n): | ||
for a in xrange(smallest_abn, (n + 1)): | ||
if not is_abundant(a): | ||
continue | ||
elif is_abundant(n - a): | ||
return True | ||
else: | ||
return False | ||
|
||
|
||
if __name__ == '__main__': | ||
numbers = xrange(upper_limit + 1) | ||
print sum(n for n in numbers if not is_sum_of_abundants(n)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
from utilities import fibonacci | ||
|
||
n_digits = 1000 | ||
M = 10**(n_digits - 1) | ||
|
||
for i, f in enumerate(fibonacci()): | ||
if f >= M: | ||
break | ||
|
||
# The +1 is necessary because we index from 0, math starts from 1 | ||
print i + 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
The prime factors of 13195 are 5, 7, 13 and 29. | ||
What is the largest prime factor of the number 600851475143 ? | ||
""" | ||
|
||
import itertools | ||
import math | ||
|
||
from utilities import primes, lower_than | ||
|
||
number = 600851475143 | ||
limit = int(math.floor(math.sqrt(number))) | ||
|
||
answer = 1 | ||
for p in itertools.takewhile(lower_than(limit), primes()): | ||
if not number % p: | ||
answer = p | ||
|
||
print answer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
The number, 197, is called a circular prime because all rotations of the digits: | ||
197, 971, and 719, are themselves prime. | ||
There are thirteen such primes below 100: | ||
2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97. | ||
How many circular primes are there below one million? | ||
""" | ||
|
||
from collections import deque | ||
|
||
import utilities | ||
|
||
pc = utilities.PrimeCache() | ||
|
||
|
||
def rotate(s, n): | ||
d = deque(s) | ||
d.rotate(n) | ||
return ''.join(d) | ||
|
||
|
||
def rotations(s): | ||
for n in xrange(len(s)): | ||
yield rotate(s, n) | ||
|
||
|
||
def is_circular_prime(n): | ||
retval = all(pc.is_prime(int(r)) for r in rotations(str(n))) | ||
return retval | ||
|
||
|
||
if __name__ == '__main__': | ||
count = 0 | ||
for n in xrange(2, int(1e6)): | ||
if is_circular_prime(n): | ||
count += 1 | ||
print count |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
import itertools | ||
from utilities import primes | ||
|
||
|
||
N = int(1e4) | ||
answer = next(itertools.islice(primes(), N, N + 1)) | ||
|
||
print answer | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
from utilities import lower_than | ||
import itertools | ||
import math | ||
|
||
|
||
N = 1000 | ||
|
||
|
||
def is_perfect_square(n): | ||
s = math.sqrt(n) | ||
return s == int(s) | ||
|
||
|
||
def find_tuple(): | ||
|
||
for a in itertools.takewhile(lower_than(N-1), itertools.count(1)): | ||
for b in itertools.takewhile(lower_than(N-a), itertools.count(a+1)): | ||
c = math.sqrt(a*a + b*b) | ||
if a + b + c == N: | ||
return a, b, int(c) | ||
else: | ||
raise ArithmeticError("Not found!") | ||
|
||
|
||
a, b, c = find_tuple() | ||
|
||
assert a*a + b*b == c*c | ||
assert a + b + c == N | ||
|
||
print a, b, c | ||
print a * b * c | ||
|
Oops, something went wrong.