├── .gitignore ├── 016.py ├── 001.py ├── 029.py ├── 010.py ├── 003.py ├── 020.py ├── 006.py ├── 056.py ├── 007.py ├── 072.py ├── 019.py ├── 097.py ├── 009.py ├── 002.py ├── 040.py ├── 178.py ├── 004.py ├── 048.py ├── README ├── 014.py ├── 099.py ├── 025.py ├── 078.py ├── 015.py ├── 022.py ├── 062.py ├── 038.py ├── 033.py ├── 055.py ├── 021.py ├── 044.py ├── 039.py ├── 091.py ├── 042.py ├── keylog.txt ├── 047.py ├── 023.py ├── 030.py ├── 206.py ├── 057.py ├── 079.py ├── 041.py ├── 045.py ├── 037.py ├── 052.py ├── 046.py ├── 087.py ├── 031.py ├── 032.py ├── 050.py ├── 035.py ├── 069.py ├── 063.py ├── 059.py ├── 005.py ├── 064.py ├── 107.py ├── 081.py ├── 049.py ├── 065.py ├── 012.py ├── 067.py ├── 034.py ├── 205.py ├── 053.py ├── 018.py ├── 017.py ├── 024.py ├── 086.py ├── 027.py ├── 008.py ├── 076.py ├── Test ├── dijkstra83.py ├── anop83.py ├── efficient83.py ├── prim.py ├── improvedprim.py ├── dijkstra.py └── network.txt ├── 073.py ├── 083.py ├── 082.py ├── 090.py ├── 028.py ├── 075.py ├── 085.py ├── 096.py ├── 080.py ├── 093.py ├── utils.py ├── 061.py ├── 068.py ├── 026.py ├── 100.py ├── 095.py ├── 043.py ├── 094.py ├── 066.py ├── 104.py ├── 011.py ├── 058.py ├── 074.py ├── 092.py ├── 098.py ├── cipher1.txt ├── 089.py ├── lazy.py ├── graph.py ├── 071.py ├── 054.py ├── 036.py ├── 102.py ├── network.txt ├── 145.py ├── 013.py ├── log.log ├── sudoku.txt ├── euler.py ├── triangle.txt └── words.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /016.py: -------------------------------------------------------------------------------- 1 | print sum(map(int, str(2**1000))) 2 | -------------------------------------------------------------------------------- /001.py: -------------------------------------------------------------------------------- 1 | print sum(x for x in range(1000) if x % 3 == 0 or x % 5 ==0) 2 | -------------------------------------------------------------------------------- /029.py: -------------------------------------------------------------------------------- 1 | print len(set(a**b for a in range(2,101) for b in range(2,101))) 2 | -------------------------------------------------------------------------------- /010.py: -------------------------------------------------------------------------------- 1 | from euler import primesieve 2 | 3 | print sum(primesieve(2*10**6)) 4 | -------------------------------------------------------------------------------- /003.py: -------------------------------------------------------------------------------- 1 | from euler import primefactors 2 | print max(primefactors(600851475143)) 3 | -------------------------------------------------------------------------------- /020.py: -------------------------------------------------------------------------------- 1 | from euler import factorial 2 | print sum(map(int, str(factorial[100]))) 3 | -------------------------------------------------------------------------------- /006.py: -------------------------------------------------------------------------------- 1 | print abs(sum(x**2 for x in range(1,101)) - (sum(x for x in range(1,101))**2)) 2 | -------------------------------------------------------------------------------- /056.py: -------------------------------------------------------------------------------- 1 | print max(sum(map(int, str(a**b))) for a in range(1,100) for b in range(1,100)) 2 | -------------------------------------------------------------------------------- /007.py: -------------------------------------------------------------------------------- 1 | from euler import prime 2 | 3 | print prime[10000] # the 10001st's index is 10000 4 | -------------------------------------------------------------------------------- /072.py: -------------------------------------------------------------------------------- 1 | from euler import totient 2 | 3 | print sum(totient(d) for d in xrange(2, 1000000+1)) 4 | -------------------------------------------------------------------------------- /019.py: -------------------------------------------------------------------------------- 1 | from calendar import weekday as wday 2 | print sum(1 for y in range(1901,2001) for m in range(1,13) if wday(y,m,1) == 6) 3 | -------------------------------------------------------------------------------- /097.py: -------------------------------------------------------------------------------- 1 | print (28433*(2<<(7830457-1)) + 1) % 10**10 2 | 3 | # this is much faster 4 | print str(pow(2,7830457,10**10) * 28433 + 1)[-10:] 5 | -------------------------------------------------------------------------------- /009.py: -------------------------------------------------------------------------------- 1 | from euler import pythagorean 2 | 3 | for a,b,c in pythagorean(1000): 4 | if a+b+c==1000: 5 | print a*b*c 6 | break 7 | -------------------------------------------------------------------------------- /002.py: -------------------------------------------------------------------------------- 1 | from itertools import takewhile 2 | from euler import fibonacci 3 | print sum(e for e in (takewhile(lambda x: x<4*10**6, fibonacci)) if e%2==0) 4 | -------------------------------------------------------------------------------- /040.py: -------------------------------------------------------------------------------- 1 | from euler import product 2 | 3 | s = '.' + ''.join((str(x) for x in range(1,10**6))) 4 | print product(int(s[10**d]) for d in range(7)) 5 | -------------------------------------------------------------------------------- /178.py: -------------------------------------------------------------------------------- 1 | def ispandigital(n): 2 | return set(str(n)) == set('01234556789') 3 | 4 | def isstep(n): 5 | l = map(int, str(n)) 6 | print l 7 | 8 | isstep(45656) 9 | -------------------------------------------------------------------------------- /004.py: -------------------------------------------------------------------------------- 1 | from euler import ispalindromic 2 | 3 | print max(i*j 4 | for i in range(100,1000) 5 | for j in range(100,1000) 6 | if ispalindromic(str(i*j))) 7 | -------------------------------------------------------------------------------- /048.py: -------------------------------------------------------------------------------- 1 | #print str(sum(x**x for x in range(1,1001)))[-10:] 2 | #print sum(x**x for x in range(1,1001)) % 10**10 3 | L = 10**10 4 | print sum(pow(x,x,L) for x in range(1,1001)) % L 5 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Project Euler 2 | ======================= 3 | Author: Riobard 4 | Email: me@riobard.com 5 | 6 | My solutions to Project Euler (http://projecteuler.net) in Python (http://python.org) 7 | -------------------------------------------------------------------------------- /014.py: -------------------------------------------------------------------------------- 1 | d = {1: 1} 2 | def nterms(n): 3 | return d[n] if n in d else d.setdefault(n, 4 | 1 + (nterms(3*n+1) if n%2 else nterms(n/2))) 5 | 6 | print max((nterms(n),n) for n in range(2,10**6))[1] 7 | -------------------------------------------------------------------------------- /099.py: -------------------------------------------------------------------------------- 1 | from math import log as ln 2 | lines = open('base_exp.txt').read().split() 3 | print max(zip(range(1,len(lines)+1), 4 | map(lambda x: map(int, x.split(',')), lines)), 5 | key=lambda x: x[1][1]*ln(x[1][0])) 6 | -------------------------------------------------------------------------------- /025.py: -------------------------------------------------------------------------------- 1 | from euler import fibonacci 2 | from itertools import count, izip, takewhile 3 | 4 | print max(izip(count(), (takewhile(lambda x:x<10**999, fibonacci))))[0] + 1 5 | # the fibonacci sequence in this problem starts from 1 instead of 0, so +1 6 | -------------------------------------------------------------------------------- /078.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This problem is a variant of P0076 3 | 4 | ''' 5 | 6 | from euler import partition as p 7 | 8 | 9 | n = 0 10 | while True: 11 | n += 1 12 | pn = p(n) 13 | 14 | if pn%1000000==0: 15 | break 16 | 17 | print n, pn 18 | -------------------------------------------------------------------------------- /015.py: -------------------------------------------------------------------------------- 1 | from euler import memoized 2 | 3 | # note there is a simple formula. read Pascal's triangle for more 4 | 5 | @memoized 6 | def a(x, y): 7 | if (x==0 or y==0): 8 | return 1 9 | else: 10 | return a(x-1, y) + a(x, y-1) 11 | 12 | print a(20, 20) 13 | -------------------------------------------------------------------------------- /022.py: -------------------------------------------------------------------------------- 1 | names = open('names.txt').read().replace('"','').split(',') 2 | names.sort() 3 | print sum(sum(map(lambda c: ord(c)-64, names[i]))*(i+1) 4 | for i in range(len(names))) 5 | print sum(sum(ord(c)-64 for c in names[i])*(i+1) 6 | for i in range(len(names))) 7 | -------------------------------------------------------------------------------- /062.py: -------------------------------------------------------------------------------- 1 | from itertools import count 2 | 3 | 4 | def P062(): 5 | d = {} 6 | for n in count(0): 7 | s = ''.join(sorted(str(n**3))) 8 | l = d.get(s, []) + [n] 9 | d[s] = l 10 | if len(l) == 5: 11 | break 12 | 13 | return min(l)**3 14 | 15 | 16 | print P062() 17 | -------------------------------------------------------------------------------- /038.py: -------------------------------------------------------------------------------- 1 | # The number must be of the form 2 | # ABCD.EFGHI where ABCD * 2 = EFGHI 3 | 4 | from euler import permutate 5 | 6 | for permu in sorted(permutate('987654321'), reverse=True): 7 | i1, i2 = map(lambda x: int(''.join(x)), [permu[:4], permu[4:]]) 8 | if i1*2 == i2: 9 | print int(''.join(permu)) 10 | break 11 | -------------------------------------------------------------------------------- /033.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Form: 3 | 4 | ab/bc = a/c 5 | 6 | where 7 | a = [1-9], b = [1-9], c = [0-9] 8 | ab < bc 9 | ab * c = bc * a 10 | 11 | ''' 12 | for a in range(1, 10): 13 | for b in range(1,10): 14 | for c in range(10): 15 | if 10*a+b<10*b+c and (10*a+b)*c==(10*b+c)*a: 16 | print '%d%d/%d%d = %d/%d' % (a, b, b, c, a, c) 17 | -------------------------------------------------------------------------------- /055.py: -------------------------------------------------------------------------------- 1 | from euler import ispalindromic 2 | 3 | 4 | def islychrel(n): 5 | 6 | for _ in range(50): 7 | nr = int(''.join(reversed(str(n)))) 8 | s = n + nr 9 | if ispalindromic(str(s)): 10 | return False 11 | else: 12 | n = s 13 | 14 | return True 15 | 16 | 17 | print len([n for n in range(10000) if islychrel(n)]) 18 | -------------------------------------------------------------------------------- /021.py: -------------------------------------------------------------------------------- 1 | from euler import properdivisors 2 | 3 | def d(n): 4 | #return sum(x for x in range(1, n//2 + 1) if not (n % x)) 5 | return sum(properdivisors(n)) 6 | 7 | 8 | s = set() 9 | for i in range(1,10000): 10 | m = d(i) 11 | n = d(m) 12 | if (i == n) and (m != n): 13 | s.add(m) 14 | s.add(n) 15 | 16 | print s 17 | print sum(s) 18 | -------------------------------------------------------------------------------- /044.py: -------------------------------------------------------------------------------- 1 | 2 | def find(): 3 | ps = set() 4 | d = {} 5 | n = 0 6 | while True: 7 | n += 1 8 | p = n*(3*n-1)/2 9 | if p in d: 10 | return d[p] 11 | 12 | for each in ps: 13 | diff = p - each 14 | if diff in ps: 15 | d[p + each] = diff 16 | 17 | ps.add(p) 18 | 19 | 20 | print find() 21 | -------------------------------------------------------------------------------- /039.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | d = defaultdict(int) # d[key] default to 0 when first accessed 4 | for a in range(1,500): 5 | for b in range(a,500): 6 | c = (a**2+b**2)**.5 7 | ci = int(c) 8 | if c == ci: 9 | p = a+b+ci 10 | if p < 1000: 11 | d[p] += 1 12 | 13 | print max((d[k],k) for k in d) 14 | -------------------------------------------------------------------------------- /091.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | def is_right_triangle(x0, y0, x1, y1, x2, y2): 6 | a2 = (x1-x0)**2 + (y1-y0)**2 7 | b2 = (x2-x0)**2 + (y2-y0)**2 8 | c2 = (x2-x1)**2 + (y2-y1)**2 9 | return (a2>0 and b2>0 and c2>0) and (a2+b2==c2 or a2+c2==b2 or b2+c2==a2) 10 | 11 | 12 | M = 50+1 13 | 14 | print sum(is_right_triangle(0, 0, x1, y1, x2, y2) 15 | for x1 in range(M) for y1 in range(M) 16 | for x2 in range(M) for y2 in range(M)) // 2 17 | 18 | -------------------------------------------------------------------------------- /042.py: -------------------------------------------------------------------------------- 1 | words = open('words.txt').read().replace('"','').split(',') 2 | 3 | def istriangle(n): 4 | i = int((n*2) ** .5) 5 | return i*(i+1)/2 == n 6 | 7 | def istriangleword(w): 8 | return istriangle(sum(ord(c)-64 for c in w)) 9 | 10 | print len([w for w in words if istriangleword(w)]) 11 | 12 | print sum(1 for w 13 | in open('words.txt').read().replace('"','').split(',') 14 | if istriangle(sum(ord(c)-64 for c in w))) 15 | -------------------------------------------------------------------------------- /keylog.txt: -------------------------------------------------------------------------------- 1 | 319 2 | 680 3 | 180 4 | 690 5 | 129 6 | 620 7 | 762 8 | 689 9 | 762 10 | 318 11 | 368 12 | 710 13 | 720 14 | 710 15 | 629 16 | 168 17 | 160 18 | 689 19 | 716 20 | 731 21 | 736 22 | 729 23 | 316 24 | 729 25 | 729 26 | 710 27 | 769 28 | 290 29 | 719 30 | 680 31 | 318 32 | 389 33 | 162 34 | 289 35 | 162 36 | 718 37 | 729 38 | 319 39 | 790 40 | 680 41 | 890 42 | 362 43 | 319 44 | 760 45 | 316 46 | 729 47 | 380 48 | 319 49 | 728 50 | 716 51 | -------------------------------------------------------------------------------- /047.py: -------------------------------------------------------------------------------- 1 | from euler import primefactors, upf 2 | 3 | 4 | def find(): 5 | n = 1 6 | while True: 7 | n += 1 8 | 9 | if all(4==len(set(primefactors(n+i))) for i in range(4)): 10 | print n 11 | break 12 | 13 | 14 | def find2(): 15 | n=1 16 | t=0 17 | while True: 18 | if len((upf(n)))==4: 19 | t+=1 20 | if t==4: 21 | print n-3 22 | break 23 | else: t=0 24 | n+=1 25 | 26 | 27 | find2() 28 | -------------------------------------------------------------------------------- /023.py: -------------------------------------------------------------------------------- 1 | from euler import properdivisors 2 | 3 | 4 | def isabundant(n): 5 | return sum(properdivisors(n)) > n 6 | 7 | 8 | abundants = [n for n in range(1,28123) if isabundant(n)] 9 | 10 | sumofabundants = set() 11 | 12 | for i in range(len(abundants)): 13 | ai = abundants[i] 14 | for j in range(i+1): 15 | aj = abundants[j] 16 | s = ai + aj 17 | sumofabundants.add(s) 18 | if s > 28123: 19 | break 20 | 21 | print sum(set(n for n in range(28123)) - sumofabundants) 22 | -------------------------------------------------------------------------------- /030.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This problem is similar to 34. 3 | 4 | If n contains d digits and n is the sum of fifth powers of its digits, it must 5 | hold true that 6 | 10**(d-1) <= n <= d * (9**5) 7 | 8 | 10**(d-1) grows exponentially and d * (9**5) grows linearly. The above holds 9 | true only when d <= 6. Thus the upper bound to test is 6 * (9**5) 10 | ''' 11 | 12 | # start from 10 to avoid single digits number 13 | print sum(i for i in range(10, 6*(9**5)) 14 | if i == sum(x**5 for x in map(int, str(i)))) 15 | 16 | -------------------------------------------------------------------------------- /206.py: -------------------------------------------------------------------------------- 1 | MIN = 10203040506070809 ** .5 # ~= 101010101 2 | MAX = int(19293949596979899 ** .5)+1 3 | 4 | 5 | i = 1010100 6 | while i < MAX: 7 | i += 3 # numbers end in 3 8 | s = str(i*i) 9 | if s[::2] == '123456789': 10 | print i * 10 11 | break 12 | 13 | i += 4 # numbers end in 7 14 | s = str(i*i) 15 | if s[::2] == '123456789': 16 | print i * 10 17 | break 18 | 19 | i += 3 # end in 0 so next loop works the same 20 | -------------------------------------------------------------------------------- /057.py: -------------------------------------------------------------------------------- 1 | ''' 2 | http://en.wikipedia.org/wiki/Continued_fraction 3 | ''' 4 | 5 | def h(): 6 | a = 3 7 | b = 7 8 | while True: 9 | yield a 10 | a, b = b, 2*b + a 11 | 12 | 13 | def k(): 14 | a = 2 15 | b = 5 16 | while True: 17 | yield a 18 | a, b = b, 2*b + a 19 | 20 | 21 | from itertools import izip 22 | 23 | cnt = 0 24 | i = 0 25 | for (x, y) in izip(h(), k()): 26 | if i == 1000: break 27 | i += 1 28 | if len(str(x)) > len(str(y)): cnt += 1 29 | 30 | print cnt 31 | -------------------------------------------------------------------------------- /079.py: -------------------------------------------------------------------------------- 1 | keys = open('keylog.txt').read().split() 2 | passcode= list(set(''.join(keys))) 3 | 4 | def swap(passcode, key): 5 | ''' 6 | Produced a rearranged passcode according to key 7 | ''' 8 | x,y,z = key 9 | a,b,c = sorted([passcode.index(k) for k in key]) 10 | passcode[a] = x 11 | passcode[b] = y 12 | passcode[c] = z 13 | return passcode 14 | 15 | 16 | for key in keys: 17 | # repeat rearranging to get the correct passcode 18 | passcode = swap(passcode, key) 19 | print ''.join(passcode) 20 | -------------------------------------------------------------------------------- /041.py: -------------------------------------------------------------------------------- 1 | 2 | ''' 3 | 9-digit pandigitals are not prime, as 1+2+3+4+5+6+7+8+9=45 is divided by 3 4 | 8-digit pandigitals are not prime, as 1+2+3+4+5+6+7+8=36 is divided by 3 5 | so check from 7-digit pandigitals 6 | ''' 7 | 8 | from euler import isprime, permutate 9 | 10 | digits = range(7,0,-1) 11 | for d in digits: 12 | for p in permutate(range(d,0,-1)): # permutate in desc order 13 | n = int(''.join(map(str,p))) 14 | #n = sum(p[i]*(10**i) for i in range(len(p))) 15 | if isprime(n): 16 | print n 17 | break 18 | -------------------------------------------------------------------------------- /045.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | def tri(n): 4 | return n*(n+1)/2 5 | 6 | def istri(n): 7 | i = int((n*2) ** .5) 8 | return i*(i+1)/2 == n 9 | 10 | def pen(n): 11 | return n*(3*n-1)/2 12 | 13 | def ispen(n): 14 | i = int(2/3 + (4/9 + 2*n/3)**.5) 15 | return n==i*(3*i-1)/2 16 | 17 | def hex(n): 18 | return n*(2*n-1) 19 | 20 | i = 143 21 | while 1: 22 | i += 1 23 | h = hex(i) 24 | if istri(h) and ispen(h): # in fact all Hex numbers are Tri numbers 25 | print h 26 | break 27 | -------------------------------------------------------------------------------- /037.py: -------------------------------------------------------------------------------- 1 | # http://en.wikipedia.org/wiki/Truncatable_prime 2 | # only 4260 left-truncatable primes and 83 right-tructable primes 3 | # find the intersection 4 | 5 | # two-sided (double trunctable) primes (excluding 2, 3, 5, 7) must be of the form 6 | # [2357][1379]*[37] 7 | 8 | # 2-digit: [2357][37] 9 | # 23, 37, 53, 73 10 | 11 | # 3-digit: [2357][1379][37] 12 | # 313, 317, 373, 797 13 | 14 | # 4-digit: [2357][1379][1379][37] 15 | # 3137, 3797 16 | 17 | # 6-digit: [2357][1379][1379][1379][1379][37] 18 | # 739397 19 | 20 | 21 | print sum([23, 37, 53, 73, 313, 317, 373, 797, 3137, 3797, 739397]) 22 | -------------------------------------------------------------------------------- /052.py: -------------------------------------------------------------------------------- 1 | ''' 2 | After bruteforce: 3 | 4 | For this problem I didn't even use a computer. I just remembered that the repeating sequence of digits in the decimal representation of 1/7 has the desired property. 5 | 6 | 1/7 = 0.142857 142857 142857 ... 7 | 8 | 2 * 142857 = 285714 9 | 3 * 142857 = 428571 10 | 4 * 142857 = 571428 11 | 5 * 142857 = 714285 12 | 6 * 142857 = 857142 13 | but 14 | 7 * 142857 = 999999 15 | ''' 16 | 17 | i = 0 18 | while True: 19 | i += 1 20 | if set(str(i))==set(str(2*i))==set(str(3*i))==set(str(4*i))==set(str(5*i))==set(str(6*i)): 21 | print i 22 | break 23 | -------------------------------------------------------------------------------- /046.py: -------------------------------------------------------------------------------- 1 | from euler import prime, isprime 2 | 3 | c = 1 4 | while True: 5 | c += 2 6 | thisisit = True # assume c is the target 7 | if not isprime(c): 8 | for p in prime: 9 | if p == 2: 10 | continue 11 | 12 | if p < c: 13 | a = int(((c - p) / 2)**.5) 14 | if c == p + 2 * a * a: 15 | thisisit = False # c is not 16 | #print '%d == %d + 2 * %d * %d' % (c, p, a, a) 17 | break 18 | else: 19 | break 20 | 21 | if thisisit: 22 | print c 23 | break 24 | -------------------------------------------------------------------------------- /087.py: -------------------------------------------------------------------------------- 1 | from euler import prime 2 | from itertools import takewhile 3 | 4 | 5 | def run(): 6 | MAX = 50000000 7 | 8 | p = list(takewhile(lambda n: n <= MAX**.5, prime)) 9 | p2 = [n**2 for n in p] 10 | p3 = [n**3 for n in p] 11 | p4 = [n**4 for n in p] 12 | 13 | s = set() 14 | for a2 in p2: 15 | if a2 > MAX: break 16 | for b3 in p3: 17 | if a2 + b3 > MAX: break 18 | for c4 in p4: 19 | if a2 + b3 + c4 > MAX: break 20 | s.add(a2+b3+c4) # remove duplicates in a set 21 | 22 | return len(s) 23 | 24 | 25 | rs = run() 26 | print rs 27 | assert 1097343 == rs 28 | 29 | -------------------------------------------------------------------------------- /031.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 5 2 1 3 | ------------- 4 | 10 2 0 0 5 | 10 1 2 1 6 | 10 1 1 3 7 | 10 1 0 5 8 | 10 0 5 0 9 | 10 0 4 2 10 | 10 0 3 4 11 | 10 0 2 6 12 | 10 0 1 8 13 | 10 0 0 10 14 | -------------- 15 | ''' 16 | 17 | 18 | def f(n, us): 19 | ''' 20 | Recursively generate all possible combinations of coins 21 | 22 | us must in desc order and the last element must be 1 23 | ''' 24 | u, us = us[0], us[1:] 25 | return [[n]] if u == 1 else [[i] + j 26 | for i in range(n//u, -1, -1) for j in f(n - i*u, us)] 27 | 28 | 29 | print len(f(200, [200,100,50,20,10,5,2,1])) 30 | -------------------------------------------------------------------------------- /032.py: -------------------------------------------------------------------------------- 1 | # only two forms of permutations are possible 2 | # ABC x DE = FGHI 3 | # ABCD x E = FGHI 4 | 5 | 6 | from euler import permutate 7 | 8 | rs = set() 9 | for permu in permutate('123456789'): 10 | 11 | m1, m2, prod = int(''.join(permu[:3])), int(''.join(permu[3:5])), int(''.join(permu[5:])) 12 | 13 | if m1 * m2 == prod: 14 | print m1, 'x', m2, '=', prod 15 | rs.add(prod) 16 | 17 | 18 | m1, m2, prod = int(''.join(permu[:4])), int(''.join(permu[4:5])), int(''.join(permu[5:])) 19 | if m1 * m2 == prod: 20 | print m1, 'x', m2, '=', prod 21 | rs.add(prod) 22 | 23 | 24 | print 'All products:', rs 25 | print 'Sum:', sum(rs) 26 | -------------------------------------------------------------------------------- /050.py: -------------------------------------------------------------------------------- 1 | from euler import primesieve 2 | 3 | MAX = 1000000 4 | p1m = primesieve(MAX) 5 | p1ms= set(p1m) 6 | l = len(p1m) 7 | 8 | def maxchainlen(MAX): 9 | # longest chain of consequtive primes that sums < MAX 10 | s = 0 11 | for i in range(l): 12 | s += p1m[i] 13 | if not s < MAX: 14 | return i 15 | 16 | 17 | def find(): 18 | mcl = maxchainlen(MAX) 19 | for chainlen in range(mcl, 0, -1): 20 | for i in range(l-chainlen): 21 | s = sum(p1m[i:i+chainlen]) 22 | 23 | if s >= MAX: 24 | break 25 | 26 | if s in p1ms: 27 | return s 28 | 29 | 30 | print find() 31 | -------------------------------------------------------------------------------- /035.py: -------------------------------------------------------------------------------- 1 | from euler import primesieve 2 | 3 | def circular(n): 4 | ''' 5 | Return a list of n rotation 6 | ''' 7 | s = str(n) 8 | return [int(s[i:] + s[:i]) for i in range(len(s))] 9 | 10 | def f(n): 11 | # filter out all primes > 10 and containing 024568 12 | if n < 10: 13 | return True 14 | 15 | s = str(n) 16 | for each in '024568': 17 | if each in s: 18 | return False 19 | else: 20 | return True 21 | 22 | 23 | def iscircularprime(n): 24 | return all(each in primes for each in circular(n)) 25 | 26 | primes = [x for x in primesieve(10**6) if f(x)] 27 | print sum(iscircularprime(x) for x in primes) 28 | -------------------------------------------------------------------------------- /069.py: -------------------------------------------------------------------------------- 1 | from euler import prime 2 | 3 | 4 | ''' 5 | According to http://en.wikipedia.org/wiki/Euler's_totient_function 6 | 7 | phi(n) = n * product( (1 - 1/p) for distinct prime p dividing n) 8 | 9 | => n/phi(n) = product( (1 - 1/p) for distinct prime p dividing n) 10 | 11 | Since (1 - 1/p) < 1, to get the smaller n/phi(n), you just need as many 12 | distinct prime as possible, as long as the product(p) <= 10**6 13 | 14 | Hence it's trivial even on paper to find that: 15 | 16 | 2 x 3 x 5 x 7 x 11 x 13 x 17 = 510510 <= 10**6 17 | 18 | (the next number 510510 x 19 > 10**6) 19 | ''' 20 | 21 | 22 | n = 1 23 | for p in prime: 24 | t = n*p 25 | if t > 10**6: 26 | break 27 | else: 28 | n = n * p 29 | 30 | print n 31 | -------------------------------------------------------------------------------- /063.py: -------------------------------------------------------------------------------- 1 | ''' 2 | for all a >= 10, a^n will have at least n+1 digits 3 | 4 | only need to check for a from 1 to 9 5 | 6 | 7 | 8 | to calcuate the number of digits in an integer a**n 9 | 10 | len(a**n) = floor(log10(a**n)+1) 11 | 12 | we want len(a**n) == n, so 13 | 14 | log10(a**n) + 1 = n 15 | log10(a**n) = n - 1 16 | n * log10(a) = n - 1 17 | log10(a) = 1 - 1.0/n 18 | 19 | 20 | f(n) = 1 - 1.0/n increases as n grows 21 | find the maximum n s.t. 22 | log10(a) <= 1 - 1.0/n 23 | ''' 24 | 25 | from math import log10 26 | 27 | cnt = 0 28 | for a in range(1, 10): 29 | log10a = log10(a) 30 | n = 0 31 | while True: 32 | n += 1 33 | if (1 - 1.0/n) > log10a: 34 | cnt += n-1 35 | break 36 | 37 | print cnt 38 | -------------------------------------------------------------------------------- /059.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | from itertools import cycle 3 | 4 | msg = map(int, open('cipher1.txt').read().split(',')) 5 | cyc = len(msg) // 3 + 1 6 | common = set(ord(c) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ,abcdefghijklmnopqrstuvwxyz 0123456789.') 7 | lower = [ord(c) for c in 'abcdefghijklmnopqrstuvwxyz'] 8 | 9 | def guess(key): 10 | #rs = [m ^ k for m, k in zip(msg, key*cyc)] 11 | rs = [m ^ k for m, k in zip(msg, cycle(key))] 12 | return sum(c in common for c in rs) / len(rs) 13 | 14 | 15 | prob, key = max((guess([a,b,c]), [a,b,c]) 16 | for a in lower for b in lower for c in lower) 17 | 18 | decrypted = [m ^ k for m, k in zip(msg, cycle(key))] 19 | print ''.join(map(chr, decrypted)) 20 | print sum(decrypted) 21 | 22 | -------------------------------------------------------------------------------- /005.py: -------------------------------------------------------------------------------- 1 | ''' the idea is simple: factorize every number from 1 to 20, that is to 2 | reduece every number to its basic form (a unique form expessed using only 3 | prime numbers, due to the fact that every natural number has a unique form). 4 | and then find the maximum power of each prime element. 5 | 6 | 1*2*3*(2*2)*5*(2*3)*7*(2*2*2)*(3*3)*(2*5)*11*(2*2*3)*13*(2*7)*(3*5)*(2*2*2*2)*17*(2*3*3)*19*(2*2*5) 7 | 8 | 1*(2**4)*(3**2)*5*7*11*13*17*19 9 | ''' 10 | 11 | from euler import uniprimefact, product 12 | 13 | nums = range(1, 20) 14 | 15 | d = {} 16 | for i in nums: 17 | for (prime, power) in uniprimefact(i).items(): 18 | if (prime in d and d[prime] < power) or (prime not in d): 19 | d[prime] = power 20 | 21 | print product(prime**power for (prime, power) in d.items()) 22 | -------------------------------------------------------------------------------- /064.py: -------------------------------------------------------------------------------- 1 | ''' 2 | http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Continued_fraction_expansion 3 | 4 | Related to P065, P066 5 | ''' 6 | 7 | def CFE(s): 8 | ' Continued fraction expansion of sqrt(s) ' 9 | 10 | m = 0 11 | d = 1 12 | a0 = int(s**.5) 13 | a = a0 14 | 15 | encountered = set([(m, d, a)]) 16 | rs = [a0] 17 | 18 | while True: 19 | 20 | m = d * a - m 21 | d = (s - m**2) / d 22 | if d == 0: break # a perfect square 23 | a = int(a0 + m) // d 24 | 25 | if (m, d, a) in encountered: 26 | break 27 | else: 28 | rs += [a] 29 | encountered.add((m, d, a)) 30 | 31 | return rs 32 | 33 | 34 | print sum(1 for n in range(10000+1) if len(CFE(n)) > 1 and len(CFE(n)) % 2==0) 35 | -------------------------------------------------------------------------------- /107.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Minimum Spanning Tree with Prim's Algorithm 3 | ''' 4 | 5 | def buildmatrix(file): 6 | return [map(lambda s: None if s=='-' else int(s), line.strip().split(',')) 7 | for line in open(file)] 8 | 9 | def buildgraph(M): 10 | L = len(M) 11 | g = {} 12 | 13 | for i in range(L): 14 | neighbors = {} 15 | for j in range(L): 16 | if M[i][j] is not None: 17 | neighbors[j] = M[i][j] 18 | g[i] = neighbors 19 | 20 | return g 21 | 22 | m = buildmatrix('network.txt') 23 | total = sum(sum(each for each in line if each is not None) 24 | for line in m) // 2 # symmetric weight matrix (undirected graph) 25 | g = buildgraph(m) 26 | from euler import prim 27 | 28 | mst = prim(g) 29 | print total - sum(mst.values()) 30 | -------------------------------------------------------------------------------- /081.py: -------------------------------------------------------------------------------- 1 | ''' 2 | P0018, P0067, P0081, P0083 are variants of each other. 3 | 4 | Dynamic Programming 5 | 1) overlapping subproblems 6 | 2) optimal substructure 7 | 8 | Two approaches: 9 | 1) Top-down: memoization 10 | 2) Bottom-up: 11 | ''' 12 | 13 | mat = [[131, 673, 234, 103, 18], 14 | [201, 96, 342, 965, 150], 15 | [630, 803, 746, 422, 111], 16 | [537, 699, 497, 121, 956], 17 | [805, 732, 524, 37, 331]] 18 | 19 | mat = [map(int, line.strip().split(',')) for line in open('matrix.txt')] 20 | M = len(mat)-1 21 | 22 | from euler import memoized 23 | 24 | @memoized 25 | def f(i, j): 26 | if i==j==M: return mat[i][j] 27 | elif i==M: return mat[i][j] + f(i, j+1) 28 | elif j==M: return mat[i][j] + f(i+1, j) 29 | else: return mat[i][j] + min(f(i+1, j), f(i, j+1)) 30 | 31 | print f(0,0) 32 | -------------------------------------------------------------------------------- /049.py: -------------------------------------------------------------------------------- 1 | def triple(ls): 2 | ''' 3 | a special permutation 4 | 5 | ls = [a, b, c, d, e] # in asc order 6 | produce: 7 | abc abd abe acd ace ade 8 | bcd bce bde 9 | cde 10 | ''' 11 | for i in range(len(ls)): 12 | for j in range(i+1, len(ls)): 13 | for k in range(j+1, len(ls)): 14 | yield [ls[i], ls[j], ls[k]] 15 | 16 | from euler import primesieve, isarithmetic 17 | 18 | s = set(primesieve(10000)) - set(primesieve(1000)) 19 | d = {} 20 | for each in sorted(s): 21 | digits = tuple(sorted(map(int,str(each)))) 22 | if digits in d: 23 | d[digits].append(each) 24 | else: 25 | d[digits] = [each] 26 | 27 | for digits in sorted(d): 28 | if len(d[digits]) >= 3: 29 | for each in triple(d[digits]): 30 | if isarithmetic(each): 31 | print each 32 | -------------------------------------------------------------------------------- /065.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Variant of P057 3 | 4 | http://en.wikipedia.org/wiki/Continued_fraction 5 | 6 | e = [2; 1,2,1, 1,4,1, 1,6,1 , ... , 1,2k,1, ...] 7 | 8 | 9 | h_n = a_n * h_{n-1} + h_{n-2} 10 | 11 | k_n = a_n * k_{n-1} + k_{n-2} 12 | 13 | 14 | The first ten terms in the sequence of convergents for e are: 15 | 16 | (h_n/k_n) = 2/1, 3/1, 8/3, 11/4, 19/7, 87/32, 106/39, 193/71, 1264/465, 1457/536 17 | 18 | 19 | Related to P064, P066 20 | 21 | ''' 22 | 23 | from lazy import lazylist 24 | 25 | @lazylist 26 | def a(): 27 | yield 2 28 | 29 | k = 1 30 | while True: 31 | yield 1 32 | yield 2*k 33 | yield 1 34 | k += 1 35 | a = a() 36 | 37 | 38 | 39 | @lazylist 40 | def h(): 41 | m = 2 42 | n = 3 43 | k = 2 44 | while True: 45 | yield m 46 | m, n = n, a[k] * n + m, 47 | k += 1 48 | h = h() 49 | 50 | 51 | print sum(map(int, str(h[99]))) 52 | -------------------------------------------------------------------------------- /012.py: -------------------------------------------------------------------------------- 1 | # for more information about this problem, check 2 | # http://mathschallenge.net/index.php?section=faq&ref=number/number_of_divisors 3 | # 4 | # According to Fundamental Theorem of Arithmetic (or Unique Prime-Factorization 5 | # theorem) , 6 | # n can be uniquely represented by a^x * b^y * c^z, where a, b, c are primes 7 | # let d(n) = the number of divisors of n 8 | # then d(n) = (x+1) * (y+1) * (z+1) 9 | 10 | from euler import uniprimefact, product 11 | from itertools import count 12 | 13 | 14 | def trinum(n): 15 | ''' Return the n-th triangle number ''' 16 | return n*(n+1)/2 17 | 18 | def trinumgen(): 19 | ''' Generate the sequence of triangle numbers ''' 20 | for n in count(1): 21 | yield trinum(n) 22 | 23 | for trin in trinumgen(): 24 | if product(each + 1 for each in uniprimefact(trin).values()) > 500: 25 | print trin 26 | break 27 | -------------------------------------------------------------------------------- /067.py: -------------------------------------------------------------------------------- 1 | ''' 2 | P0018, P0067, P0081, P0082 are variants of each other. 3 | 4 | P0083 requires Graph Theory 5 | 6 | Dynamic Programming 7 | 1) overlapping subproblems 8 | 2) optimal substructure 9 | 10 | Two approaches: 11 | 1) Top-down: memoization 12 | 2) Bottom-up: 13 | ''' 14 | 15 | mat = '''\ 16 | 3 17 | 7 5 18 | 2 4 6 19 | 8 5 9 3\ 20 | ''' 21 | 22 | mat = open('triangle.txt').read().strip() 23 | 24 | mat = [map(int, line.split()) for line in mat.split('\n')] 25 | M = len(mat)-1 26 | 27 | from euler import deepcopied 28 | @deepcopied 29 | def solve(l): 30 | for i in range(2,len(l)+1): 31 | for j in range(0,len(l[-i])): 32 | l[-i][j] += max(l[-i+1][j:j+2]) 33 | return l[0][0] 34 | print solve(mat) 35 | 36 | from euler import memoized 37 | @memoized 38 | def f(i, j): 39 | if i==M: return mat[i][j] 40 | else: return mat[i][j] + max(f(i+1, j), f(i+1, j+1)) 41 | 42 | print f(0,0) 43 | -------------------------------------------------------------------------------- /034.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1 = 1! 3 | 2 = 2! 4 | 145 = 1! + 4! + 5! = 1 + 24 + 120 5 | 40585 = 4!+ 0! + 5! + 8! + 5! = 24 + 1 + 120 + 40320 6 | 7 | These four numbers are called ``factorion'', a natural number that equals the 8 | sum of the factorials of its decimal digits. These are the only four. 9 | 10 | To search for them, we need an upper bound. 11 | 12 | If n contains d digits, and it's a factorion, it must hold true that 13 | 10^(d-1) <= n <= d * 9! 14 | thus 15 | 10^(d-1) <= d*9! 16 | Note 10^(d-1) grows exponentially and d*9! grows linearly. when d >= 8, the 17 | above inequation no longer holds true. Thus d must <= 7. So the upper bound to 18 | check is 7*9! = 2540160. 19 | ''' 20 | 21 | from euler import factorial as f 22 | 23 | def factorion(): 24 | for i in range(7*f[9]): 25 | if i == sum(f[x] for x in map(int, str(i))): 26 | yield i 27 | 28 | factorions = list(factorion()) 29 | print factorions 30 | print sum(factorions) - 1 - 2 31 | -------------------------------------------------------------------------------- /205.py: -------------------------------------------------------------------------------- 1 | from itertools import product 2 | 3 | pyramidal = 4**9 4 | cubic = 6**6 5 | 6 | 7 | die4 = [1,2,3,4] 8 | die6 = [1,2,3,4,5,6] 9 | 10 | peter = [die4]*9 11 | colin = [die6]*6 12 | 13 | 14 | ev_peter = {} 15 | for each in product(*peter): 16 | total = sum(each) 17 | ev_peter[total] = ev_peter.get(total, 0) + 1 18 | 19 | # Frequency distribution of expected value for Peter 20 | evfd_peter = dict((ev, float(c) / pyramidal) for (ev, c) in ev_peter.items()) 21 | 22 | 23 | ev_colin = {} 24 | for each in product(*colin): 25 | total = sum(each) 26 | ev_colin[total] = ev_colin.get(total, 0) + 1 27 | 28 | # Frequency distribution of expected value for Colin 29 | evfd_colin = dict((ev, float(c) / cubic) for (ev, c) in ev_colin.items()) 30 | 31 | 32 | p = 0 33 | for ev_peter in evfd_peter: 34 | for ev_colin in range(6, ev_peter): 35 | p_peter = evfd_peter[ev_peter] 36 | p_colin = evfd_colin[ev_colin] 37 | p += p_peter * p_colin 38 | 39 | print '%.7f' % p 40 | -------------------------------------------------------------------------------- /053.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A much more efficient approach using Pascal Triangle 3 | 4 | C(n, r) results the Pascal Triangle 5 | 6 | 0: 1 7 | 1: 1 1 8 | 2: 1 2 1 9 | 3: 1 3 3 1 10 | 4: 1 4 6 4 1 11 | 5: 1 5 10 10 5 1 12 | 13 | with n (from 0) denoting row and r (from 1) denoting column. 14 | 15 | Each row of this triangle is symmetric and bell-curve shaped, so C(n, r) == 16 | C(n, n-r) and any C(n, x) for x between r and (n-r) is greater than C(n, r). 17 | 18 | Thus if C(n, r) > 10**6, we know that C(n, x) for x from r to (n-r) must also 19 | > 10**6. Total number of C(n, r) > 10**6 is (n-r)-r+1. So during looping we 20 | stop whenever C(N, r) > 10**6 is encountered and try next row. This will 21 | save the time needed to check all numbers in a given row. 22 | ''' 23 | 24 | from euler import combination as C 25 | 26 | total = 0 27 | for i in range(0,101): 28 | for j in range(i+1): 29 | if C(i,j) > 10**6: 30 | total += i-j-j+1 31 | break 32 | print total 33 | -------------------------------------------------------------------------------- /018.py: -------------------------------------------------------------------------------- 1 | ''' 2 | P0018, P0067, P0081, P0083 are variants of each other. 3 | 4 | Dynamic Programming 5 | 1) overlapping subproblems 6 | 2) optimal substructure 7 | 8 | Two approaches: 9 | 1) Top-down: memoization 10 | 2) Bottom-up: 11 | ''' 12 | 13 | mat = '''\ 14 | 3 15 | 7 5 16 | 2 4 6 17 | 8 5 9 3\ 18 | ''' 19 | 20 | mat = '''\ 21 | 75 22 | 95 64 23 | 17 47 82 24 | 18 35 87 10 25 | 20 04 82 47 65 26 | 19 01 23 75 03 34 27 | 88 02 77 73 07 63 67 28 | 99 65 04 28 06 16 70 92 29 | 41 41 26 56 83 40 80 70 33 30 | 41 48 72 33 47 32 37 16 94 29 31 | 53 71 44 65 25 43 91 52 97 51 14 32 | 70 11 33 28 77 73 17 78 39 68 17 57 33 | 91 71 52 38 17 14 91 43 58 50 27 29 48 34 | 63 66 04 68 89 53 67 30 73 16 69 87 40 31 35 | 04 62 98 27 23 09 70 98 73 93 38 53 60 04 23\ 36 | ''' 37 | 38 | mat = [map(int, line.split()) for line in mat.split('\n')] 39 | M = len(mat)-1 40 | 41 | from euler import memoized 42 | 43 | @memoized 44 | def f(i, j): 45 | if i==M: return mat[i][j] 46 | else: return mat[i][j] + max(f(i+1, j), f(i+1, j+1)) 47 | 48 | print f(0,0) 49 | -------------------------------------------------------------------------------- /017.py: -------------------------------------------------------------------------------- 1 | m = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 2 | 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 3 | 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', 4 | 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'] 5 | n = range(21) + range(30,91,10) 6 | d = dict(zip(n,m)) 7 | 8 | def num2word(n): 9 | if n in d: 10 | return d[n] 11 | elif n < 100: 12 | return '%s-%s' % (d[n // 10 * 10], d[n % 10]) 13 | elif n < 1000: 14 | n100, n = n // 100, n % 100 15 | if n > 20: 16 | n10, n = n // 10 * 10, n % 10 17 | return ('%s hundred' % d[n100]) + (' and %s' % d[n10] if n10 else '')\ 18 | + ('-%s' % d[n] if n else '') 19 | else: 20 | return ('%s hundred' % d[n100]) + (' and %s' % d[n] if n else '') 21 | 22 | elif n == 1000: 23 | return 'one thousand' 24 | else: 25 | raise 'Error' 26 | 27 | print sum(len(num2word(i).replace(' ', '').replace('-','')) 28 | for i in range(1,1001)) 29 | -------------------------------------------------------------------------------- /024.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This has something to do with factoradic, a factorial-based mixed radix 3 | numeral system 4 | 5 | clever way by euler: 6 | 7 | We know that there are n! permutations for n distinct digits and, as we're 8 | working in lexicographical order, after 9! permutations the ten digit string 9 | will have become: 0987654321. The 9!+1 permutation will be 1023456789, the 10 | 2*9!+1=725761 permutation will be 2013456789. However, the 3*9!+1 permutation 11 | (3012456789) will be greater than one million. So we now consider the 12 | permutations of the last nine digits, 013456789: 6*8!+1 will take it to 13 | 701345689. We have now computed 967681 permutations and arrived at the number 14 | 2701345689. Then we look at the last eight digits, and work out that a further 15 | 6*7!+1 takes it to the string 2780134569 and a total of 997921 permutations... 16 | 17 | This method converges quickly. 18 | ''' 19 | 20 | from euler import permutate as P, factorial as F 21 | 22 | d = '0123456789' 23 | n = 999999 # 0-based index of 1000000th permutation 24 | ls = '' 25 | for i in range(9, -1, -1): 26 | q, n= divmod(n, F[i]) 27 | print q,n,d 28 | ls += d[q] 29 | d = d[:q] + d[q+1:] 30 | 31 | print ls 32 | -------------------------------------------------------------------------------- /086.py: -------------------------------------------------------------------------------- 1 | def combo(xy, z): 2 | # xy = x + y 3 | # 1 <= x <= y <= z 4 | # ===> 5 | # 1 <= x 6 | # xy - z <= x 7 | # x <= xy//2 8 | # x <= z 9 | # ===> max(1, xy-z) <= x <= min(xy//2, z) 10 | 11 | lo = max(1, xy-z) 12 | hi = min(xy//2, z) 13 | 14 | return hi - lo + 1 if lo <= hi else 0 15 | 16 | 17 | def ncube(M): 18 | cnt = 0 19 | for z in xrange(1, M+1): 20 | for xy in xrange(2, 2*z + 1): 21 | xy2 = xy**2 22 | z2 = z**2 23 | k2 = xy2+z2 24 | k = int(k2**.5) 25 | if k**2 == k2: 26 | cnt += combo(xy, z) 27 | return cnt 28 | 29 | 30 | 31 | 32 | def bisearch(f, cond, lo, hi): 33 | ''' 34 | search a monotonously increasing function f for the first x s.t. 35 | cond(f(x)) is true and x is an integer and x >= 0 36 | ''' 37 | 38 | while hi-lo > 1: 39 | x = (lo + hi) // 2 40 | n = f(x) 41 | if cond(n): 42 | hi = x 43 | else: 44 | lo = x 45 | 46 | return hi 47 | 48 | 49 | 50 | def P086(): 51 | assert 2060 == ncube(100) 52 | print bisearch(ncube, lambda n: n>1000000, 100, 10000) 53 | 54 | 55 | P086() 56 | -------------------------------------------------------------------------------- /027.py: -------------------------------------------------------------------------------- 1 | from euler import primesieve 2 | 3 | ''' 4 | f(n) = n*n + a*n + b 5 | 6 | when n = 0, b must be a prime. And |b| < 1000, so b is one of the primes < 7 | 1000. 8 | ''' 9 | 10 | primes = set(primesieve(10**5)) 11 | def allprimes(n, a, b): 12 | ''' True if f(n, a, b) is prime for n in [0...n) ''' 13 | ls = [n*n + a*n + b for n in range(n)] 14 | largest = max(ls) 15 | 16 | if largest < 10**5: 17 | return all(l in primes for l in ls) 18 | else: 19 | raise Exception('Prime set not big enough. Max value %d' % largest) 20 | 21 | 22 | from itertools import * 23 | def mostprimes(a, b): 24 | ''' count how many primes for consecutive values of n ''' 25 | for n in count(): 26 | f = n*n + a*n + b 27 | if f not in primes: 28 | break 29 | return n 30 | 31 | prime1k = primesieve(1000) 32 | 33 | # filter a to those produce at least 40 primes 34 | als = [a for a in range(-999, 1000) for b in prime1k 35 | if allprimes(40, a, b)] 36 | 37 | # leaving only this number of combinations of (a, b) 38 | #print len(als) * len(prime1k) 39 | 40 | rs = max((mostprimes(a,b), a, b) for a in als for b in prime1k) 41 | print rs[1]*rs[2] 42 | -------------------------------------------------------------------------------- /008.py: -------------------------------------------------------------------------------- 1 | s = '''\ 2 | 73167176531330624919225119674426574742355349194934 3 | 96983520312774506326239578318016984801869478851843 4 | 85861560789112949495459501737958331952853208805511 5 | 12540698747158523863050715693290963295227443043557 6 | 66896648950445244523161731856403098711121722383113 7 | 62229893423380308135336276614282806444486645238749 8 | 30358907296290491560440772390713810515859307960866 9 | 70172427121883998797908792274921901699720888093776 10 | 65727333001053367881220235421809751254540594752243 11 | 52584907711670556013604839586446706324415722155397 12 | 53697817977846174064955149290862569321978468622482 13 | 83972241375657056057490261407972968652414535100474 14 | 82166370484403199890008895243450658541227588666881 15 | 16427171479924442928230863465674813919123162824586 16 | 17866458359124566529476545682848912883142607690042 17 | 24219022671055626321111109370544217506941658960408 18 | 07198403850962455444362981230987879927244284909188 19 | 84580156166097919133875499200524063689912560717606 20 | 05886116467109405077541002256983155200055935729725 21 | 71636269561882670428252483600823257530420752963450\ 22 | ''' 23 | 24 | l = map(int, s.replace('\n','')) 25 | print max(reduce(lambda x,y: x*y, l[i:i+5]) for i in range(1000-5)) 26 | -------------------------------------------------------------------------------- /076.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This problem is a variant of P0078 3 | 4 | 1 = 1 5 | 6 | 2 = 2 7 | = 1 + 1 8 | 9 | 3 = 3 10 | = 2 + 1 11 | = 1 + 1 + 1 12 | 13 | 4 = 4 14 | = 3 + 1 15 | = 2 + 2 16 | = 2 + 1 + 1 17 | = 1 + 1 + 1 + 1 18 | 19 | 5 = 5 20 | = 4 + 1 21 | = 3 + 2 22 | = 3 + 1 + 1 23 | = 2 + 2 + 1 24 | = 2 + 1 + 1 + 1 25 | = 1 + 1 + 1 + 1 + 1 26 | 27 | 6 = 6 28 | = 5 + 1 29 | = 4 + 2 30 | = 4 + 1 + 1 31 | = 3 + 3 32 | = 3 + 2 + 1 33 | = 3 + 1 + 1 + 1 34 | = 2 + 2 + 2 35 | = 2 + 2 + 1 + 1 36 | = 2 + 1 + 1 + 1 + 1 37 | = 1 + 1 + 1 + 1 + 1 + 1 38 | 39 | 7 = 7 40 | = 6 + 1 41 | = 5 + 2 42 | = 5 + 1 + 1 43 | = 4 + 3 44 | = 4 + 2 + 1 45 | = 4 + 1 + 1 + 1 46 | = 3 + 3 + 1 47 | = 3 + 2 + 2 48 | = 3 + 2 + 1 + 1 49 | = 3 + 1 + 1 + 1 + 1 50 | = 2 + 2 + 2 + 1 51 | = 2 + 2 + 1 + 1 + 1 52 | = 2 + 1 + 1 + 1 + 1 + 1 53 | = 1 + 1 + 1 + 1 + 1 + 1 + 1 54 | 55 | ''' 56 | 57 | 58 | from euler import partition as p 59 | 60 | 61 | assert 7 == p(5) 62 | assert 56 == p(11) 63 | assert 190569291 == p(100)-1 # excluding itself (1-partition) 64 | print p(100)-1 65 | -------------------------------------------------------------------------------- /Test/dijkstra83.py: -------------------------------------------------------------------------------- 1 | from time import clock 2 | t = clock() 3 | 4 | M = [map(int, line.strip().split(',')) for line in open('matrix.txt')] 5 | N=len(M)-1 6 | 7 | TM=[[10000*80 for a in range(N+1)] for a in range(N+1)] 8 | 9 | def sol_up(a,b): 10 | if b==N and a==N: 11 | TM[a][b]=0 12 | return 0 13 | r=0 14 | if a0: 25 | t=min(TM[a][b],M[a-1][b]+TM[a-1][b]) 26 | if TM[a][b]!=t: 27 | TM[a][b]=t 28 | r=1 29 | if b>0: 30 | t=min(TM[a][b],M[a][b-1]+TM[a][b-1]) 31 | if TM[a][b]!=t: 32 | TM[a][b]=t 33 | r=1 34 | return r 35 | 36 | def sol_(): 37 | r=0 38 | for b in range(N,-1,-1): 39 | for a in range(N,-1,-1): 40 | if sol_up(a,b): r+=1 41 | return r 42 | 43 | s=0 44 | z=1 45 | while z: 46 | z=sol_() 47 | #print z 48 | s+=1 49 | mi=TM[0][0]+M[0][0] 50 | print mi 51 | print clock()-t, 's', s 52 | -------------------------------------------------------------------------------- /073.py: -------------------------------------------------------------------------------- 1 | from euler import gcd 2 | 3 | def f(d): 4 | return sum(1 if 2*x < d < 3*x and gcd(x, d)==1 else 0 5 | for x in xrange(d//3, d//2+1)) 6 | 7 | print sum(f(d) for d in xrange(2, 12000+1)) 8 | 9 | 10 | 11 | 12 | 13 | ' another approach (slower and consume more memory) ' 14 | 15 | from collections import deque 16 | def CPP(M=None): 17 | ' Generate coprime pairs (m, n) with m <= M if M is given ' 18 | def branch(m, n, M=None): 19 | q = deque([(m, n)]) 20 | 21 | while len(q)>0: 22 | (m, n) = q.popleft() 23 | yield (m, n) 24 | 25 | if M is None: 26 | q.append((2*m-n, m)) 27 | q.append((2*m+n, m)) 28 | q.append((m+2*n, n)) 29 | else: 30 | if 2*m-n <= M: q.append((2*m-n, m)) 31 | if 2*m+n <= M: q.append((2*m+n, m)) 32 | if m+2*n <= M: q.append((m+2*n, n)) 33 | 34 | 35 | if M is None: 36 | for each in branch(2, 1): yield each 37 | for each in branch(3, 1): yield each 38 | else: 39 | for each in branch(2, 1, M): yield each 40 | for each in branch(3, 1, M): yield each 41 | 42 | 43 | def another_way(): 44 | print sum(1 if (2*n < m < 3*n) else 0 for (m, n) in CPP(12000)) 45 | 46 | -------------------------------------------------------------------------------- /Test/anop83.py: -------------------------------------------------------------------------------- 1 | 2 | xsize = 80 3 | ysize = 80 4 | 5 | orig_arr = [] 6 | for line in file("matrix.txt", "rb") : 7 | orig_line = [] 8 | for val in line.strip().split(",") : 9 | orig_line.append(int(val)) 10 | orig_arr.append(orig_line) 11 | 12 | calc_arr = [] 13 | for y in xrange(80) : 14 | calc_arr.append([99999999999999] * xsize) 15 | 16 | def array_insert(val, x, y) : 17 | l = 0 18 | r = len(walk_array) 19 | while l < r : 20 | m = (l+r) / 2 21 | if walk_array[m][0] > val : 22 | r = m 23 | else : 24 | l = m + 1 25 | walk_array.insert(l, (val, x, y)) 26 | 27 | def check_cell(x, y, val) : 28 | if x < 0 or x >= xsize or y < 0 or y >= ysize : 29 | return 30 | 31 | val += orig_arr[y][x] 32 | if calc_arr[y][x] > val : 33 | calc_arr[y][x] = val 34 | array_insert(val, x, y) 35 | 36 | calc_arr[0][0] = orig_arr[0][0] 37 | walk_array = [(0, 0, 0)] 38 | 39 | while len(walk_array) : 40 | (dummy, x, y) = walk_array[0] 41 | walk_array = walk_array[1:] 42 | 43 | val = calc_arr[y][x] 44 | check_cell(x+1, y, val) 45 | check_cell(x-1, y, val) 46 | check_cell(x, y+1, val) 47 | check_cell(x, y-1, val) 48 | 49 | print calc_arr[xsize-1][ysize-1] 50 | -------------------------------------------------------------------------------- /083.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Dijkstra's Shortest Path Algorithm 3 | ''' 4 | 5 | def buildgraph(M): 6 | g = {} # graph as a dict of dicts of edge weights 7 | X = len(M) 8 | Y = len(M[0]) 9 | for i in range(X): 10 | for j in range(Y): 11 | n = {} # neighbors to node (i, j) 12 | if i+1 < Y: 13 | n[(i+1, j)] = M[i+1][j] 14 | if j+1 < X: 15 | n[(i, j+1)] = M[i][j+1] 16 | if i > 0: 17 | n[(i-1, j)] = M[i-1][j] 18 | if j > 0: 19 | n[(i, j-1)] = M[i][j-1] 20 | g[(i,j)] = n 21 | return g 22 | 23 | def pathcost(p, g): 24 | ''' 25 | return the cost of path p in graph g 26 | ''' 27 | return 0 if len(p) < 2 else sum(g[a][b] for (a,b) in zip(p, p[1:])) 28 | 29 | 30 | M = [[131, 673, 234, 103, 18], 31 | [201, 96, 342, 965, 150], 32 | [630, 803, 746, 422, 111], 33 | [537, 699, 497, 121, 956], 34 | [805, 732, 524, 37, 331]] 35 | 36 | M = [map(int, line.strip().split(',')) for line in open('matrix.txt')] 37 | N = len(M) 38 | 39 | g = buildgraph(M) 40 | g[(-1,-1)] = {(0,0):M[0][0]} # source outside the matrix 41 | 42 | from euler import dijkstra 43 | 44 | path = dijkstra(g, (-1,-1), (N-1, N-1)) 45 | print pathcost(path, g) 46 | -------------------------------------------------------------------------------- /082.py: -------------------------------------------------------------------------------- 1 | ''' 2 | P0018, P0067, P0081, P0082, P0083 are variants of each other. 3 | 4 | Dynamic Programming 5 | 1) overlapping subproblems 6 | 2) optimal substructure 7 | 8 | Two approaches: 9 | 1) Top-down: memoization 10 | 2) Bottom-up: 11 | ''' 12 | 13 | mat = [[131,673,234,103,18], 14 | [201,96,342,965,150], 15 | [630,803,746,422,111], 16 | [537,699,497,121,956], 17 | [805,732,524,37,331]] 18 | 19 | mat = [map(int, line.strip().split(',')) for line in open('matrix.txt')] 20 | M = len(mat) - 1 21 | 22 | from euler import memoized 23 | @memoized 24 | def f(i, j, ii, jj=None): 25 | v = mat[i][j] 26 | if j==M: 27 | return v 28 | elif i==0: 29 | if i==ii: 30 | return v + min(f(i, j+1, i), f(i+1, j, i)) 31 | else: 32 | return v + f(i, j+1, i) 33 | elif i==M: 34 | if i==ii: 35 | return v + min(f(i, j+1, i), f(i-1, j, i)) 36 | else: 37 | return v + f(i, j+1, i) 38 | else: 39 | if i < ii: 40 | return v + min(f(i-1, j, i), f(i, j+1, i)) 41 | elif i > ii: 42 | return v + min(f(i+1, j, i), f(i, j+1, i)) 43 | else: 44 | return v + min(f(i+1, j, i), f(i-1, j, i), f(i, j+1, i)) 45 | 46 | print min(f(i, 0, i) for i in range(M+1)) 47 | -------------------------------------------------------------------------------- /090.py: -------------------------------------------------------------------------------- 1 | from euler import combinate 2 | 3 | def validate(cube1, cube2): 4 | s1 = set(cube1) 5 | s2 = set(cube2) 6 | if 6 in s1: s1.add(9) 7 | if 9 in s1: s1.add(6) 8 | if 6 in s2: s2.add(9) 9 | if 9 in s2: s2.add(6) 10 | return all((a in s1 and b in s2) or (a in s2 and b in s1) 11 | for (a,b) in [(0,1), (0,4), (0,9), (1,6), (2,5), (3,6), (4,9), (6,4), (8,1)]) 12 | 13 | 14 | 15 | def run(): 16 | s = set() 17 | cubes = list(combinate(range(10), 6)) 18 | for cube1 in cubes: 19 | for cube2 in cubes: 20 | if validate(cube1, cube2): 21 | str1 = ''.join(str(d) for d in sorted(cube1)) 22 | str2 = ''.join(str(d) for d in sorted(cube2)) 23 | s.add((str1, str2)) 24 | 25 | return len(s)//2 # order of the two cubes does not matter 26 | 27 | print run() 28 | 29 | 30 | ''' 31 | Comment: 32 | 33 | The wording about distinct sets in the last but one paragraph is quite misleading: for the purpose of forming 2-digit numbers 34 | {1, 2, 3, 4, 5, 6} and 35 | {1, 2, 3, 4, 5, 9} both reprents the extended set {1, 2, 3, 4, 5, 6, 9} 36 | 37 | But when counting the # of distinct arrangments of the two cubes, the cube 38 | {1, 2, 3, 4, 5, 6} 39 | is considered a different cube than 40 | {1, 2, 3, 4, 5, 9} 41 | 42 | I made the mistake that they are counted as one. 43 | ''' 44 | -------------------------------------------------------------------------------- /028.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Some observations: 3 | 1. the clock-wise-spining spiral always ends in the top-right corner 4 | 2. the length of each side inreases by 2 every circle outward 5 | 3. except the center, the 4 corners are easy to find 6 | 7 | ''' 8 | 9 | 10 | from itertools import count, takewhile 11 | 12 | # my complex version 13 | 14 | def take(n, iter): 15 | return [iter.next() for i in range(n)] 16 | 17 | def g(r): 18 | ' generate the # of elements in each circle of a spiral of radius r ' 19 | last = 0 20 | accu = 0 21 | for each in (n**2 for n in xrange(1, r+1, 2)): 22 | last = each - accu 23 | yield last 24 | accu = each 25 | 26 | def g2(): 27 | cnt = count(1) 28 | for circle in (take(n, cnt) for n in g(1001)): 29 | for each in circle[::-1][::max(1, len(circle)//4)][::-1]: 30 | yield each 31 | 32 | print sum(g2()) 33 | 34 | # another elegant solution 35 | # it turns out that working backwards (counter-clockwise) is much simpler 36 | 37 | def g3(): 38 | for i in range(1001, 1, -2): 39 | # work backwards # of elements in each circle of the spiral 40 | k = i**2 # the top-right corner value 41 | for j in range(4): # work backwards the 4 corner values 42 | yield k - j*(i-1) 43 | yield 1 # the center of the spiral 44 | 45 | print sum(g3()) 46 | -------------------------------------------------------------------------------- /075.py: -------------------------------------------------------------------------------- 1 | def old(): 2 | ' old version of the problem solved using brutal force ' 3 | n = 10000//3 4 | d = {} 5 | for a in range(1,n+1): 6 | for b in range(a+1, n+1): 7 | s = a*a + b*b 8 | c = int(s**.5) 9 | l = a + b + c 10 | if l > 10000: 11 | break 12 | if (s == c*c): 13 | if l in d: 14 | d[l] += 1 15 | else: 16 | d[l] = 1 17 | 18 | print sum(d[k] == 1 for k in d) 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | def PPT(f, a=3, b=4, c=5): 28 | ' Primitive Pythagorean Triples ' 29 | 30 | if f(a, b, c): 31 | PPT(f, a-2*b+2*c, 2*a-b+2*c, 2*a-2*b+3*c) 32 | PPT(f, a+2*b+2*c, 2*a+b+2*c, 2*a+2*b+3*c) 33 | PPT(f, -a+2*b+2*c, -2*a+b+2*c, -2*a+2*b+3*c) 34 | 35 | 36 | M = 1500000 37 | L = [0] * (M+1) 38 | 39 | def f(a, b, c): 40 | l = a + b + c 41 | if l > M: 42 | return False # discontinue recursion in PPT 43 | 44 | k = 0 45 | while True: 46 | k += 1 47 | kl = k * l # PPT's can be scaled: (3, 4, 5) -> (30, 40, 50) 48 | if kl > M: 49 | break 50 | else: 51 | L[kl] += 1 52 | 53 | return True # continue recursion 54 | 55 | 56 | PPT(f) 57 | 58 | print sum(1 if L[i]==1 else 0 for i in xrange(M+1)) 59 | -------------------------------------------------------------------------------- /085.py: -------------------------------------------------------------------------------- 1 | def f(W, H): 2 | return sum([w * h for w in range(1, W+1) for h in range(1, H+1)]) # takes a long time 3 | 4 | 5 | ''' 6 | Sum of the matrix: 7 | 8 | 1x1 1x2 1x3 1x4 ... 1xW 9 | 2x1 2x2 2x3 2x4 ... 2xW 10 | 3x1 3x2 3x3 3x4 ... 3xW 11 | . . . . . 12 | . . . . . 13 | . . . . . 14 | Hx1 Hx2 Hx3 Hx4 ... HxW 15 | 16 | 17 | for each column 18 | sum_col = w*(1+H)*H/2 19 | where w = 1, 2, 3, ..., W 20 | 21 | sum = (1+W)*W/2 * (1+H)*H/2 22 | ''' 23 | 24 | 25 | def g(W, H): 26 | return W*(1+W)/2 * H*(1+H)/2 27 | 28 | 29 | def run(): 30 | d = target = 2000000 31 | for W in range(1,2000+1): 32 | for H in range(W, 2000+1): 33 | n = g(W, H) 34 | dd = abs(n - target) 35 | if dd < d: 36 | d = dd 37 | print n, W, H, W * H 38 | 39 | run() 40 | 41 | 42 | 43 | ''' 44 | Another way to look at this problem: 45 | 46 | There is an analytical way to solve this one. If you imagine a rectangular grid 47 | measuring a units across and b units down. There are a+1 vertical lines and b+1 48 | horizontal lines. Each rectangle formed on this grid is made up of two vertical 49 | lines and two horizontal lines. As there are C(a+1,2)=a(a+1)/2 ways of picking 50 | two vertical lines and, similarly, b(b+1)/2, ways of picking two horizontal 51 | lines. Hence, there are a(a+1)b(b+1)/4 rectangles on an a by b rectangular 52 | grid. 53 | ''' 54 | 55 | -------------------------------------------------------------------------------- /096.py: -------------------------------------------------------------------------------- 1 | def sudoku(board): 2 | def available_options(pos, board): 3 | x,y = divmod(pos, 9) 4 | row = board[x*9:(x+1)*9] 5 | col = board[y::9] 6 | start = x//3*3*9 + y//3*3 7 | box = board[start:start+3] + board[start+9:start+9+3] + board[start+2*9:start+2*9+3] 8 | return set('123456789') - set(row) - set(col) - set(box) 9 | 10 | for pos in range(0, 9*9): 11 | if board[pos]=='0': # empty slot to fill 12 | for option in available_options(pos, board): 13 | new_board = board[:pos] + option + board[pos+1:] 14 | #print 'pos %2d, new board = %s' % (pos, new_board) 15 | rs = sudoku(new_board) 16 | if rs != 'failure': return rs 17 | return 'failure' # no available options. previous steps must be wrong 18 | return board # no empty slot left and no failure. we are gold. 19 | 20 | 21 | 22 | # usage: 23 | #b1 = '003020600900305001001806400008102900700000008006708200002609500800203009005010300' 24 | #s1 = '483921657967345821251876493548132976729564138136798245372689514814253769695417382' 25 | #t1 = sudoku(b1) 26 | #assert(t1 == s1) 27 | 28 | 29 | lines = [line.strip() for line in open('sudoku.txt')] 30 | rs = 0 31 | for i in range(0, 50): 32 | board = ''.join(lines[i*10+1:i*10+10]) 33 | solution= sudoku(board) 34 | #print 'Board #%2d, solution = %s' % (i+1, solution) 35 | rs += int(solution[:3]) 36 | print rs 37 | -------------------------------------------------------------------------------- /080.py: -------------------------------------------------------------------------------- 1 | 'http://www.homeschoolmath.net/teaching/square-root-algorithm.php' 2 | 3 | 4 | def sqrt(s, precision=100, as_str=False): 5 | 6 | def makepairs(d): 7 | pairs = [] 8 | while True: 9 | d, r = divmod(d, 100) 10 | 11 | pairs += [r] 12 | 13 | if d == 0: 14 | break 15 | 16 | pairs.reverse() 17 | return pairs 18 | 19 | 20 | pairs = makepairs(s) 21 | p = i = 0 22 | b = pairs[p] 23 | int_digits = [] 24 | frac_digits = [] 25 | 26 | while p < precision: 27 | 28 | for x in range(9, -1, -1): 29 | a = (20*i + x) * x 30 | if a <= b: 31 | break 32 | 33 | #print i, i*20+x, x, a, b, b-a 34 | 35 | if p < len(pairs): 36 | int_digits.append(x) 37 | else: 38 | frac_digits.append(x) 39 | 40 | 41 | i = i*10 + x 42 | p += 1 43 | b = (b - a)*100 + (pairs[p] if p < len(pairs) else 0) 44 | 45 | 46 | if b==0: # perfect square 47 | break 48 | 49 | 50 | 51 | if as_str: 52 | int_part = ''.join(map(str, int_digits)) 53 | if len(frac_digits) > 0: 54 | frac_part = ''.join(map(str, frac_digits)) 55 | return int_part + '.' + frac_part 56 | else: 57 | return int_part 58 | else: 59 | return int_digits, frac_digits 60 | 61 | 62 | 63 | s = 0 64 | for n in range(100+1): 65 | intd, fracd = sqrt(n) 66 | if len(fracd) > 0: 67 | # if it has fraction part, it is irrational; 68 | # otherwise it is a perfect square. 69 | s += sum(intd+fracd) 70 | 71 | print s 72 | -------------------------------------------------------------------------------- /093.py: -------------------------------------------------------------------------------- 1 | def quad(): 2 | for a in range(1, 10): 3 | for b in range(a+1, 10): 4 | for c in range(b+1, 10): 5 | for d in range(c+1, 10): 6 | yield a,b,c,d 7 | 8 | 9 | OPS = [ 10 | lambda x,y: x+y, 11 | lambda x,y: x-y, 12 | lambda x,y: x*y, 13 | lambda x,y: float(x)/y # note: division by zero possible 14 | ] 15 | 16 | # all possible full binary tree with 4 leaf nodes 17 | 18 | TREES = [ 19 | lambda op1, op2, op3, a, b, c, d: op1(op2(op3(a, b), c), d), 20 | lambda op1, op2, op3, a, b, c, d: op1(op2(a, op3(b, c)), d), 21 | lambda op1, op2, op3, a, b, c, d: op1(op2(a, b), op3(c, d)), 22 | lambda op1, op2, op3, a, b, c, d: op1(a, op2(op3(b, c), d)), 23 | lambda op1, op2, op3, a, b, c, d: op1(a, op2(b, op3(c, d))) 24 | ] 25 | 26 | 27 | def ops_triple(): 28 | for op1 in OPS: 29 | for op2 in OPS: 30 | for op3 in OPS: 31 | yield op1, op2, op3 32 | 33 | 34 | def expr(a, b, c, d): 35 | from euler import permutate 36 | 37 | rs = set() 38 | 39 | for (op1, op2, op3) in ops_triple(): 40 | for (a,b,c,d) in permutate([a, b, c, d]): 41 | for t in TREES: 42 | try: 43 | n = t(op1, op2, op3, a, b, c, d) 44 | if n > 0 and int(n) == n: 45 | rs.add(n) 46 | except: 47 | pass 48 | return rs 49 | 50 | 51 | def maxn(a, b, c, d): 52 | n = 0 53 | for each in sorted(expr(a, b, c, d)): 54 | if each != n+1: 55 | return n 56 | else: 57 | n = each 58 | 59 | 60 | print max((maxn(*t), t) for t in quad()) 61 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | from os import times 3 | from sys import platform, version_info 4 | from time import time, sleep 5 | 6 | from collections import defaultdict 7 | 8 | def groupcount(sq): 9 | ''' Accept a sequence, sq, and count its elements by group ''' 10 | d = defaultdict(int) # default 0 11 | for each in sq: 12 | d[each] += 1 13 | return dict(d) 14 | 15 | def timex(): 16 | ' Return elapsed (user time, system time, real time) since last call ' 17 | (utime, stime, _, _, _), rtime = times(), time() 18 | if platform=='win32' and version_info[0]<=2 and version_info[1]<=5: 19 | utime, stime = stime, utime 20 | 21 | while True: 22 | (utime2, stime2, _, _, _), rtime2 = times(), time() 23 | if platform=='win32' and version_info[0]<=2 and version_info[1]<=5: 24 | utime2, stime2 = stime2, utime2 25 | dutime, dstime, drtime = utime2 - utime, stime2 - stime, rtime2 - rtime 26 | rs = (dutime, dstime, drtime) 27 | print '%.4fu %.4fs %.4fr' % rs 28 | yield rs 29 | utime, stime, rtime = utime2, stime2, rtime2 30 | timex = timex().next 31 | 32 | 33 | 34 | def bin(n): 35 | ''' Return the binary representation 36 | 37 | >>> bin(4) 38 | '0b100' 39 | >>> bin(-4) 40 | '-0b100' 41 | ''' 42 | 43 | sign = '' if n >= 0 else '-' 44 | n = abs(n) 45 | s = [] 46 | while n: 47 | n, r = divmod(n, 2) 48 | s.append(r) 49 | return sign+'0b'+(''.join(map(str, s[::-1])) if len(s)>0 else '0') 50 | 51 | 52 | if __name__ == '__main__': 53 | timex() 54 | max(xrange(10**7)) 55 | sleep(5) 56 | timex() 57 | -------------------------------------------------------------------------------- /061.py: -------------------------------------------------------------------------------- 1 | from itertools import count 2 | from euler import permutate 3 | 4 | p3 = lambda n: n*(n+1)/2 5 | p4 = lambda n: n*n 6 | p5 = lambda n: n*(3*n-1)/2 7 | p6 = lambda n: n*(2*n-1) 8 | p7 = lambda n: n*(5*n-3)/2 9 | p8 = lambda n: n*(3*n-2) 10 | 11 | 12 | def take4digit(pn): 13 | for i in count(1): 14 | p = pn(i) 15 | if p < 1000: 16 | continue 17 | elif p > 9999: 18 | break 19 | else: 20 | yield p 21 | 22 | 23 | p3s = tuple(take4digit(p3)) 24 | p4s = tuple(take4digit(p4)) 25 | p5s = tuple(take4digit(p5)) 26 | p6s = tuple(take4digit(p6)) 27 | p7s = tuple(take4digit(p7)) 28 | p8s = tuple(take4digit(p8)) 29 | 30 | 31 | def find(pa, pb, pc, pd, pe, pf): 32 | for a in pa: 33 | a34 = a%100 34 | for b in pb: 35 | if a34==b//100: 36 | b34 = b%100 37 | for c in pc: 38 | if b34==c//100: 39 | c34 = c%100 40 | for d in pd: 41 | if c34==d//100: 42 | d34 = d%100 43 | for e in pe: 44 | if d34==e//100: 45 | e34 = e%100 46 | for f in pf: 47 | if e34==f//100: 48 | f34 = f%100 49 | if f34==a//100: 50 | return a,b,c,d,e,f 51 | 52 | 53 | 54 | def tryall(): 55 | ps = [p3s, p4s, p5s, p6s, p7s, p8s] 56 | for each in permutate(ps): 57 | rs = find(*each) 58 | if rs is not None: 59 | return rs 60 | 61 | print sum(tryall()) 62 | -------------------------------------------------------------------------------- /068.py: -------------------------------------------------------------------------------- 1 | from euler import permutate 2 | 3 | 4 | def ring3(a): 5 | line1 = a[0], a[1], a[2] 6 | line2 = a[3], a[2], a[5] 7 | line3 = a[4], a[5], a[1] 8 | if sum(line1)==sum(line2)==sum(line3): 9 | start = min(line1[0], line2[0], line3[0]) 10 | if line1[0] == start: 11 | return line1 + line2 + line3 12 | elif line2[0] == start: 13 | return line2 + line3 + line1 14 | else: 15 | return line3 + line1 + line2 16 | 17 | def find3(): 18 | s = set() 19 | for each in permutate([1,2,3,4,5,6]): 20 | rs = ring3(each) 21 | if rs is not None: 22 | s.add(rs) 23 | 24 | for each in sorted(s): 25 | print each 26 | 27 | 28 | 29 | def ring5(a): 30 | line1 = a[0], a[1], a[2] 31 | line2 = a[3], a[2], a[5] 32 | line3 = a[4], a[5], a[6] 33 | line4 = a[7], a[6], a[9] 34 | line5 = a[8], a[9], a[1] 35 | if sum(line1)==sum(line2)==sum(line3)==sum(line4)==sum(line5): 36 | start = min(line1[0], line2[0], line3[0], line4[0], line5[0]) 37 | if line1[0]==start: 38 | return line1 + line2 + line3 + line4 + line5 39 | elif line2[0]==start: 40 | return line2 + line3 + line4 + line5 + line1 41 | elif line3[0]==start: 42 | return line3 + line4 + line5 + line1 + line2 43 | elif line4[0]==start: 44 | return line4 + line5 + line1 + line2 + line3 45 | else: 46 | return line5 + line1 + line2 + line3 + line4 47 | 48 | 49 | 50 | def find5(): 51 | s = set() 52 | for each in permutate([1,2,3,4,5,6,7,8,9,10]): 53 | rs = ring5(each) 54 | if rs is not None: 55 | ds = ''.join(str(d) for d in rs) 56 | if len(ds)==16: 57 | print ds 58 | s.add(ds) 59 | 60 | 61 | return max(s) 62 | 63 | print find5() 64 | -------------------------------------------------------------------------------- /026.py: -------------------------------------------------------------------------------- 1 | 2 | def rindex(s, v): 3 | return len(s)+ ~list(reversed(s)).index(v) 4 | 5 | 6 | def frac(a, b): 7 | '''Return the precise representation of fraction a/b with recurring cycle 8 | 9 | e.g. 10 | 1/2 = 0.5 => 0, [5], [] 11 | 1/3 = 0.(3) => 0, [], [3] 12 | 1/6 = 0.1(6) = 0, [1], [6] 13 | ''' 14 | rs = [] 15 | ds = [] 16 | d, r = divmod(a, b) 17 | id = d # digits before the dot 18 | if r != 0: 19 | while True: 20 | a = r 21 | cnt = 0 22 | while a < b: 23 | a *= 10 24 | cnt += 1 25 | 26 | if cnt > 1: 27 | ds += [0]*(cnt-1) 28 | rs += [-1]*(cnt-1) 29 | 30 | d, r = divmod(a, b) 31 | 32 | if r == 0: # finite fraction 33 | ds += [d] 34 | return id, ds, [] 35 | 36 | if r in rs: 37 | i = rindex(rs, r) 38 | if d != ds[i]: # merge 0.3(3) into 0.(3) 39 | ds += [d] 40 | if i == len(rs) - 1: # dealing with edge cases 1/6 = 0.1(6) 41 | i += 1 42 | #''.join(map(str, ds[i:]))) 43 | return id, ds[:i], ds[i:] 44 | 45 | ds += [d] 46 | rs += [r] 47 | 48 | 49 | def pp(a, b): 50 | 'Pretty print the decimal representation of a/b' 51 | id, nonrecur, recur = frac(a, b) 52 | rs ='%s.%s' % (id, ''.join(map(str, nonrecur))) 53 | if len(recur) > 0: 54 | rs += '(%s)' % (''.join(map(str, recur))) 55 | return rs 56 | 57 | 58 | 59 | c = [] 60 | for n in range(2, 1000): 61 | id, nonrecur, recur = frac(1, n) 62 | 63 | c += [(len(recur), n)] 64 | 65 | k, n = max(c) 66 | 67 | print "1/%d = " % n, pp(1, n), 'contains a recurring cycle of length', k 68 | -------------------------------------------------------------------------------- /100.py: -------------------------------------------------------------------------------- 1 | from itertools import count 2 | 3 | 4 | def find(M=10**12): 5 | sqrt2 = 2**.5 6 | t = M 7 | while True: 8 | T = t*(t-1) 9 | b = int(t/sqrt2) 10 | while True: 11 | B = 2*b*(b-1) 12 | if B==T: 13 | return b, t, B, T 14 | elif B > T: 15 | break 16 | else: 17 | b += 1 18 | 19 | t += 1 20 | 21 | 22 | def test(): 23 | ' use this to find the initial values of b ' 24 | t = 2 25 | while True: 26 | b, t, B, T = find(t) 27 | print b, 28 | t += 1 29 | 30 | 31 | 32 | 33 | def A011900(): 34 | ' http://oeis.org/A011900 ' 35 | a = 1 36 | b = 3 37 | while True: 38 | yield a 39 | a, b = b, 6*b - a - 2 40 | 41 | 42 | def brutalforce(): 43 | ''' 44 | b = # of blue discs; t = # of total discs 45 | 46 | b(b-1) 1 47 | ------ = - 48 | t(t-1) 2 49 | 50 | since t >= 10^2 is quite huge, use approximation 51 | b^2 1 52 | --- = - 53 | t^2 2 54 | 55 | t >= 10^2, t^2 >= 10^24, therefore search for 2b^2 >= 10^24 56 | ''' 57 | for b in A011900(): 58 | if 2*b*b >= 10**24: 59 | return b 60 | 61 | 62 | 63 | ''' 64 | Analytical method: 65 | 66 | b = # of blue discs 67 | t = # of total discs 68 | 69 | b(b-1) 1 70 | ------ = - 71 | t(t-1) 2 72 | 73 | 2(b^2 - b) - (t^2 - t) = 0 74 | 75 | In general the way to solve these equations is to turn them into Pell's equation 76 | by linear substitution: 77 | 78 | 2(b^2 - b - 1/4 + 1/4) - (t^2 - t - 1/4 + 1/4) = 0 79 | 2((b-1/2)^2 + 1/4) - ((t-1/2)^2 + 1/4) = 0 80 | 81 | let x/2 = b-1/2 82 | y/2 = t-1/2 83 | 84 | 2((x^2)/4 + 1/4) - ((y^2)/4 + 1/4) = 0 85 | 2(x^2 + 1) - (y^2 + 1) = 0 86 | 2x^2 - y^2 = 1 87 | 88 | Now use Pell's equation to solve x, y (see Problem 66) 89 | ''' 90 | -------------------------------------------------------------------------------- /Test/efficient83.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | t0 = time() 3 | f = open("matrix.txt") 4 | filetext = f.read() 5 | f.close() 6 | matrix = filetext.strip().split("\n") 7 | for i in range(0,len(matrix)): 8 | matrix[i] = matrix[i].split(",") 9 | for j in range(0,len(matrix[i])): 10 | matrix[i][j] = int(matrix[i][j]) 11 | 12 | Neighbors = {} 13 | MinSoFar = {} 14 | for c in range(0,80): 15 | if c == 79: dcs = [-1] 16 | elif c == 0: dcs = [1] 17 | else: dcs = [-1,1] 18 | for r in range(0,80): 19 | MinSoFar[(r,c)] = 1600000 20 | if r == 79: drs = [-1] 21 | elif r == 0: drs = [1] 22 | else: drs = [-1,1] 23 | Neighbors[(r,c)] = [] 24 | for dc in dcs: 25 | Neighbors[(r,c)].append((r,c+dc)) 26 | for dr in drs: 27 | Neighbors[(r,c)].append((r+dr,c)) 28 | MinSoFar[(79,79)] = matrix[79][79] 29 | NodesToCheck = set([(78,79),(79,78)]) 30 | 31 | def UpdateMatrix(): 32 | global matrix,Neighbors,MinSoFar,NodesToCheck 33 | CheckNextTime = set() 34 | for (r,c) in NodesToCheck: 35 | if (r,c) in CheckNextTime: 36 | CheckNextTime.remove((r,c)) 37 | minneighborval = 1600000 38 | rcneighbors = list(Neighbors[(r,c)]) 39 | for nbr in rcneighbors: 40 | neighborval = MinSoFar[nbr] 41 | if neighborval < minneighborval: 42 | minneighborval = neighborval 43 | minneighbor = nbr 44 | newval = matrix[r][c] + minneighborval 45 | if newval == MinSoFar[(r,c)]: continue 46 | MinSoFar[(r,c)] = newval 47 | rcneighbors.remove(minneighbor) 48 | for nbr in rcneighbors: CheckNextTime.add(nbr) 49 | NodesToCheck = CheckNextTime 50 | 51 | iteration = 0 52 | limit = 164 53 | while iteration < limit: 54 | UpdateMatrix() 55 | iteration += 1 56 | 57 | print "the answer is", MinSoFar[0,0] 58 | print "took", time()-t0 59 | 60 | -------------------------------------------------------------------------------- /095.py: -------------------------------------------------------------------------------- 1 | from euler import memoized 2 | 3 | @memoized 4 | def sum_of_proper_divisors(n): 5 | s = 1 6 | i = 2 7 | while i**2 <= n: 8 | if n%i==0: 9 | s += i 10 | k = n // i 11 | if k != i: 12 | s += k 13 | i += 1 14 | 15 | return s 16 | 17 | 18 | 19 | def amicable_chain(n, threshold=10**6): 20 | seen = set() 21 | chain = [] 22 | while n not in seen: 23 | if n > threshold: return [] 24 | seen.add(n) 25 | chain.append(n) 26 | n = sum_of_proper_divisors(n) 27 | 28 | return chain[chain.index(n):] 29 | 30 | 31 | 32 | def search(threshold): 33 | n = 1 34 | longest = 0 35 | while n <= threshold: 36 | chain = amicable_chain(n) 37 | l = len(chain) 38 | if l > longest: 39 | longest = l 40 | print l, min(chain), chain 41 | 42 | n += 1 43 | 44 | #search(10**6) # takes about 1 min using PyPy; not good 45 | 46 | 47 | 48 | def sieve_divisor_sum(limit): 49 | ' sieving for divisor sums ' 50 | divsum = [0]*limit 51 | for i in xrange(1,limit): 52 | for j in xrange(2*i, limit, i): 53 | divsum[j] += i 54 | 55 | return divsum 56 | 57 | 58 | 59 | def main(): 60 | 61 | threshold = 10**6 62 | divsum = sieve_divisor_sum(threshold) 63 | 64 | def amicable_chain(n): 65 | seen = set() 66 | chain = [] 67 | while n not in seen: 68 | seen.add(n) 69 | chain.append(n) 70 | if n < threshold: 71 | n = divsum[n] 72 | else: 73 | return [] 74 | 75 | return chain[chain.index(n):] 76 | 77 | 78 | def search(): 79 | n = 1 80 | longest = 0 81 | while n <= threshold: 82 | chain = amicable_chain(n) 83 | l = len(chain) 84 | if l > longest: 85 | longest = l 86 | print l, min(chain), chain 87 | 88 | n += 1 89 | 90 | 91 | search() 92 | 93 | 94 | 95 | main() 96 | -------------------------------------------------------------------------------- /Test/prim.py: -------------------------------------------------------------------------------- 1 | def prim(g): 2 | ''' 3 | Prim's Minimum Spanning Tree Algorithm 4 | 5 | (Only works for undirected graph) 6 | ''' 7 | 8 | solved = set([g.keys()[0]]) # get an arbitrary node from the graph 9 | remain = set(g) - solved 10 | mst = {} 11 | 12 | while remain: 13 | cost, last, next = min((g[last][next], last, next) 14 | for last in solved for next in g[last] 15 | if next not in solved) 16 | mst[(last, next)] = cost 17 | solved.add(next) 18 | remain.remove(next) 19 | 20 | return mst 21 | 22 | 23 | def buildmatrix(file): 24 | return [map(lambda s: None if s=='-' else int(s), line.strip().split(',')) 25 | for line in open(file)] 26 | 27 | def buildgraph(M): 28 | X = len(M) 29 | Y = len(M[0]) 30 | g = {} 31 | 32 | for i in range(X): 33 | neighbors = {} 34 | for j in range(Y): 35 | if M[i][j] is not None: 36 | neighbors[j] = M[i][j] 37 | g[i] = neighbors 38 | 39 | return g 40 | 41 | from time import clock 42 | m = buildmatrix('network.txt') 43 | total = sum(sum(each for each in line if each is not None) 44 | for line in m) // 2 # symmetric weight matrix (undirected graph) 45 | g = buildgraph(m) 46 | 47 | t = clock() 48 | for i in range(1): 49 | mst = prim(g) 50 | print clock() - t 51 | 52 | print len(mst) 53 | print sum(mst.values()) 54 | print total - sum(mst.values()) 55 | 56 | 57 | 58 | 59 | M = [map(int, line.strip().split(',')) for line in open('matrix.txt')] 60 | X = len(M) 61 | Y = len(M[0]) 62 | 63 | g = {} 64 | for i in range(X): 65 | for j in range(Y): 66 | n = {} 67 | if i+1 < Y: 68 | n[(i+1, j)] = M[i+1][j] 69 | if j+1 < X: 70 | n[(i, j+1)] = M[i][j+1] 71 | g[(i,j)] = n 72 | 73 | g[(X-1, Y-1)] = {(0,0): M[0][0]} 74 | g[(0,0)][(X-1,Y-1)] = M[0][0] 75 | t = clock() 76 | mst = prim(g) 77 | print clock() - t 78 | -------------------------------------------------------------------------------- /043.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Bruteforce approach: 3 | Permutate 0..9 and check if the number satisfies the constraints. 4 | This needs 10! = 3628800 operations 5 | 6 | 7 | A better approach: 8 | Since d2d3d4 is divisible by 2, d4 is even (0, 2, 4, 6, 8). 9 | Since d4d5d6 is divisible by 5, d6 is 0 or 5. 10 | Permutate remaining digits requires 8! operations. 11 | This will reduce to 5 * 2 * 8! = 403200 operations 12 | 13 | 14 | Further speedup: 15 | Since d8d9d10 is divisible by 17, d8d9d10 is multiples of 17 under 1000 16 | without redudant digits. There are 44 in total. 17 | Permutate remainding digits. 18 | This will reduce to 5 * 2 * 44 * 5! = 52800 operations. 19 | ''' 20 | 21 | from euler import permutate, permutation as P 22 | 23 | def unique(s): 24 | ''' check if a set has no redudant elements ''' 25 | return len(s)==len(set(s)) 26 | 27 | def c8910(): 28 | for each in range(17,1000,17): 29 | s = map(int, '%03d' % each) 30 | if unique(s): 31 | yield s 32 | 33 | def c4(): 34 | for each in range(0,9,2): 35 | yield each 36 | 37 | def c6(): 38 | for each in (0,5): 39 | yield each 40 | 41 | def c(): 42 | digits = set(range(10)) 43 | for d4 in c4(): 44 | for d6 in c6(): 45 | for d8,d9,d10 in c8910(): 46 | if unique([d4,d6,d8,d9,d10]): 47 | for d1, d2, d3, d5, d7 in permutate(digits - 48 | set([d4,d6,d8,d9,d10])): 49 | yield [d1,d2,d3,d4,d5,d6,d7,d8,d9,d10] 50 | 51 | def f(): 52 | for n in c(): 53 | if ((n[2]*100 + n[3]*10 + n[4]) % 3 == 0 and 54 | (n[4]*100 + n[5]*10 + n[6]) % 7 == 0 and 55 | (n[5]*100 + n[6]*10 + n[7]) % 11== 0 and 56 | (n[6]*100 + n[7]*10 + n[8]) % 13== 0): 57 | yield (n[9] + n[8]*10 + n[7]*10**2 + n[6]*10**3 + 58 | n[5]*10**4 + n[4]*10**5 + n[3]*10**6 + 59 | n[2]*10**7 + n[1]*10**8 + n[0]*10**9) 60 | 61 | print sum(list(f())) 62 | -------------------------------------------------------------------------------- /094.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Heron's formula: 3 | 4 | Area = sqrt(s * (s - a) * (s - b) * (s - c)) 5 | 6 | s = (a + b + c) / 2 7 | 8 | a, b, c are the lengths of the three sides of the triangle. 9 | 10 | 11 | here we need 12 | 13 | a, a, a + 1 14 | 15 | or 16 | 17 | a, a, a - 1 18 | 19 | 20 | therefore 21 | 22 | A = (a+1) * sqrt((3a+1) * (a-1)) / 4 23 | 24 | or 25 | 26 | A = (a-1) * sqrt((3a-1) * (a+1)) / 4 27 | 28 | where A must be integral. 29 | ''' 30 | 31 | def naive(): 32 | acc = 0 33 | a = 1 34 | while a <= 10**9//3: 35 | a += 1 # a > 2 otherwise 1, 1, 2 or 1, 1, 0 is not a triangle 36 | p1 = 3*a+1 37 | p2 = 3*a-1 38 | 39 | r1 = p1 * (a - 1) 40 | if int(r1**.5)**2 == r1 and ((a+1)**2 * r1) % 16==0: 41 | acc += p1 42 | print a, a, a + 1 43 | 44 | r2 = p2 * (a + 1) 45 | if int(r2**.5)**2 == r2 and ((a-1)**2 * r2) % 16==0: 46 | acc += p2 47 | print a, a, a - 1 48 | 49 | return acc 50 | 51 | #print naive() 52 | 53 | 54 | ''' 55 | http://en.wikipedia.org/wiki/Heronian_triangle#Almost-equilateral_Heronian_triangles 56 | ''' 57 | 58 | 59 | 60 | def PPT(): 61 | ' Primitive Pythagorean Triples ' 62 | 63 | from collections import deque 64 | fifo = deque([(3, 4, 5)]) 65 | while True: 66 | (a, b, c) = fifo.popleft() 67 | yield (a, b, c) 68 | fifo.append((a-2*b+2*c, 2*a-b+2*c, 2*a-2*b+3*c)) 69 | fifo.append((a+2*b+2*c, 2*a+b+2*c, 2*a+2*b+3*c)) 70 | fifo.append((-a+2*b+2*c, -2*a+b+2*c, -2*a+2*b+3*c)) 71 | 72 | 73 | 74 | 75 | def use_ppt(): 76 | acc = 0 77 | for (x, y, z) in PPT(): 78 | if z==2*x+1 or z==2*x-1: 79 | p = 2*z + 2*x 80 | if p > 10**9: break 81 | print z, z, 2*x 82 | acc += p 83 | 84 | 85 | if z==2*y+1 or z==2*y-1: 86 | p = 2*z + 2*y 87 | if p > 10**9: break 88 | print z, z, 2*y 89 | acc += p 90 | 91 | assert 518408346 == acc 92 | print acc 93 | 94 | use_ppt() 95 | 96 | 'needs PyPy for both implementation ...' 97 | -------------------------------------------------------------------------------- /066.py: -------------------------------------------------------------------------------- 1 | ' Related to P064, P065 ' 2 | 3 | def CFE(s): 4 | ' Continued fraction expansion of sqrt(s) ' 5 | 6 | m = 0 7 | d = 1 8 | a0 = int(s**.5) 9 | a = a0 10 | 11 | encountered = set([(m, d, a)]) 12 | rs = [a0] 13 | 14 | while True: 15 | m = d * a - m 16 | d = (s - m**2) / d 17 | if d == 0: break # a perfect square 18 | a = int(a0 + m) // d 19 | 20 | if (m, d, a) in encountered: 21 | break 22 | else: 23 | rs += [a] 24 | encountered.add((m, d, a)) 25 | 26 | return rs 27 | 28 | 29 | def convergent(CFE): 30 | 31 | def g(CFE): 32 | ' Generate a_i for i = 0, 1, 2, ... in the CFE ' 33 | yield CFE[0] # a0 34 | if len(CFE) > 1: 35 | while True: 36 | # square root has periodic CFE from a1 to an 37 | for each in CFE[1:]: 38 | yield each 39 | 40 | a = g(CFE) 41 | a0 = a.next() # a0 will be the only element if CFE is from a square. 42 | a1 = a.next() # Throw StopIteration if CFE is not periodic and 43 | # stop the outer generator as a side effect. Nice! 44 | 45 | hm, km = a0, 1 46 | kn, hn = a1, a0 * a1 + 1 47 | 48 | while True: 49 | yield (hn, kn) 50 | ai = a.next() 51 | hm, hn = hn, ai * hn + hm 52 | km, kn = kn, ai * kn + km 53 | 54 | 55 | 56 | def pell(D): 57 | ''' 58 | Pell's equation (http://en.wikipedia.org/wiki/Pell's_equation) 59 | 60 | x^2 - D * y^2 = 1 61 | 62 | if D is a square, there is no int solutions 63 | 64 | return the fundamental solution (x, y) s.t. x is minimal 65 | return None if no solution when D is a square 66 | ''' 67 | 68 | for (x, y) in convergent(CFE(D)): 69 | if x**2 - D * y**2 == 1: 70 | return x, y 71 | 72 | 73 | def P066(M): 74 | rs = [] 75 | for D in xrange(1, M+1): 76 | xy = pell(D) 77 | if xy is not None: 78 | x, y = xy 79 | rs.append((x, D)) 80 | 81 | return max(rs)[1] 82 | 83 | print P066(1000) 84 | -------------------------------------------------------------------------------- /104.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | def fib(nth): 4 | ''' 5 | Calculate the approximation of the n-th fibonacci number 6 | 7 | This is useful to get the most significant digits of the number, but is 8 | not accurate for the least significant digits 9 | ''' 10 | phi = (1+5**.5)/2 # golden ratio 11 | return int((phi**nth + (1 - phi)**nth) / (5**.5)) # will overflow 12 | 13 | 14 | 15 | ''' 16 | basic idea for the following code: 17 | 18 | check the last 9 digits, if it is pandigital, then use the fib(nth) function 19 | above to check the first 9 digits. when iterating the fib numbers, only add 20 | the last 9 digits with modulo arithmetic. this will speed up because fewer 21 | big ints are used. 22 | 23 | In short, 24 | 1) addition mod 10^9 to track the last 9 digits (iteration approach) 25 | 2) multiplication by (1+sqrt(5))/2 to track the first 9 digits (golden ratio) 26 | 27 | 28 | from math import sqrt 29 | 30 | def isPandigital(s): 31 | return set(s) == set('123456789') 32 | 33 | rt5=sqrt(5) 34 | def check_first_digits(n): 35 | def mypow( x, n ): 36 | res=1.0 37 | for i in xrange(n): 38 | res *= x 39 | # truncation to avoid overflow: 40 | if res>1E20: res*=1E-10 41 | return res 42 | # this is an approximation for large n: 43 | F = mypow( (1+rt5)/2, n )/rt5 44 | s = '%f' % F 45 | if isPandigital(s[:9]): 46 | print n 47 | return True 48 | 49 | a, b, n = 1, 1, 1 50 | while True: 51 | if isPandigital( str(a)[-9:] ): 52 | # Only when last digits are 53 | # pandigital check the first digits: 54 | if check_first_digits(n): 55 | break 56 | a, b = b, a+b 57 | b=b%1000000000 58 | n += 1 59 | 60 | exit() 61 | ''' 62 | 63 | ''' 64 | F(n) = n # n <= 1 65 | F(n) = F(n-1) + F(n-2) # n > 1 66 | ''' 67 | 68 | a, b, k = 0, 1, 0 69 | d = set('123456789') 70 | while 1: 71 | if set(str(a%10**9)) == d == set(str(a)[:9]): 72 | print k 73 | break 74 | 75 | a, b = b, a+b 76 | k += 1 77 | if not (k % 1000): 78 | print k 79 | -------------------------------------------------------------------------------- /Test/improvedprim.py: -------------------------------------------------------------------------------- 1 | def prim(g): 2 | solved = set() 3 | mst = {} 4 | edges = set() 5 | 6 | current = g.keys()[0] 7 | while True: 8 | for neighbor in g[current]: 9 | cost = g[current][neighbor] 10 | pair = frozenset([current, neighbor]) 11 | edge = (cost, pair) 12 | if pair in mst: continue 13 | if edge in edges: 14 | edges.remove(edge) 15 | else: 16 | edges.add(edge) 17 | 18 | if edges: 19 | edge = min(edges) 20 | edges.remove(edge) 21 | cost, (a, b) = edge 22 | mst[frozenset([a,b])] = cost 23 | solved.add(current) 24 | current = a if b in solved else b 25 | else: 26 | break 27 | 28 | return mst 29 | 30 | def buildmatrix(file): 31 | return [map(lambda s: None if s=='-' else int(s), line.strip().split(',')) 32 | for line in open(file)] 33 | 34 | def buildgraph(M): 35 | X = len(M) 36 | Y = len(M[0]) 37 | g = {} 38 | 39 | for i in range(X): 40 | neighbors = {} 41 | for j in range(Y): 42 | if M[i][j] is not None: 43 | neighbors[j] = M[i][j] 44 | g[i] = neighbors 45 | 46 | return g 47 | 48 | 49 | from time import clock 50 | m = buildmatrix('network.txt') 51 | total = sum(sum(each for each in line if each is not None) 52 | for line in m) // 2 # symmetric weight matrix (undirected graph) 53 | g = buildgraph(m) 54 | 55 | t = clock() 56 | for i in range(1): 57 | mst = prim(g) 58 | print clock() - t 59 | 60 | print len(mst) 61 | print sum(mst.values()) 62 | print total - sum(mst.values()) 63 | 64 | 65 | M = [map(int, line.strip().split(',')) for line in open('matrix.txt')] 66 | X = len(M) 67 | Y = len(M[0]) 68 | 69 | g = {} 70 | for i in range(X): 71 | for j in range(Y): 72 | n = {} 73 | if i+1 < Y: 74 | n[(i+1, j)] = M[i+1][j] 75 | if j+1 < X: 76 | n[(i, j+1)] = M[i][j+1] 77 | g[(i,j)] = n 78 | 79 | g[(X-1, Y-1)] = {(0,0): M[0][0]} 80 | g[(0,0)][(X-1,Y-1)] = M[0][0] 81 | 82 | t = clock() 83 | mst = prim(g) 84 | print clock() - t 85 | -------------------------------------------------------------------------------- /011.py: -------------------------------------------------------------------------------- 1 | matrix = '''\ 2 | 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 3 | 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 4 | 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 5 | 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 6 | 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 7 | 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 8 | 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 9 | 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 10 | 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 11 | 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 12 | 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 13 | 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 14 | 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 15 | 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 16 | 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 17 | 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 18 | 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 19 | 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 20 | 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 21 | 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48\ 22 | ''' 23 | 24 | m = [] 25 | for line in matrix.split('\n'): m.append(map(int, line.split())) 26 | 27 | # crazy one-liner 28 | print max((lambda i,j: max( 29 | reduce(lambda x,y: x*y, (m[i ][j+x] for x in range(4) if j+x < 20)), 30 | reduce(lambda x,y: x*y, (m[i+x][j ] for x in range(4) if i+x < 20)), 31 | reduce(lambda x,y: x*y, (m[i+x][j+x] for x in range(4) if i+x < 20 and j+x < 20)), 32 | reduce(lambda x,y: x*y, (m[i+x][j-x] for x in range(4) if i+x < 20 and 0 <= j+x < 20)))) 33 | (i,j) for i in range(20) for j in range(20)) 34 | 35 | 36 | # normal approach 37 | def maxpro(i, j): 38 | h = reduce(lambda x,y: x*y, (m[i ][j+x] for x in range(4) if j+x < 20)) 39 | v = reduce(lambda x,y: x*y, (m[i+x][j ] for x in range(4) if i+x < 20)) 40 | dl = reduce(lambda x,y: x*y, (m[i+x][j+x] for x in range(4) if i+x < 20 and j+x < 20)) 41 | dr = reduce(lambda x,y: x*y, (m[i+x][j-x] for x in range(4) if i+x < 20 and 0 <= j+x < 20)) 42 | return max(h,v,dl,dr) 43 | 44 | print max(maxpro(i,j) for i in range(20) for j in range(20)) 45 | -------------------------------------------------------------------------------- /058.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | from euler import isprime 3 | from itertools import izip 4 | 5 | 6 | # helper functions 7 | def take(n, iter): 8 | return [iter.next() for i in range(n)] 9 | 10 | def count(offset=0, step=1): 11 | while True: 12 | yield offset 13 | offset += step 14 | 15 | # version 1, very slow 16 | ''' 17 | def g(): 18 | ' generate the # of elements in each circle of a spiral ' 19 | last = 0 20 | accu = 0 21 | for each in (n**2 for n in count(1, 2)): 22 | last = each - accu 23 | yield last 24 | accu = each 25 | 26 | def g2(): 27 | cnt = count(1) 28 | for circle in (take(n, cnt) for n in g()): 29 | for each in circle[::-1][::max(1, len(circle)//4)][::-1]: 30 | yield each 31 | 32 | def g3(): 33 | ntotal = 0 34 | nprimes = 0 35 | for each in g2(): 36 | ntotal += 1 37 | if isprime(each): nprimes += 1 38 | 39 | yield nprimes/ntotal 40 | 41 | gg = g3() 42 | take(10, gg) # initially is 0 because 1 is not prime 43 | for (num, ratio) in izip(count(10), gg): 44 | #print num, '%3.2f' % ratio 45 | if ratio < 0.13: break 46 | print 'Length', (num-1)//4 * 2 + 1 47 | ''' 48 | 49 | # version 2, slightly better 50 | ''' 51 | def g4(): 52 | i = 1 53 | l = 3 54 | for n in count(8, 8): 55 | yield l, n, n+i 56 | i += n 57 | l += 2 58 | 59 | def g5(): 60 | for l,n,e in g4(): 61 | for i in reversed(range(4)): 62 | yield e - i*(l-1) 63 | 64 | ntotal = 0 65 | nprime = 0 66 | for each in g5(): 67 | ntotal += 1 68 | if isprime(each): nprime += 1 69 | if nprime/ntotal < .1: break 70 | print int(each**.5) 71 | ''' 72 | 73 | def g6(): 74 | ' generate corner values of the spiral (excluding the center) ' 75 | for i in count(3, 2): # start from the 2nd circle (width=3) 76 | end = i**2 # the end value of the circle 77 | for j in reversed(range(4)): # 4 corners of the circle 78 | yield end - j*(i-1) 79 | 80 | def f(ratio): 81 | ntotal = 0 82 | nprime = 0 83 | for each in g6(): 84 | ntotal += 1 85 | if isprime(each): nprime += 1 86 | if nprime/ntotal < ratio: return int(each**.5) 87 | 88 | print f(.1) 89 | -------------------------------------------------------------------------------- /074.py: -------------------------------------------------------------------------------- 1 | 'Similar to problem 92. Also related to problem 34.' 2 | 3 | from euler import memoized, factorial as F 4 | 5 | 6 | 7 | @memoized 8 | def next(n): 9 | s = 0 10 | while n!=0: 11 | n, r = divmod(n, 10) 12 | s += F(r) 13 | 14 | return s 15 | 16 | 17 | @memoized 18 | def cycle(n): 19 | def recur(n, c, s=set()): 20 | if n in s: 21 | return c 22 | else: 23 | return recur(next(n), c+1, s ^ set([n])) 24 | return recur(n, 0) 25 | 26 | 27 | def run(): 28 | 29 | 30 | def permutation(seq): 31 | '''number of all permutations of a sequence without repetition 32 | 33 | there might be repeated elements in the sequence though 34 | 35 | e.g. [1, 1, 2, 3, 3, 4, 5] 36 | 37 | there are 38 | 2 x 1's (A = 2) 39 | 1 x 2's (B = 1) 40 | 2 x 3's (C = 2) 41 | 1 x 4's (D = 1) 42 | 1 x 5's (E = 1) 43 | 44 | total permutations: (A+B+C+D+E)! / (A! * B! * C! * D! * E!) 45 | ''' 46 | 47 | 48 | l = len(seq) 49 | 50 | f = {} 51 | for each in seq: 52 | f[each] = f.get(each, 0) + 1 53 | 54 | d = 1 55 | for v in f.values(): 56 | d *= F(v) 57 | 58 | return F(l) / d 59 | 60 | 61 | 62 | def g(): 63 | for d5 in range(9, 0, -1): # 1st digit cannot be 0 64 | yield [d5] # 1-digit 65 | for d4 in range(d5, -1, -1): 66 | yield [d5, d4] # 2-digit 67 | for d3 in range(d4, -1, -1): 68 | yield [d5, d4, d3] # 3-digit 69 | for d2 in range(d3, -1, -1): 70 | yield [d5, d4, d3, d2] # 4-digit 71 | for d1 in range(d2, -1, -1): 72 | yield [d5, d4, d3, d2, d1] # 5-digit 73 | for d0 in range(d1, -1, -1): 74 | yield [d5, d4, d3, d2, d1, d0] # 6-digit 75 | 76 | 77 | s = 0 78 | for seq in g(): 79 | n = int(''.join(str(d) for d in seq)) 80 | if 60 == cycle(n): 81 | p = permutation(seq) 82 | if 0 in seq: 83 | p0 = permutation([d for d in seq if d!=0]) 84 | print seq, p, '-', p0 , '=', p - p0 85 | s += p - p0 86 | else: 87 | print seq, p 88 | s += p 89 | return s 90 | 91 | print 'Positions of digits do not matter as long as there is no 0. Notice if there is any 0 in the sequence, they cannot be at the beginning. Subtract those permutations accordingly. ' 92 | print run() 93 | -------------------------------------------------------------------------------- /092.py: -------------------------------------------------------------------------------- 1 | from euler import factorial 2 | 3 | def naive(): 4 | 5 | def a89(n): 6 | while True: 7 | if n == 1: 8 | return False 9 | 10 | if n == 89: 11 | return True 12 | 13 | n = sum(int(each)**2 for each in str(n)) 14 | 15 | c = 0 16 | for n in range(1, 10000000): 17 | if a89(n): 18 | c += 1 19 | 20 | print c 21 | 22 | 23 | 24 | def slightlybetter(): 25 | 26 | def chain(n): 27 | while True: 28 | if n == 0 or n == 1 or n == 89: 29 | return n 30 | 31 | n = sum(int(each)**2 for each in str(n)) 32 | 33 | c567 = [chain(n) for n in range(567+1)] 34 | 35 | c = 0 36 | for n in range(10000000): 37 | if 89 == c567[sum(int(each)**2 for each in str(n))]: 38 | c += 1 39 | print c 40 | 41 | 42 | 43 | def efficient(): 44 | 45 | def chain(n): 46 | while True: 47 | if n == 0 or n == 1 or n == 89: 48 | return n 49 | 50 | n = sum(int(each)**2 for each in str(n)) 51 | 52 | 53 | 54 | 55 | def permutation(seq): 56 | '''number of all permutations of a sequence without repetition 57 | 58 | there might be repeated elements in the sequence though 59 | 60 | e.g. [1, 1, 2, 3, 3, 4, 5] 61 | 62 | there are 63 | 2 x 1's (A = 2) 64 | 1 x 2's (B = 1) 65 | 2 x 3's (C = 2) 66 | 1 x 4's (D = 1) 67 | 1 x 5's (E = 1) 68 | 69 | total permutations: (A+B+C+D+E)! / (A! * B! * C! * D! * E!) 70 | ''' 71 | 72 | 73 | l = len(seq) 74 | 75 | f = {} 76 | for each in seq: 77 | f[each] = f.get(each, 0) + 1 78 | 79 | d = 1 80 | for v in f.values(): 81 | d *= factorial[v] 82 | 83 | return factorial[l] / d 84 | 85 | 86 | 87 | def g(): 88 | 89 | for d0 in range(10): 90 | for d1 in range(d0+1): 91 | for d2 in range(d1+1): 92 | for d3 in range(d2+1): 93 | for d4 in range(d3+1): 94 | for d5 in range(d4+1): 95 | for d6 in range(d5+1): 96 | yield [d6, d5, d4, d3, d2, d1, d0] 97 | 98 | 99 | 100 | c567 = [chain(n) for n in range(567+1)] 101 | c = 0 102 | for each in g(): 103 | if 89 == c567[sum(d**2 for d in each)]: 104 | c += permutation(each) 105 | 106 | return c 107 | 108 | 109 | print efficient() 110 | -------------------------------------------------------------------------------- /Test/dijkstra.py: -------------------------------------------------------------------------------- 1 | def buildgraph(M): 2 | g = {} # graph as a dict of dicts of edge weights 3 | X = len(M) 4 | Y = len(M[0]) 5 | for i in range(X): 6 | for j in range(Y): 7 | n = {} # neighbors to node (i, j) 8 | if i+1 < Y: 9 | n[(i+1, j)] = M[i+1][j] 10 | if j+1 < X: 11 | n[(i, j+1)] = M[i][j+1] 12 | if i > 0: 13 | n[(i-1, j)] = M[i-1][j] 14 | if j > 0: 15 | n[(i, j-1)] = M[i][j-1] 16 | g[(i,j)] = n 17 | return g 18 | 19 | def tracetosource(n, p): 20 | ''' 21 | produce a path tracing back to source according to precedecssor p 22 | ''' 23 | path = [] 24 | path.append(n) 25 | while n in p: 26 | n = p[n] 27 | path.append(n) 28 | return path 29 | 30 | def pathcost(p, g): 31 | ''' 32 | return the cost of path p in graph g 33 | ''' 34 | return 0 if len(p) < 2 else sum(g[a][b] for (a,b) in zip(p, p[1:])) 35 | 36 | 37 | def dijkstra(g, s, d): 38 | ''' 39 | Dijkstra's Shortest Path Algorithm 40 | 41 | Find the shortest path from source s to destination d in graph g 42 | 43 | Dijkastra is a special case of A* (A-star) path searching algorithm w/o 44 | heuristic (F = G + H, with H=0) 45 | 46 | A*: http://www.policyalmanac.org/games/aStarTutorial.htm 47 | ''' 48 | open = set([s]) 49 | closed = set() 50 | predecessor = {} 51 | cost = {s:0} # cost of path to node from s 52 | 53 | while open: 54 | mincost, current = min((cost[each], each) for each in open) 55 | open.remove(current) 56 | closed.add(current) 57 | if current==d: 58 | break 59 | for neighbor in g[current]: 60 | if neighbor in closed: 61 | continue 62 | if neighbor in open: 63 | newcost = cost[current] + g[current][neighbor] 64 | if newcost < cost[neighbor]: 65 | predecessor[neighbor] = current 66 | cost[neighbor] = newcost 67 | else: 68 | open.add(neighbor) 69 | predecessor[neighbor] = current 70 | cost[neighbor] = cost[current] + g[current][neighbor] 71 | 72 | return tracetosource(d, predecessor)[::-1] # reverse the traceback 73 | 74 | 75 | M = [[131, 673, 234, 103, 18], 76 | [201, 96, 342, 965, 150], 77 | [630, 803, 746, 422, 111], 78 | [537, 699, 497, 121, 956], 79 | [805, 732, 524, 37, 331]] 80 | M = [map(int, line.strip().split(',')) for line in open('matrix.txt')] 81 | 82 | N = len(M) 83 | g = buildgraph(M) 84 | g[(-1,-1)] = {(0,0):M[0][0]} # source outside the matrix 85 | 86 | from time import clock 87 | t = clock() 88 | path = dijkstra(g, (-1,-1), (N-1, N-1)) 89 | print pathcost(path, g) 90 | print clock() - t 91 | -------------------------------------------------------------------------------- /098.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from sys import argv 4 | from pprint import pprint 5 | from itertools import takewhile, count 6 | from math import ceil 7 | from euler import memoized 8 | 9 | 10 | @memoized 11 | def swaps(n=9): 12 | ' all square anagram digit pairs with n digits ' 13 | anagrams = {} 14 | 15 | lo = int(ceil((10**(n-1))**.5)) 16 | hi = int((10**n)**.5) 17 | 18 | for each in (x**2 for x in range(lo, hi)): 19 | s = str(each) 20 | ss = ''.join(sorted(s, reverse=True)) 21 | if ss in anagrams: 22 | anagrams[ss].append(s) 23 | else: 24 | anagrams[ss] = [s] 25 | 26 | 27 | pairs = [] 28 | for v in anagrams.values(): 29 | if len(v) > 1: 30 | v = sorted(v) 31 | for a in v: 32 | for b in v[1:]: 33 | if a != b: 34 | pairs.append((a, b)) 35 | return pairs 36 | 37 | 38 | 39 | 40 | def swap(word1, word2): 41 | ' word1 and word2 are a square anagram word pair ' 42 | 43 | if sorted(word1) == sorted(word2): 44 | patterns = swaps(len(word1)) 45 | for (p1, p2) in patterns: 46 | l1 = sorted(zip(word1, p1)) 47 | l2 = sorted(zip(word2, p2)) 48 | if l1 == l2: 49 | 50 | d_char = {} 51 | d_digit = {} 52 | flag = True 53 | for (char, digit) in l1: 54 | if char in d_char: 55 | if d_char[char] != digit: 56 | flag = False 57 | break 58 | else: 59 | d_char[char] = digit 60 | 61 | 62 | if digit in d_digit: 63 | if d_digit[digit] != char: 64 | flag = False 65 | break 66 | else: 67 | d_digit[digit] = char 68 | 69 | 70 | if flag: 71 | yield p1, p2 72 | 73 | 74 | 75 | 76 | def anagrams(words): 77 | ' return all pairs of anagrams from a list of words ' 78 | rs = {} 79 | for word in words: 80 | w = ''.join(sorted(word)) 81 | if w in rs: 82 | rs[w].add(word) 83 | else: 84 | rs[w] = set([word]) 85 | 86 | pairs = [] 87 | for (k, v) in rs.items(): 88 | if len(v)>1: 89 | v = sorted(v) 90 | for a in v: 91 | for b in v[1:]: 92 | if a != b: 93 | pairs.append((a,b)) 94 | 95 | return pairs 96 | 97 | 98 | 99 | def main(): 100 | words = open(argv[1]).read().replace('"', '').split(',') 101 | for (word1, word2) in anagrams(words): 102 | for (p1, p2) in swap(word1, word2): 103 | p1 = int(p1) 104 | p2 = int(p2) 105 | yield max(p1, p2), min(p1, p2), word1, word2 106 | 107 | 108 | 109 | print max(main()) 110 | -------------------------------------------------------------------------------- /cipher1.txt: -------------------------------------------------------------------------------- 1 | 79,59,12,2,79,35,8,28,20,2,3,68,8,9,68,45,0,12,9,67,68,4,7,5,23,27,1,21,79,85,78,79,85,71,38,10,71,27,12,2,79,6,2,8,13,9,1,13,9,8,68,19,7,1,71,56,11,21,11,68,6,3,22,2,14,0,30,79,1,31,6,23,19,10,0,73,79,44,2,79,19,6,28,68,16,6,16,15,79,35,8,11,72,71,14,10,3,79,12,2,79,19,6,28,68,32,0,0,73,79,86,71,39,1,71,24,5,20,79,13,9,79,16,15,10,68,5,10,3,14,1,10,14,1,3,71,24,13,19,7,68,32,0,0,73,79,87,71,39,1,71,12,22,2,14,16,2,11,68,2,25,1,21,22,16,15,6,10,0,79,16,15,10,22,2,79,13,20,65,68,41,0,16,15,6,10,0,79,1,31,6,23,19,28,68,19,7,5,19,79,12,2,79,0,14,11,10,64,27,68,10,14,15,2,65,68,83,79,40,14,9,1,71,6,16,20,10,8,1,79,19,6,28,68,14,1,68,15,6,9,75,79,5,9,11,68,19,7,13,20,79,8,14,9,1,71,8,13,17,10,23,71,3,13,0,7,16,71,27,11,71,10,18,2,29,29,8,1,1,73,79,81,71,59,12,2,79,8,14,8,12,19,79,23,15,6,10,2,28,68,19,7,22,8,26,3,15,79,16,15,10,68,3,14,22,12,1,1,20,28,72,71,14,10,3,79,16,15,10,68,3,14,22,12,1,1,20,28,68,4,14,10,71,1,1,17,10,22,71,10,28,19,6,10,0,26,13,20,7,68,14,27,74,71,89,68,32,0,0,71,28,1,9,27,68,45,0,12,9,79,16,15,10,68,37,14,20,19,6,23,19,79,83,71,27,11,71,27,1,11,3,68,2,25,1,21,22,11,9,10,68,6,13,11,18,27,68,19,7,1,71,3,13,0,7,16,71,28,11,71,27,12,6,27,68,2,25,1,21,22,11,9,10,68,10,6,3,15,27,68,5,10,8,14,10,18,2,79,6,2,12,5,18,28,1,71,0,2,71,7,13,20,79,16,2,28,16,14,2,11,9,22,74,71,87,68,45,0,12,9,79,12,14,2,23,2,3,2,71,24,5,20,79,10,8,27,68,19,7,1,71,3,13,0,7,16,92,79,12,2,79,19,6,28,68,8,1,8,30,79,5,71,24,13,19,1,1,20,28,68,19,0,68,19,7,1,71,3,13,0,7,16,73,79,93,71,59,12,2,79,11,9,10,68,16,7,11,71,6,23,71,27,12,2,79,16,21,26,1,71,3,13,0,7,16,75,79,19,15,0,68,0,6,18,2,28,68,11,6,3,15,27,68,19,0,68,2,25,1,21,22,11,9,10,72,71,24,5,20,79,3,8,6,10,0,79,16,8,79,7,8,2,1,71,6,10,19,0,68,19,7,1,71,24,11,21,3,0,73,79,85,87,79,38,18,27,68,6,3,16,15,0,17,0,7,68,19,7,1,71,24,11,21,3,0,71,24,5,20,79,9,6,11,1,71,27,12,21,0,17,0,7,68,15,6,9,75,79,16,15,10,68,16,0,22,11,11,68,3,6,0,9,72,16,71,29,1,4,0,3,9,6,30,2,79,12,14,2,68,16,7,1,9,79,12,2,79,7,6,2,1,73,79,85,86,79,33,17,10,10,71,6,10,71,7,13,20,79,11,16,1,68,11,14,10,3,79,5,9,11,68,6,2,11,9,8,68,15,6,23,71,0,19,9,79,20,2,0,20,11,10,72,71,7,1,71,24,5,20,79,10,8,27,68,6,12,7,2,31,16,2,11,74,71,94,86,71,45,17,19,79,16,8,79,5,11,3,68,16,7,11,71,13,1,11,6,1,17,10,0,71,7,13,10,79,5,9,11,68,6,12,7,2,31,16,2,11,68,15,6,9,75,79,12,2,79,3,6,25,1,71,27,12,2,79,22,14,8,12,19,79,16,8,79,6,2,12,11,10,10,68,4,7,13,11,11,22,2,1,68,8,9,68,32,0,0,73,79,85,84,79,48,15,10,29,71,14,22,2,79,22,2,13,11,21,1,69,71,59,12,14,28,68,14,28,68,9,0,16,71,14,68,23,7,29,20,6,7,6,3,68,5,6,22,19,7,68,21,10,23,18,3,16,14,1,3,71,9,22,8,2,68,15,26,9,6,1,68,23,14,23,20,6,11,9,79,11,21,79,20,11,14,10,75,79,16,15,6,23,71,29,1,5,6,22,19,7,68,4,0,9,2,28,68,1,29,11,10,79,35,8,11,74,86,91,68,52,0,68,19,7,1,71,56,11,21,11,68,5,10,7,6,2,1,71,7,17,10,14,10,71,14,10,3,79,8,14,25,1,3,79,12,2,29,1,71,0,10,71,10,5,21,27,12,71,14,9,8,1,3,71,26,23,73,79,44,2,79,19,6,28,68,1,26,8,11,79,11,1,79,17,9,9,5,14,3,13,9,8,68,11,0,18,2,79,5,9,11,68,1,14,13,19,7,2,18,3,10,2,28,23,73,79,37,9,11,68,16,10,68,15,14,18,2,79,23,2,10,10,71,7,13,20,79,3,11,0,22,30,67,68,19,7,1,71,8,8,8,29,29,71,0,2,71,27,12,2,79,11,9,3,29,71,60,11,9,79,11,1,79,16,15,10,68,33,14,16,15,10,22,73 2 | -------------------------------------------------------------------------------- /089.py: -------------------------------------------------------------------------------- 1 | ROMAN = { 2 | 'I': 1, 3 | 'V': 5, 4 | 'X': 10, 5 | 'L': 50, 6 | 'C': 100, 7 | 'D': 500, 8 | 'M': 1000 9 | } 10 | 11 | COMBO = { 12 | 'IV': 4, 13 | 'IX': 9, 14 | 'XL': 40, 15 | 'XC': 90, 16 | 'CD': 400, 17 | 'CM': 900 18 | } 19 | 20 | 21 | DESC = [(n, r) for (r, n) in ROMAN.items()] + [(n, r) for (r, n) in COMBO.items()] 22 | DESC.sort(reverse=True) 23 | # DESC = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')] 24 | 25 | def parse_roman(s): 26 | ' parse a valid Roman numeral to its integer value ' 27 | 28 | i = 0 29 | n = 0 30 | p = 1000 31 | while i < len(s): 32 | current = s[i] 33 | next = s[i+1] if i+1 < len(s) else '' 34 | pair = current + next 35 | 36 | if pair in COMBO: 37 | v = COMBO[pair] 38 | if p < v: 39 | return 0 40 | else: 41 | p = v 42 | n += v 43 | i += 2 44 | else: 45 | v = ROMAN[current] 46 | if p < v: 47 | return 0 48 | else: 49 | p = v 50 | n += v 51 | i += 1 52 | return n 53 | 54 | 55 | 56 | def test_parse_roman(): 57 | assert 3 == parse_roman('III') 58 | assert 4 == parse_roman('IIII') # valid but not minimal (should be IV) 59 | assert 4 == parse_roman('IV') 60 | assert 0 == parse_roman('IIV') # invalid 61 | assert 16 == parse_roman('XVI') 62 | assert 16 == parse_roman('XIIIIII') # valid but not minimal 63 | assert 16 == parse_roman('VVVI') # valid but not minimal 64 | assert 19 == parse_roman('XIX') # valid but not minimal 65 | assert 0 == parse_roman('IXX') # invalid 66 | 67 | 68 | 69 | def format_roman(k): 70 | ' format integer n as a minimal Roman numeral ' 71 | 72 | roman = '' 73 | i = 0 74 | while k > 0: 75 | (n, r) = DESC[i] 76 | d = k - n 77 | if d >= 0: 78 | roman += r 79 | k = d 80 | else: 81 | i += 1 82 | 83 | return roman 84 | 85 | 86 | 87 | 88 | def test_format_roman(): 89 | assert format_roman(3) == 'III' 90 | assert format_roman(4) == 'IV' 91 | assert format_roman(5) == 'V' 92 | assert format_roman(6) == 'VI' 93 | assert format_roman(7) == 'VII' 94 | assert format_roman(8) == 'VIII' 95 | assert format_roman(9) == 'IX' 96 | assert format_roman(453) == 'CDLIII' 97 | assert format_roman(3390) == 'MMMCCCXC' 98 | 99 | print 'format_roman() tested' 100 | 101 | 102 | #test_format_roman() 103 | 104 | 105 | def main(): 106 | from sys import stdin 107 | 108 | num_digits_saved = 0 109 | for each in stdin: 110 | roman = each.strip() 111 | formatted = format_roman(parse_roman(roman)) 112 | num_digits_saved += len(roman) - len(formatted) 113 | print num_digits_saved 114 | 115 | 116 | main() 117 | -------------------------------------------------------------------------------- /lazy.py: -------------------------------------------------------------------------------- 1 | ''' Lazy List module 2 | 3 | Two goals: 4 | 1. Lazy lists should be no different from ordinary lists in users' view. 5 | 2. Provide a decorator function to transform a generator to a lazy list. 6 | ''' 7 | 8 | class LazyException(Exception): pass 9 | 10 | class LazyList(object): 11 | # must be new style class for slicing to work properly 12 | # otherwise l[:] will result in a slice object (0, sys.maxint, None) 13 | # instead of (None, None, None) 14 | 15 | def __init__(self, g): 16 | self.l = [] # interal cache of generated list 17 | self.g = g # g is an instantiated generator 18 | 19 | def _extend(self, n): 20 | self.l.extend(self.g.next() for _ in range(n)) 21 | 22 | def __getitem__(self, k): 23 | if isinstance(k, int): # l[n] 24 | d = k - len(self.l) 25 | if d>=0: self._extend(d+1) 26 | return self.l[k] 27 | elif isinstance(k, slice): # l[start:stop:step] 28 | if k.stop is None: # l[_:] -> extend to the end 29 | self.l.extend(self.g) 30 | else: 31 | d = k.stop - len(self.l) 32 | if d>=0: self._extend(d+1) 33 | return self.l[k] 34 | else: 35 | raise LazyException('Invalid index: %s' % k) 36 | 37 | def __call__(self, k): # mimic a callable function 38 | return self[k] 39 | 40 | def __iter__(self): 41 | def iter(): 42 | for each in self.l: 43 | yield each 44 | 45 | for each in self.g: 46 | self.l.append(each) # incremental cache 47 | yield each 48 | 49 | return iter() 50 | 51 | def lazylist(g): 52 | '''lazylist decorator. 53 | 54 | used to make a LazyList from generator definition''' 55 | 56 | return lambda *a: LazyList(g(*a)) 57 | 58 | 59 | def compact(s): 60 | '''Compact a sequence: [a,b,b,c,c,c] -> [(a,1),(b,2),(c,3)]''' 61 | 62 | @lazylist 63 | def g(): 64 | seq = iter(s) # make it an iterator, otherwise there will be one more 65 | # count of the 1st element if s is a list/str/tuple 66 | cnt = 0 67 | for it in seq: 68 | cnt = 1 # if the sequence is empty, cnt will be 0, which stops the 69 | # last yield statement at the bottom 70 | break 71 | # TRICK: this will pop the 1st element from the sequence while leaving 72 | # the rest untouched. this is useful to work with iterators, since a 73 | # iterator only supports one-pass read 74 | 75 | for e in seq: 76 | if it==e: 77 | cnt += 1 78 | else: 79 | yield (it, cnt) 80 | it, cnt = e, 1 # reset counter 81 | 82 | if cnt: yield (it, cnt) 83 | 84 | return g() 85 | 86 | def expand(s): 87 | '''Expand a sequence: [(a,1),(b,2),(c,3)] -> [a,b,b,c,c,c]''' 88 | 89 | @lazylist 90 | def g(): 91 | for (e, cnt) in s: 92 | for i in range(cnt): 93 | yield e 94 | 95 | return g() 96 | -------------------------------------------------------------------------------- /graph.py: -------------------------------------------------------------------------------- 1 | class Graph(object): 2 | g = {} # {src: {neighbor: weight of edge src->neighbor}, ...} 3 | 4 | def __init__(self, iter=[]): 5 | for src, dst, weight in iter: 6 | self.add(src, dst, weight) 7 | 8 | def add(self, src, dst, weight): 9 | ''' Add an edge from src to dst with weight ''' 10 | self.g.setdefault(src, {})[dst] = weight 11 | 12 | def neighbors(self, node): 13 | ''' Return a dict of {neighbor: weight} of all neighbors of node ''' 14 | return self.g.get(node, {}) 15 | 16 | def weight(self, src, dst): 17 | ''' Return the weight of the edge from src to dst ''' 18 | return 0 if src==dst else self.g[src][dst] 19 | 20 | DirectedGraph = Graph # DirectedGraph is an alias to Graph 21 | 22 | class UndirectedGraph(Graph): 23 | def add(self, src, dst, weight): 24 | super(self.__class__, self).add(src, dst, weight) 25 | super(self.__class__, self).add(dst, src, weight) 26 | 27 | def dijkstra(graph, src): 28 | ''' Generate the shortest path to each node from src 29 | 30 | Each time the generator will yield a tuple of (parent, child, cost), 31 | an edge of the shortest path spanning tree rooted from src in graph 32 | ''' 33 | 34 | assert isinstance(graph, Graph) 35 | 36 | pending = set([src]) 37 | closed = set() 38 | mintc = {src: 0} # min total cost to each node from src 39 | parent = {} # {child: parent} track path to each node 40 | 41 | while pending: 42 | tc, cur = min((mintc[each], each) for each in pending) 43 | if cur in parent: # skip the root node (with no parent) of the tree 44 | yield parent[cur], cur, graph.weight(parent[cur], cur) 45 | pending.remove(cur) 46 | closed.add(cur) 47 | 48 | for node in graph.neighbors(cur): 49 | if node not in closed: 50 | assert graph.weight(cur, node) >= 0 51 | # Dijkstra's algorithm only works for non-negative weight 52 | cost = mintc[cur] + graph.weight(cur, node) 53 | if node in pending: 54 | if cost < mintc[node]: # if a shorter path is found 55 | mintc[node] = cost # update cost and trace 56 | parent[node]= cur 57 | else: 58 | pending.add(node) 59 | mintc[node] = cost 60 | parent[node]= cur 61 | 62 | def shortestPath(graph, src, dst): 63 | tree = {} 64 | for parent, child, cost in dijkstra(graph, src): 65 | tree[child] = parent 66 | if child==dst: break 67 | 68 | def traceToRoot(tree, node): 69 | ''' Trace the path from node to root in tree ''' 70 | yield node 71 | while node in tree: 72 | node = tree[node] 73 | yield node 74 | 75 | return list(traceToRoot(tree, dst))[::-1] # reverse the path so src->dst 76 | 77 | 78 | 79 | if __name__ == '__main__': 80 | g = UndirectedGraph([ 81 | ('O', 'A', 2), 82 | ('O', 'B', 5), 83 | ('O', 'C', 4), 84 | ('A', 'B', 2), 85 | ('C', 'B', 1), 86 | ('A', 'D', 7), 87 | ('B', 'D', 4), 88 | ('B', 'E', 3), 89 | ('C', 'E', 4), 90 | ('D', 'E', 1), 91 | ('D', 'T', 5), 92 | ('E', 'T', 7), 93 | ]) 94 | 95 | for node in dijkstra(g, 'O'): 96 | print node 97 | 98 | print shortestPath(g, 'O', 'T') 99 | -------------------------------------------------------------------------------- /071.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | 4 | ''' 5 | calculating the number to the left of 3/7 in each successive sequence ... 6 | 7 | This is Farey sequence: 8 | F1 = 0/1, 1/1 9 | F2 = 0/1, 1/2, 1/1 10 | F3 = 0/1, 1/3, 1/2, 2/3, 1/1 11 | 12 | Each term is the mediant of its neighbors. 13 | Mediant of a/b and c/d is (a+c)/(b+d) 14 | 15 | See also Stern-Brocot Tree for a visual illustration of the process of 16 | creating Farey sequence. 17 | 18 | So if we know a/b and c/d, the terms between them will be 19 | a a+c c 20 | - --- - 21 | b b+d d 22 | 23 | a a+c a+2c c 24 | - --- ---- - 25 | b b+d b+2d d 26 | 27 | a a+c a+2c a+3c c 28 | - --- ---- ---- - 29 | b b+d b+2d b+3d d 30 | 31 | In general, the term immediately to the left of c/d will be (a+n*c)/(b+n*d). 32 | 33 | In this problem a=2, b=5, c=3, d=7. The term to the left of 3/7 is thus 34 | (2+3*n)/(5+7*n) 35 | 36 | And 5+7*n <= 10**6, n == (10**6 - 5) // 7 37 | 38 | The nominator would be (2 + 3 * ((10**6 - 5)//7)) 39 | ''' 40 | 41 | print (2 + 3 * ((10**6 - 5) // 7)) 42 | 43 | exit() 44 | 45 | ''' 46 | The following code does the previous math iterally. 47 | ''' 48 | 49 | def prob71(): 50 | a, b = 2, 5 51 | c, d = 3, 7 52 | for n in range(8, 10**6+1): 53 | m1, m2 = a + c, b + d 54 | if m2 <= n: 55 | a, b = m1, m2 56 | return a, b 57 | 58 | print prob71() 59 | exit() 60 | 61 | ''' 62 | the following code works this way: 63 | 1. List all n/d immediately to the left of 3/7 for d in [1,10**6] 64 | 2. Remove k * (3/7) (caused by Int conversion) 65 | 3. Sort the result list in descending order 66 | 4. Find the first fraction n/d such that hcf(n/d) == 1 67 | ''' 68 | 69 | from euler import hcf 70 | 71 | 72 | ds = [(int(d*3/7), d) for d in range(1,10**6+1)] 73 | ds.sort(key=lambda x: -x[0]/x[1]) 74 | ds = [each for each in ds if each[0]/each[1] < 3/7] 75 | 76 | for n,d in ds: 77 | if hcf(n,d) == 1: 78 | print '%d/%d = %10.10f' % (n, d, n/d) 79 | break 80 | 81 | exit() 82 | 83 | ''' 84 | L = 3/7 85 | min = L 86 | min_= 0 87 | for d in range(1,10**6+1): 88 | n = int(d*L) 89 | if min > L - n/d != 0: 90 | min = L - n/d 91 | min_= d 92 | print 'Done,', int(min_*L), '/', min_ 93 | ''' 94 | 95 | ''' 96 | Find the largest n/d such that 97 | 1. n and d are positive integers 98 | 2. n < d <= 10**6 99 | 3. n/d < 3/7 100 | 4. hcf(n, d) == 1 101 | 102 | Procedures: 103 | 1. Check d from 10**6 to 1, since it is likely the largest n/d will be 104 | found when both n and d are large. 105 | 2. For each d, check n from d*3/7 to 1, since n/d < 3/7 must hold true 106 | 3. Record the first pair of (n, d) such that hcf(n, d) == 1 107 | 4. Check next d 108 | 5. Repeat until d is 1 109 | 6. Compare pairs of (n, d) and find the largest n/d 110 | ''' 111 | 112 | exit() # this following code is fast to find the first two but slow to finish 113 | 114 | 115 | p = (0, 0, 0) 116 | l = 3/7 117 | for d in range(10**6, 0, -1): 118 | for n in range(int(d*3/7), 1, -1): 119 | if hcf(n, d) == 1: 120 | k = (n/d, n, d) 121 | if l > k[0] > p[0]: 122 | p = k 123 | print '%d/%d = %10.10f' % (p[1], p[2], p[0]) 124 | break 125 | -------------------------------------------------------------------------------- /054.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3 | bit representation of a card 4 | 5 | rrrr shdc 6 | 7 | 0-3 shdc: suit of the card (Spade, Heart, Diamond, Club) 8 | 4-7 rrrr: rank of the card (0-12: "23456789TJQKA") 9 | 10 | ''' 11 | 12 | 13 | RANK = "23456789TJQKA" 14 | SUIT = "CDHS" 15 | CARDMAP = dict((RANK[rank] + SUIT[suit], (rank<<4)|(1<>4 for card in hand), reverse=True) 35 | 36 | # is the hand a flush? 37 | isflush = c1 & c2 & c3 & c4 & c5 & 0b1111 38 | 39 | # is the hand a straight? ABCDE 40 | isstraight = (r1-r2==r2-r3==r3-r4==r4-r5==1) 41 | 42 | if isflush and isstraight: 43 | if r1==11: 44 | return [ ROYALFLUSH ] 45 | else: 46 | return [ STRAIGHTFLUSH, r1 ] 47 | 48 | if isflush: 49 | return [ FLUSH, r1, r2, r3, r4, r5 ] 50 | 51 | if isstraight: 52 | return [ STRAIGHT, r1 ] 53 | 54 | 55 | # is the hand four of a kind? AAAAB or ABBBB 56 | is4ofakind = (r2 == r3 == r4) and (r1==r2 or r4==r5) 57 | if is4ofakind: 58 | if r1==r2: # AAAAB 59 | return [ FOUROFAKIND, r1, r5 ] 60 | else: # ABBBB 61 | return [ FOUROFAKIND, r5, r1 ] 62 | 63 | # is the hand full house? AAABB or AABBB 64 | isfullhouse = (r1==r2==r3 and r4==r5) or (r1==r2 and r3==r4==r5) 65 | if isfullhouse: 66 | if r2==r3: # AAABB 67 | return [ FULLHOUSE, r1, r5 ] 68 | else: # AABBB 69 | return [ FULLHOUSE, r5, r1 ] 70 | 71 | 72 | # is the hand three of a kind? AAABC, ABBBC, ABCCC 73 | is3ofakind = (r1==r2==r3) or (r2==r3==r4) or (r3==r4==r5) 74 | if is3ofakind: 75 | if r2==r3: 76 | if r3!=r4: # AAABC 77 | return [ THREEOFAKIND, r1, r4, r5 ] 78 | else: # ABBBC 79 | return [ THREEOFAKIND, r2, r1, r5 ] 80 | else: # ABCCC 81 | return [ THREEOFAKIND, r5, r1, r2 ] 82 | 83 | 84 | # is the hand two pairs? AABBC, AABCC, ABBCC 85 | is2pairs = (r1==r2 and r3==r4) or (r1==r2 and r4==r5) or (r2==r3 and r4==r5) 86 | if is2pairs: 87 | if r1==r2: 88 | if r3==r4: # AABBC 89 | return [ TWOPAIRS, r1, r3, r5 ] 90 | else: # AABCC 91 | return [ TWOPAIRS, r1, r5, r3 ] 92 | else: # ABBCC 93 | return [TWOPAIRS, r2, r5, r1 ] 94 | 95 | 96 | # is the hand one pair? AABCD, ABBCD, ABCCD, ABCDD 97 | is1pair = (r1==r2) or (r2==r3) or (r3==r4) or (r4==r5) 98 | if is1pair: 99 | if r1==r2: # AABCD 100 | return [ ONEPAIR, r1, r3, r4, r5 ] 101 | elif r2==r3: # ABBCD 102 | return [ ONEPAIR, r2, r1, r4, r5 ] 103 | elif r3==r4: # ABCCD 104 | return [ ONEPAIR, r3, r1, r2, r5 ] 105 | else: 106 | return [ ONEPAIR, r5, r1, r2, r3 ] 107 | 108 | # else the hand must be a high card 109 | ishighcard = True 110 | if ishighcard: 111 | return [ HIGHCARD, r1, r2, r3, r4, r5 ] 112 | 113 | 114 | 115 | def p1win(hand_str): 116 | ''' if p1 wins ''' 117 | hand = [CARDMAP[card] for card in hand_str.strip().split(' ')] 118 | p1, p2 = hand[:5], hand[5:] 119 | 120 | return rank(p1) > rank(p2) 121 | 122 | 123 | from sys import argv 124 | print sum(p1win(line) for line in open(argv[1])) 125 | -------------------------------------------------------------------------------- /036.py: -------------------------------------------------------------------------------- 1 | from euler import ispalindromic, dec2bin 2 | 3 | # this is slow (taking about 10 sec. to compute) 4 | #print sum(i for i in range(10**6) if ispalindromic(str(i)) and 5 | #ispalindromic(dec2bin(i))) 6 | 7 | ''' 8 | All palindromic numbers above 10 below 1,000,000 are in one of the following 9 | forms: 10 | 11 | AA 12 | ABA 13 | ABBA 14 | ABCBA 15 | ABCCBA 16 | 17 | where A in [1,2,3,4,5,6,7,8,9], B and C in [0,1,2,3,4,5,6,7,8,9]. 18 | 19 | All single-digit numbers are palindromic numbers [0,1,2,3,4,5,6,7,8,9]. 20 | 21 | Notice that palindromic numbers are symmetric, so we only need to calculate the 22 | first half of a palindromic number. 23 | 24 | If a palindromic number has n digits and n is even, it is in the same form of 25 | the palindromic number containing n-1 digits (n-1 is odd)---the only difference 26 | is that it repeats the middle digit in the n-1 digit number. 27 | 28 | In base 2, all palindromic numbers must be odd, because if it is even, it must 29 | ends with 0, while the first bit will never be 0. 30 | ''' 31 | 32 | def palindromicnumbers(): 33 | ''' 34 | Generate a list of all palindromic numbers containing up to 6 digits 35 | ''' 36 | 37 | return map(int, ['%d' % (a) # 10 1-digit numbers (including 0) 38 | for a in range(10)] +\ 39 | ['%d%d' % (a,a) # 9 2-digit numbers 40 | for a in range(1,10)] +\ 41 | ['%d%d%d' % (a,b,a) # 90 3-digit 42 | for a in range(1,10) 43 | for b in range(10)] +\ 44 | ['%d%d%d%d' % (a,b,b,a) # 90 4-digit, same as 3-digit 45 | for a in range(1,10) 46 | for b in range(10)] +\ 47 | ['%d%d%d%d%d' % (a,b,c,b,a) # 900 5-digit 48 | for a in range(1,10) 49 | for b in range(10) 50 | for c in range(10)] +\ 51 | ['%d%d%d%d%d%d' % (a,b,c,c,b,a) # 900 6-digit, same as 5-digit 52 | for a in range(1,10) 53 | for b in range(10) 54 | for c in range(10)]) 55 | 56 | # This is much more efficient 57 | print sum(i for i in palindromicnumbers() 58 | if i%2 and ispalindromic(dec2bin(i))) 59 | 60 | # now I'm going to write it like crazy Lisp-ist ... 61 | 62 | def palindromic(n): 63 | ''' 64 | Generate palindromic numbers containing n digits 65 | ''' 66 | return range(10) if n==1 else map(int, ('%d'*n % (comb + comb[::-1][n%2:]) 67 | for comb in reduce(lambda ts, es: [t+(e,) for t in ts for e in es], 68 | [[(t,) for t in range(1,10)]] + [range(10)]*(sum(divmod(n,2))-1)))) 69 | 70 | 71 | print sum(each for each in reduce(lambda x,y: x+y, 72 | (palindromic(i) for i in range(1,7))) 73 | if each % 2 and ispalindromic(dec2bin(each))) 74 | 75 | # eventually evolves into a one-liner ... 76 | 77 | print sum(each for each in reduce(lambda x,y: x+y, 78 | # this lambda for concatenating lists of palindromic numbers 79 | 80 | ((lambda n: range(10) if n==1 else map(int, 81 | # this lambda for producing a list of palindromic numbers with n-digits 82 | 83 | ('%d'*n % (comb + comb[::-1][n%2:]) 84 | # this is to expand (3,2,1) to (3,2,1,2,3) or (3,2,1,1,2,3), depending on 85 | # the required palindromic number containing odd/even number of digits, 86 | # thus the n%2 to test. comb[::-1] effectively reverses comb 87 | 88 | for comb in reduce(lambda ts, es: [t+(e,) for t in ts for e in es], 89 | # this lambda for producing a list of tuple [(x,y) for x in xs for y in ys] 90 | # but it can do so for any number of 'for's! 91 | 92 | [[(t,) for t in range(1,10)]] + [range(10)]*(sum(divmod(n,2))-1)))) 93 | # sum(divmod(n,2)) = n//2 + n%2. This is used to calculate half part of all 94 | # digits necessary to get the palindromic numbers 95 | # e.g.: AA = 1, ABA = 2, ABBA = 2, ABCBA = 3, ABCCBA = 3 96 | 97 | )(i) for i in range(1,7))) if each % 2 and ispalindromic(dec2bin(each))) 98 | # range(1,7) to produce palindromic numbers containing 1~6 digits 99 | # also check if the palindromic number is odd to speed up a little bit 100 | -------------------------------------------------------------------------------- /102.py: -------------------------------------------------------------------------------- 1 | ''' 2 | There are various methods to determine if a point is an interior/exterior 3 | point of a polygon. http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/ 4 | ''' 5 | 6 | 7 | ''' 8 | This works for all convex polygon 9 | 10 | Walk along the edges of a convex polygon in a direction (clockwise/counter- 11 | clockwise). If point p is always on the same side (right/left) as you walk, p 12 | is an interior point of the convex polygon; otherwise p is an exterior point. 13 | ''' 14 | 15 | def position(p, line): 16 | '''Return the sign of relation between point p and line 17 | 18 | This method makes use of exterior product of vector A->P and B->P to 19 | calculate the signed area of the parallelogram formed by the two vectors. 20 | ''' 21 | px, py = p 22 | (ax, ay), (bx, by) = line 23 | s, t = px-ax, py-ay # vector AP 24 | u, v = px-bx, py-by # vector BP 25 | return s*v - t*u # exterior product of vector AP and BP, a.k.a signed 26 | # area of the parallelogram formed by the two vectors 27 | 28 | 29 | def pointinpolygon(pt, pts): 30 | ''' Check if point pt is an interior point of polygon specified by a list of 31 | points pts 32 | ''' 33 | shiftpts = pts[1:] + [pts[0]] # shift the points ... 34 | pairs = zip(pts, shiftpts) # ... to generate a list of pairs 35 | signs = [position(pt, pair) for pair in pairs] 36 | return all(map(lambda x: x>=0, signs)) or all(map(lambda x: x<=0, signs)) 37 | 38 | print sum(pointinpolygon((0, 0), [(ax,ay),(bx,by),(cx,cy)]) 39 | for ax,ay,bx,by,cx,cy in 40 | (map(int, line.split(',')) for line in open('triangles.txt'))) 41 | 42 | 43 | ''' 44 | Signed Area and orientation of polygons 45 | 46 | Need some modern geometry knowledge to understand ... 47 | ''' 48 | def signedarea(x1,y1,x2,y2,x3,y3): 49 | # the order of the three points determines the orientation of the triangle 50 | # positive if counterclockwise, negative if clockwise 51 | return (-x2*y1 + x3*y1 + x1*y2 - x3*y2 - x1*y3 + x2*y3) * .5 52 | # this is the signed area of the triangle. half of the parallelogram 53 | # calculated by exterior product of the two vectors 54 | 55 | def orientation(x1,y1,x2,y2,x3,y3): 56 | return signedarea(x1,y1,x2,y2,x3,y3) > 0 57 | 58 | def contains(x1,y1,x2,y2,x3,y3,xp,yp): 59 | # for point p (xp, yp) lies in the triangle, the three sub-triangles must 60 | # have the same orientation 61 | o1 = orientation(x1,y1,x2,y2,xp,yp) 62 | o2 = orientation(x2,y2,x3,y3,xp,yp) 63 | o3 = orientation(x3,y3,x1,y1,xp,yp) 64 | return o1 == o2 == o3 65 | 66 | 67 | print sum(contains(ax,ay,bx,by,cx,cy, 0, 0) for ax,ay,bx,by,cx,cy in 68 | (map(int, line.split(',')) for line in open('triangles.txt'))) 69 | 70 | 71 | ''' 72 | A more elegant way 73 | 74 | Triangle ABC contains P if the A(ABP) + A(ACP) + A(BCP) = A(ABC) 75 | 76 | A() is the area function of a triangle 77 | 78 | Heron's formula to calcuate area of triangles 79 | 80 | A = (s * (s - a) * (s - b) * (s - c)) ** .5 81 | where 82 | s = (a + b + c)/2 83 | a,b,c are the length of the three sides 84 | 85 | Note this method is not very perfect due to rounding error in area 86 | ''' 87 | 88 | def distance(x1,y1,x2,y2): 89 | return ((x1-x2)**2 + (y1-y2)**2)**.5 90 | 91 | def area(a, b, c): 92 | s = (a + b + c) * .5 93 | return (s * (s - a) * (s - b) * (s - c)) ** .5 94 | 95 | def areatriangle(x1,y1,x2,y2,x3,y3): 96 | a = distance(x1,y1,x2,y2) 97 | b = distance(x1,y1,x3,y3) 98 | c = distance(x2,y2,x3,y3) 99 | return area(a,b,c) 100 | 101 | def contain(x0,y0,x1,y1,x2,y2,x3,y3): 102 | s0 = areatriangle(x1,y1,x2,y2,x3,y3) 103 | s1 = areatriangle(x0,y0,x1,y1,x2,y2) 104 | s2 = areatriangle(x0,y0,x1,y1,x3,y3) 105 | s3 = areatriangle(x0,y0,x2,y2,x3,y3) 106 | return abs((s1 + s2 + s3) - s0) < .0001 # combat rounding error 107 | 108 | print sum(contain(0, 0, ax,ay,bx,by,cx,cy) for ax,ay,bx,by,cx,cy in 109 | (map(int, line.split(',')) for line in open('triangles.txt'))) 110 | -------------------------------------------------------------------------------- /Test/network.txt: -------------------------------------------------------------------------------- 1 | -,-,-,427,668,495,377,678,-,177,-,-,870,-,869,624,300,609,131,-,251,-,-,-,856,221,514,-,591,762,182,56,-,884,412,273,636,-,-,774 2 | -,-,262,-,-,508,472,799,-,956,578,363,940,143,-,162,122,910,-,729,802,941,922,573,531,539,667,607,-,920,-,-,315,649,937,-,185,102,636,289 3 | -,262,-,-,926,-,958,158,647,47,621,264,81,-,402,813,649,386,252,391,264,637,349,-,-,-,108,-,727,225,578,699,-,898,294,-,575,168,432,833 4 | 427,-,-,-,366,-,-,635,-,32,962,468,893,854,718,427,448,916,258,-,760,909,529,311,404,-,-,588,680,875,-,615,-,409,758,221,-,-,76,257 5 | 668,-,926,366,-,-,-,250,268,-,503,944,-,677,-,727,793,457,981,191,-,-,-,351,969,925,987,328,282,589,-,873,477,-,-,19,450,-,-,- 6 | 495,508,-,-,-,-,-,765,711,819,305,302,926,-,-,582,-,861,-,683,293,-,-,66,-,27,-,-,290,-,786,-,554,817,33,-,54,506,386,381 7 | 377,472,958,-,-,-,-,-,-,120,42,-,134,219,457,639,538,374,-,-,-,966,-,-,-,-,-,449,120,797,358,232,550,-,305,997,662,744,686,239 8 | 678,799,158,635,250,765,-,-,-,35,-,106,385,652,160,-,890,812,605,953,-,-,-,79,-,712,613,312,452,-,978,900,-,901,-,-,225,533,770,722 9 | -,-,647,-,268,711,-,-,-,283,-,172,-,663,236,36,403,286,986,-,-,810,761,574,53,793,-,-,777,330,936,883,286,-,174,-,-,-,828,711 10 | 177,956,47,32,-,819,120,35,283,-,50,-,565,36,767,684,344,489,565,-,-,103,810,463,733,665,494,644,863,25,385,-,342,470,-,-,-,730,582,468 11 | -,578,621,962,503,305,42,-,-,50,-,155,519,-,-,256,990,801,154,53,474,650,402,-,-,-,966,-,-,406,989,772,932,7,-,823,391,-,-,933 12 | -,363,264,468,944,302,-,106,172,-,155,-,-,-,380,438,-,41,266,-,-,104,867,609,-,270,861,-,-,165,-,675,250,686,995,366,191,-,433,- 13 | 870,940,81,893,-,926,134,385,-,565,519,-,-,313,851,-,-,-,248,220,-,826,359,829,-,234,198,145,409,68,359,-,814,218,186,-,-,929,203,- 14 | -,143,-,854,677,-,219,652,663,36,-,-,313,-,132,-,433,598,-,-,168,870,-,-,-,128,437,-,383,364,966,227,-,-,807,993,-,-,526,17 15 | 869,-,402,718,-,-,457,160,236,767,-,380,851,132,-,-,596,903,613,730,-,261,-,142,379,885,89,-,848,258,112,-,900,-,-,818,639,268,600,- 16 | 624,162,813,427,727,582,639,-,36,684,256,438,-,-,-,-,539,379,664,561,542,-,999,585,-,-,321,398,-,-,950,68,193,-,697,-,390,588,848,- 17 | 300,122,649,448,793,-,538,890,403,344,990,-,-,433,596,539,-,-,73,-,318,-,-,500,-,968,-,291,-,-,765,196,504,757,-,542,-,395,227,148 18 | 609,910,386,916,457,861,374,812,286,489,801,41,-,598,903,379,-,-,-,946,136,399,-,941,707,156,757,258,251,-,807,-,-,-,461,501,-,-,616,- 19 | 131,-,252,258,981,-,-,605,986,565,154,266,248,-,613,664,73,-,-,686,-,-,575,627,817,282,-,698,398,222,-,649,-,-,-,-,-,654,-,- 20 | -,729,391,-,191,683,-,953,-,-,53,-,220,-,730,561,-,946,686,-,-,389,729,553,304,703,455,857,260,-,991,182,351,477,867,-,-,889,217,853 21 | 251,802,264,760,-,293,-,-,-,-,474,-,-,168,-,542,318,136,-,-,-,-,392,-,-,-,267,407,27,651,80,927,-,974,977,-,-,457,117,- 22 | -,941,637,909,-,-,966,-,810,103,650,104,826,870,261,-,-,399,-,389,-,-,-,202,-,-,-,-,867,140,403,962,785,-,511,-,1,-,707,- 23 | -,922,349,529,-,-,-,-,761,810,402,867,359,-,-,999,-,-,575,729,392,-,-,388,939,-,959,-,83,463,361,-,-,512,931,-,224,690,369,- 24 | -,573,-,311,351,66,-,79,574,463,-,609,829,-,142,585,500,941,627,553,-,202,388,-,164,829,-,620,523,639,936,-,-,490,-,695,-,505,109,- 25 | 856,531,-,404,969,-,-,-,53,733,-,-,-,-,379,-,-,707,817,304,-,-,939,164,-,-,616,716,728,-,889,349,-,963,150,447,-,292,586,264 26 | 221,539,-,-,925,27,-,712,793,665,-,270,234,128,885,-,968,156,282,703,-,-,-,829,-,-,-,822,-,-,-,736,576,-,697,946,443,-,205,194 27 | 514,667,108,-,987,-,-,613,-,494,966,861,198,437,89,321,-,757,-,455,267,-,959,-,616,-,-,-,349,156,339,-,102,790,359,-,439,938,809,260 28 | -,607,-,588,328,-,449,312,-,644,-,-,145,-,-,398,291,258,698,857,407,-,-,620,716,822,-,-,293,486,943,-,779,-,6,880,116,775,-,947 29 | 591,-,727,680,282,290,120,452,777,863,-,-,409,383,848,-,-,251,398,260,27,867,83,523,728,-,349,293,-,212,684,505,341,384,9,992,507,48,-,- 30 | 762,920,225,875,589,-,797,-,330,25,406,165,68,364,258,-,-,-,222,-,651,140,463,639,-,-,156,486,212,-,-,349,723,-,-,186,-,36,240,752 31 | 182,-,578,-,-,786,358,978,936,385,989,-,359,966,112,950,765,807,-,991,80,403,361,936,889,-,339,943,684,-,-,965,302,676,725,-,327,134,-,147 32 | 56,-,699,615,873,-,232,900,883,-,772,675,-,227,-,68,196,-,649,182,927,962,-,-,349,736,-,-,505,349,965,-,474,178,833,-,-,555,853,- 33 | -,315,-,-,477,554,550,-,286,342,932,250,814,-,900,193,504,-,-,351,-,785,-,-,-,576,102,779,341,723,302,474,-,689,-,-,-,451,-,- 34 | 884,649,898,409,-,817,-,901,-,470,7,686,218,-,-,-,757,-,-,477,974,-,512,490,963,-,790,-,384,-,676,178,689,-,245,596,445,-,-,343 35 | 412,937,294,758,-,33,305,-,174,-,-,995,186,807,-,697,-,461,-,867,977,511,931,-,150,697,359,6,9,-,725,833,-,245,-,949,-,270,-,112 36 | 273,-,-,221,19,-,997,-,-,-,823,366,-,993,818,-,542,501,-,-,-,-,-,695,447,946,-,880,992,186,-,-,-,596,949,-,91,-,768,273 37 | 636,185,575,-,450,54,662,225,-,-,391,191,-,-,639,390,-,-,-,-,-,1,224,-,-,443,439,116,507,-,327,-,-,445,-,91,-,248,-,344 38 | -,102,168,-,-,506,744,533,-,730,-,-,929,-,268,588,395,-,654,889,457,-,690,505,292,-,938,775,48,36,134,555,451,-,270,-,248,-,371,680 39 | -,636,432,76,-,386,686,770,828,582,-,433,203,526,600,848,227,616,-,217,117,707,369,109,586,205,809,-,-,240,-,853,-,-,-,768,-,371,-,540 40 | 774,289,833,257,-,381,239,722,711,468,933,-,-,17,-,-,148,-,-,853,-,-,-,-,264,194,260,947,-,752,147,-,-,343,112,273,344,680,540,- -------------------------------------------------------------------------------- /network.txt: -------------------------------------------------------------------------------- 1 | -,-,-,427,668,495,377,678,-,177,-,-,870,-,869,624,300,609,131,-,251,-,-,-,856,221,514,-,591,762,182,56,-,884,412,273,636,-,-,774 2 | -,-,262,-,-,508,472,799,-,956,578,363,940,143,-,162,122,910,-,729,802,941,922,573,531,539,667,607,-,920,-,-,315,649,937,-,185,102,636,289 3 | -,262,-,-,926,-,958,158,647,47,621,264,81,-,402,813,649,386,252,391,264,637,349,-,-,-,108,-,727,225,578,699,-,898,294,-,575,168,432,833 4 | 427,-,-,-,366,-,-,635,-,32,962,468,893,854,718,427,448,916,258,-,760,909,529,311,404,-,-,588,680,875,-,615,-,409,758,221,-,-,76,257 5 | 668,-,926,366,-,-,-,250,268,-,503,944,-,677,-,727,793,457,981,191,-,-,-,351,969,925,987,328,282,589,-,873,477,-,-,19,450,-,-,- 6 | 495,508,-,-,-,-,-,765,711,819,305,302,926,-,-,582,-,861,-,683,293,-,-,66,-,27,-,-,290,-,786,-,554,817,33,-,54,506,386,381 7 | 377,472,958,-,-,-,-,-,-,120,42,-,134,219,457,639,538,374,-,-,-,966,-,-,-,-,-,449,120,797,358,232,550,-,305,997,662,744,686,239 8 | 678,799,158,635,250,765,-,-,-,35,-,106,385,652,160,-,890,812,605,953,-,-,-,79,-,712,613,312,452,-,978,900,-,901,-,-,225,533,770,722 9 | -,-,647,-,268,711,-,-,-,283,-,172,-,663,236,36,403,286,986,-,-,810,761,574,53,793,-,-,777,330,936,883,286,-,174,-,-,-,828,711 10 | 177,956,47,32,-,819,120,35,283,-,50,-,565,36,767,684,344,489,565,-,-,103,810,463,733,665,494,644,863,25,385,-,342,470,-,-,-,730,582,468 11 | -,578,621,962,503,305,42,-,-,50,-,155,519,-,-,256,990,801,154,53,474,650,402,-,-,-,966,-,-,406,989,772,932,7,-,823,391,-,-,933 12 | -,363,264,468,944,302,-,106,172,-,155,-,-,-,380,438,-,41,266,-,-,104,867,609,-,270,861,-,-,165,-,675,250,686,995,366,191,-,433,- 13 | 870,940,81,893,-,926,134,385,-,565,519,-,-,313,851,-,-,-,248,220,-,826,359,829,-,234,198,145,409,68,359,-,814,218,186,-,-,929,203,- 14 | -,143,-,854,677,-,219,652,663,36,-,-,313,-,132,-,433,598,-,-,168,870,-,-,-,128,437,-,383,364,966,227,-,-,807,993,-,-,526,17 15 | 869,-,402,718,-,-,457,160,236,767,-,380,851,132,-,-,596,903,613,730,-,261,-,142,379,885,89,-,848,258,112,-,900,-,-,818,639,268,600,- 16 | 624,162,813,427,727,582,639,-,36,684,256,438,-,-,-,-,539,379,664,561,542,-,999,585,-,-,321,398,-,-,950,68,193,-,697,-,390,588,848,- 17 | 300,122,649,448,793,-,538,890,403,344,990,-,-,433,596,539,-,-,73,-,318,-,-,500,-,968,-,291,-,-,765,196,504,757,-,542,-,395,227,148 18 | 609,910,386,916,457,861,374,812,286,489,801,41,-,598,903,379,-,-,-,946,136,399,-,941,707,156,757,258,251,-,807,-,-,-,461,501,-,-,616,- 19 | 131,-,252,258,981,-,-,605,986,565,154,266,248,-,613,664,73,-,-,686,-,-,575,627,817,282,-,698,398,222,-,649,-,-,-,-,-,654,-,- 20 | -,729,391,-,191,683,-,953,-,-,53,-,220,-,730,561,-,946,686,-,-,389,729,553,304,703,455,857,260,-,991,182,351,477,867,-,-,889,217,853 21 | 251,802,264,760,-,293,-,-,-,-,474,-,-,168,-,542,318,136,-,-,-,-,392,-,-,-,267,407,27,651,80,927,-,974,977,-,-,457,117,- 22 | -,941,637,909,-,-,966,-,810,103,650,104,826,870,261,-,-,399,-,389,-,-,-,202,-,-,-,-,867,140,403,962,785,-,511,-,1,-,707,- 23 | -,922,349,529,-,-,-,-,761,810,402,867,359,-,-,999,-,-,575,729,392,-,-,388,939,-,959,-,83,463,361,-,-,512,931,-,224,690,369,- 24 | -,573,-,311,351,66,-,79,574,463,-,609,829,-,142,585,500,941,627,553,-,202,388,-,164,829,-,620,523,639,936,-,-,490,-,695,-,505,109,- 25 | 856,531,-,404,969,-,-,-,53,733,-,-,-,-,379,-,-,707,817,304,-,-,939,164,-,-,616,716,728,-,889,349,-,963,150,447,-,292,586,264 26 | 221,539,-,-,925,27,-,712,793,665,-,270,234,128,885,-,968,156,282,703,-,-,-,829,-,-,-,822,-,-,-,736,576,-,697,946,443,-,205,194 27 | 514,667,108,-,987,-,-,613,-,494,966,861,198,437,89,321,-,757,-,455,267,-,959,-,616,-,-,-,349,156,339,-,102,790,359,-,439,938,809,260 28 | -,607,-,588,328,-,449,312,-,644,-,-,145,-,-,398,291,258,698,857,407,-,-,620,716,822,-,-,293,486,943,-,779,-,6,880,116,775,-,947 29 | 591,-,727,680,282,290,120,452,777,863,-,-,409,383,848,-,-,251,398,260,27,867,83,523,728,-,349,293,-,212,684,505,341,384,9,992,507,48,-,- 30 | 762,920,225,875,589,-,797,-,330,25,406,165,68,364,258,-,-,-,222,-,651,140,463,639,-,-,156,486,212,-,-,349,723,-,-,186,-,36,240,752 31 | 182,-,578,-,-,786,358,978,936,385,989,-,359,966,112,950,765,807,-,991,80,403,361,936,889,-,339,943,684,-,-,965,302,676,725,-,327,134,-,147 32 | 56,-,699,615,873,-,232,900,883,-,772,675,-,227,-,68,196,-,649,182,927,962,-,-,349,736,-,-,505,349,965,-,474,178,833,-,-,555,853,- 33 | -,315,-,-,477,554,550,-,286,342,932,250,814,-,900,193,504,-,-,351,-,785,-,-,-,576,102,779,341,723,302,474,-,689,-,-,-,451,-,- 34 | 884,649,898,409,-,817,-,901,-,470,7,686,218,-,-,-,757,-,-,477,974,-,512,490,963,-,790,-,384,-,676,178,689,-,245,596,445,-,-,343 35 | 412,937,294,758,-,33,305,-,174,-,-,995,186,807,-,697,-,461,-,867,977,511,931,-,150,697,359,6,9,-,725,833,-,245,-,949,-,270,-,112 36 | 273,-,-,221,19,-,997,-,-,-,823,366,-,993,818,-,542,501,-,-,-,-,-,695,447,946,-,880,992,186,-,-,-,596,949,-,91,-,768,273 37 | 636,185,575,-,450,54,662,225,-,-,391,191,-,-,639,390,-,-,-,-,-,1,224,-,-,443,439,116,507,-,327,-,-,445,-,91,-,248,-,344 38 | -,102,168,-,-,506,744,533,-,730,-,-,929,-,268,588,395,-,654,889,457,-,690,505,292,-,938,775,48,36,134,555,451,-,270,-,248,-,371,680 39 | -,636,432,76,-,386,686,770,828,582,-,433,203,526,600,848,227,616,-,217,117,707,369,109,586,205,809,-,-,240,-,853,-,-,-,768,-,371,-,540 40 | 774,289,833,257,-,381,239,722,711,468,933,-,-,17,-,-,148,-,-,853,-,-,-,-,264,194,260,947,-,752,147,-,-,343,112,273,344,680,540,- 41 | -------------------------------------------------------------------------------- /145.py: -------------------------------------------------------------------------------- 1 | def isreversible(n): 2 | if n%10: 3 | s = n + int(str(n)[::-1]) 4 | return all(i%2 for i in (map(int, str(s)))) 5 | else: 6 | return False 7 | 8 | 9 | def nreversible(d): 10 | ''' 11 | # of reversible numbers with n digits 12 | ''' 13 | n, r = divmod(d, 4) 14 | if r == 0 or r == 2: 15 | n = d // 2 16 | return 20*(30**(n-1)) # 2n digit solutions (4n+0 or 4n+2) 17 | elif r == 1: 18 | return 0 # no 4n+1 digits solutions 19 | else: 20 | return 5*20*((25*20)**n) # 4n+3 digits solutions 21 | 22 | for i in range(1,10): 23 | print i, nreversible(i) 24 | 25 | 26 | ''' 27 | print sum(isreversible(i) for i in range(10**6,10**7)) 28 | 29 | for i in range(100000,1000000,12): 30 | if isreversible(i): 31 | print i, int(str(i)[::-1]) 32 | ''' 33 | 34 | ''' 35 | A good explanation by unknonw commenter: 36 | 37 | I used only pencil and paper this time, and I must admit that this problem is 38 | very interesting. 39 | 40 | Essentially I followed the reasoning that smq explained in the third post, but 41 | without thinking to the general solution as he did after the brute force, but 42 | instead trying all possible (and valid) combinations of digit sums. 43 | 44 | If one plots all the possible digit sums, you understand that: 45 | * there are 25 couples of digits that have an even sum and bring no carry 46 | * there are 25 couples of digits that have an even sum and bring a carry to 47 | * the next sum there are 30 couples of digits with odd sum and no carry (10 of 48 | * them include the 0, that sometimes we have to drop) the remaining 20 couples 49 | * give a odd sum with carry 50 | 51 | Furthermore, as we're adding only two numbers, the carry between a column and 52 | the previous one can only be 1 or be absent. So, if we want to obtain a odd 53 | sum, we need a odd sum if the incoming carry is zero, or a even sum if the 54 | incoming carry is one. 55 | 56 | In the following paragraphs, lines starting with * are almost evident 57 | hypothesis. Assumptions follow the hypothesis. 58 | 59 | Reasoning on 4-digit numbers (abcd+dcba): 60 | * a+d is always odd and b+c must never give a carry 61 | If a+d gives a carry, then b+c should be even with a carry to the next sum. 62 | This case is contrast with the hypothesis and must be discarded. If a+d does 63 | not give a carry, b+c is odd with no carry. -> So there are 20*30=600 64 | solutions with 4 digits (I'm using 20 as first factor as a and d cannot be 65 | zero). 66 | 67 | Reasoning on 5-digit numbers (abcde+edcba): 68 | * a+e is always odd and b+d must never give a carry. c+c is obviously always 69 | * even. So, we need a carry from b+d to guarantee that c+c+ is odd, but 70 | * this is in contrast with the previous hypothesis. 71 | -> No solutions. 72 | 73 | Reasoning on 6-digit numbers (abcdef+fedcba): 74 | * a+f is always odd and b+e must never give a carry 75 | If a+f gives a carry, then b+e must be even. This means also that c+d must 76 | give a carry, as we need a odd sum in the second column from the left. In this 77 | case c+d should be both even (to make a odd sum in the third column) and odd 78 | (to make a odd sum in the fourth column). Contrast, so wrong assumption. If 79 | a+f does not give a carry, then b+e is odd. This implies that c+d has no carry 80 | and, furthermore, that this sum is odd. -> So there are 20*30*30=18000 81 | solutions with 6 digits 82 | 83 | Reasoning on 7-digit numbers (abcdefg+gfedcba): 84 | * a+g is always odd and b+f must never give a carry. d+d is obviously always 85 | * even. 86 | If a+g gives a carry, then b+f is even. This implies that c+e gives a carry. 87 | c+e must also be odd, as we need a odd sum in the fifth column from left. This 88 | implies also that d+d must not give a carry (as we need a odd result in the 89 | third column). If a+g does not give a carry, then b+f must be odd. This 90 | means that c+e must not give a carry (as we need a odd sum in the second 91 | column). But, in this case, there is no possibility to obtain a odd sum in 92 | the middle column (as d+d is even and there is no carry available). Wrong 93 | assumption. -> So there are 20*25*20*5=50000 solutions with 7 digits 94 | 95 | Reasoning on 8-digit numbers (abcdefgh+hgfedcba): 96 | * a+h is always odd and b+g must never give a carry. 97 | If a+h gives a carry, b+g is even. Then, c+f must be odd (see the sixth 98 | column) and give a carry (second column). d+e must not give a carry, as we 99 | already have an odd sum in the third column. If d+e is even, in the fourth 100 | column we have an even sum (d+e+). If d+e is odd, in the fifth 101 | column we have an even sum (d+e+). So again we're stuck. If 102 | a+h does not give a carry, b+g is odd. f+c, then is odd too (sixth column) and 103 | gives no carry (see second column). This is good as now we need d+e odd and 104 | with no carry to complete the puzzle. -> So there are 20*30*30*30=540000 105 | solutions with 8 digits 106 | 107 | This is a long (read: confused :) ) explanation but now I'm happy of having 108 | written it :) 109 | 110 | ''' 111 | -------------------------------------------------------------------------------- /013.py: -------------------------------------------------------------------------------- 1 | s = '''\ 2 | 37107287533902102798797998220837590246510135740250 3 | 46376937677490009712648124896970078050417018260538 4 | 74324986199524741059474233309513058123726617309629 5 | 91942213363574161572522430563301811072406154908250 6 | 23067588207539346171171980310421047513778063246676 7 | 89261670696623633820136378418383684178734361726757 8 | 28112879812849979408065481931592621691275889832738 9 | 44274228917432520321923589422876796487670272189318 10 | 47451445736001306439091167216856844588711603153276 11 | 70386486105843025439939619828917593665686757934951 12 | 62176457141856560629502157223196586755079324193331 13 | 64906352462741904929101432445813822663347944758178 14 | 92575867718337217661963751590579239728245598838407 15 | 58203565325359399008402633568948830189458628227828 16 | 80181199384826282014278194139940567587151170094390 17 | 35398664372827112653829987240784473053190104293586 18 | 86515506006295864861532075273371959191420517255829 19 | 71693888707715466499115593487603532921714970056938 20 | 54370070576826684624621495650076471787294438377604 21 | 53282654108756828443191190634694037855217779295145 22 | 36123272525000296071075082563815656710885258350721 23 | 45876576172410976447339110607218265236877223636045 24 | 17423706905851860660448207621209813287860733969412 25 | 81142660418086830619328460811191061556940512689692 26 | 51934325451728388641918047049293215058642563049483 27 | 62467221648435076201727918039944693004732956340691 28 | 15732444386908125794514089057706229429197107928209 29 | 55037687525678773091862540744969844508330393682126 30 | 18336384825330154686196124348767681297534375946515 31 | 80386287592878490201521685554828717201219257766954 32 | 78182833757993103614740356856449095527097864797581 33 | 16726320100436897842553539920931837441497806860984 34 | 48403098129077791799088218795327364475675590848030 35 | 87086987551392711854517078544161852424320693150332 36 | 59959406895756536782107074926966537676326235447210 37 | 69793950679652694742597709739166693763042633987085 38 | 41052684708299085211399427365734116182760315001271 39 | 65378607361501080857009149939512557028198746004375 40 | 35829035317434717326932123578154982629742552737307 41 | 94953759765105305946966067683156574377167401875275 42 | 88902802571733229619176668713819931811048770190271 43 | 25267680276078003013678680992525463401061632866526 44 | 36270218540497705585629946580636237993140746255962 45 | 24074486908231174977792365466257246923322810917141 46 | 91430288197103288597806669760892938638285025333403 47 | 34413065578016127815921815005561868836468420090470 48 | 23053081172816430487623791969842487255036638784583 49 | 11487696932154902810424020138335124462181441773470 50 | 63783299490636259666498587618221225225512486764533 51 | 67720186971698544312419572409913959008952310058822 52 | 95548255300263520781532296796249481641953868218774 53 | 76085327132285723110424803456124867697064507995236 54 | 37774242535411291684276865538926205024910326572967 55 | 23701913275725675285653248258265463092207058596522 56 | 29798860272258331913126375147341994889534765745501 57 | 18495701454879288984856827726077713721403798879715 58 | 38298203783031473527721580348144513491373226651381 59 | 34829543829199918180278916522431027392251122869539 60 | 40957953066405232632538044100059654939159879593635 61 | 29746152185502371307642255121183693803580388584903 62 | 41698116222072977186158236678424689157993532961922 63 | 62467957194401269043877107275048102390895523597457 64 | 23189706772547915061505504953922979530901129967519 65 | 86188088225875314529584099251203829009407770775672 66 | 11306739708304724483816533873502340845647058077308 67 | 82959174767140363198008187129011875491310547126581 68 | 97623331044818386269515456334926366572897563400500 69 | 42846280183517070527831839425882145521227251250327 70 | 55121603546981200581762165212827652751691296897789 71 | 32238195734329339946437501907836945765883352399886 72 | 75506164965184775180738168837861091527357929701337 73 | 62177842752192623401942399639168044983993173312731 74 | 32924185707147349566916674687634660915035914677504 75 | 99518671430235219628894890102423325116913619626622 76 | 73267460800591547471830798392868535206946944540724 77 | 76841822524674417161514036427982273348055556214818 78 | 97142617910342598647204516893989422179826088076852 79 | 87783646182799346313767754307809363333018982642090 80 | 10848802521674670883215120185883543223812876952786 81 | 71329612474782464538636993009049310363619763878039 82 | 62184073572399794223406235393808339651327408011116 83 | 66627891981488087797941876876144230030984490851411 84 | 60661826293682836764744779239180335110989069790714 85 | 85786944089552990653640447425576083659976645795096 86 | 66024396409905389607120198219976047599490197230297 87 | 64913982680032973156037120041377903785566085089252 88 | 16730939319872750275468906903707539413042652315011 89 | 94809377245048795150954100921645863754710598436791 90 | 78639167021187492431995700641917969777599028300699 91 | 15368713711936614952811305876380278410754449733078 92 | 40789923115535562561142322423255033685442488917353 93 | 44889911501440648020369068063960672322193204149535 94 | 41503128880339536053299340368006977710650566631954 95 | 81234880673210146739058568557934581403627822703280 96 | 82616570773948327592232845941706525094512325230608 97 | 22918802058777319719839450180888072429661980811197 98 | 77158542502016545090413245809786882778948721859617 99 | 72107838435069186155435662884062257473692284509516 100 | 20849603980134001723930671666823555245252804609722 101 | 53503534226472524250874054075591789781264330331690\ 102 | ''' 103 | 104 | print str(sum(int(line) for line in s.split()))[:10] 105 | -------------------------------------------------------------------------------- /log.log: -------------------------------------------------------------------------------- 1 | (-1, 0) -> (0, 0) 2 | (0, 0) -> (0, 1) 3 | (0, 1) -> (0, 2) 4 | (0, 2) -> (1, 2) 5 | (1, 2) -> (2, 2) 6 | (1, 2) -> (1, 1) 7 | (1, 1) -> (1, 0) 8 | (1, 0) -> (0, 0) 9 | (0, 0) -> (0, 1) 10 | (0, 1) -> (0, 2) 11 | (0, 2) -> (1, 2) 12 | (1, 2) -> (1, 1) 13 | (1, 1) -> (1, 0) 14 | (1, 0) -> (0, 0) 15 | (0, 0) -> (0, 1) 16 | (0, 1) -> (0, 2) 17 | (0, 2) -> (1, 2) 18 | (1, 2) -> (1, 1) 19 | (1, 1) -> (1, 0) 20 | (1, 0) -> (0, 0) 21 | (0, 0) -> (0, 1) 22 | (0, 1) -> (0, 2) 23 | (0, 2) -> (1, 2) 24 | (1, 2) -> (1, 1) 25 | (1, 1) -> (1, 0) 26 | (1, 0) -> (0, 0) 27 | (0, 0) -> (0, 1) 28 | (0, 1) -> (0, 2) 29 | (0, 2) -> (1, 2) 30 | (1, 2) -> (1, 1) 31 | (1, 1) -> (1, 0) 32 | (1, 0) -> (0, 0) 33 | (0, 0) -> (0, 1) 34 | (0, 1) -> (0, 2) 35 | (0, 2) -> (1, 2) 36 | (1, 2) -> (1, 1) 37 | (1, 1) -> (1, 0) 38 | (1, 0) -> (0, 0) 39 | (0, 0) -> (0, 1) 40 | (0, 1) -> (0, 2) 41 | (0, 2) -> (1, 2) 42 | (1, 2) -> (1, 1) 43 | (1, 1) -> (1, 0) 44 | (1, 0) -> (0, 0) 45 | (0, 0) -> (0, 1) 46 | (0, 1) -> (0, 2) 47 | (0, 2) -> (1, 2) 48 | (1, 2) -> (1, 1) 49 | (1, 1) -> (1, 0) 50 | (1, 0) -> (0, 0) 51 | (0, 0) -> (0, 1) 52 | (0, 1) -> (0, 2) 53 | (0, 2) -> (1, 2) 54 | (1, 2) -> (1, 1) 55 | (1, 1) -> (1, 0) 56 | (1, 0) -> (0, 0) 57 | (0, 0) -> (0, 1) 58 | (0, 1) -> (0, 2) 59 | (0, 2) -> (1, 2) 60 | (1, 2) -> (1, 1) 61 | (1, 1) -> (1, 0) 62 | (1, 0) -> (0, 0) 63 | (0, 0) -> (0, 1) 64 | (0, 1) -> (0, 2) 65 | (0, 2) -> (1, 2) 66 | (1, 2) -> (1, 1) 67 | (1, 1) -> (1, 0) 68 | (1, 0) -> (0, 0) 69 | (0, 0) -> (0, 1) 70 | (0, 1) -> (0, 2) 71 | (0, 2) -> (1, 2) 72 | (1, 2) -> (1, 1) 73 | (1, 1) -> (1, 0) 74 | (1, 0) -> (0, 0) 75 | (0, 0) -> (0, 1) 76 | (0, 1) -> (0, 2) 77 | (0, 2) -> (1, 2) 78 | (1, 2) -> (1, 1) 79 | (1, 1) -> (1, 0) 80 | (1, 0) -> (0, 0) 81 | (0, 0) -> (0, 1) 82 | (0, 1) -> (0, 2) 83 | (0, 2) -> (1, 2) 84 | (1, 2) -> (1, 1) 85 | (1, 1) -> (1, 0) 86 | (1, 0) -> (0, 0) 87 | (0, 0) -> (0, 1) 88 | (0, 1) -> (0, 2) 89 | (0, 2) -> (1, 2) 90 | (1, 2) -> (1, 1) 91 | (1, 1) -> (1, 0) 92 | (1, 0) -> (0, 0) 93 | (0, 0) -> (0, 1) 94 | (0, 1) -> (0, 2) 95 | (0, 2) -> (1, 2) 96 | (1, 2) -> (1, 1) 97 | (1, 1) -> (1, 0) 98 | (1, 0) -> (0, 0) 99 | (0, 0) -> (0, 1) 100 | (0, 1) -> (0, 2) 101 | (0, 2) -> (1, 2) 102 | (1, 2) -> (1, 1) 103 | (1, 1) -> (1, 0) 104 | (1, 0) -> (0, 0) 105 | (0, 0) -> (0, 1) 106 | (0, 1) -> (0, 2) 107 | (0, 2) -> (1, 2) 108 | (1, 2) -> (1, 1) 109 | (1, 1) -> (1, 0) 110 | (1, 0) -> (0, 0) 111 | (0, 0) -> (0, 1) 112 | (0, 1) -> (0, 2) 113 | (0, 2) -> (1, 2) 114 | (1, 2) -> (1, 1) 115 | (1, 1) -> (1, 0) 116 | (1, 0) -> (0, 0) 117 | (0, 0) -> (0, 1) 118 | (0, 1) -> (0, 2) 119 | (0, 2) -> (1, 2) 120 | (1, 2) -> (1, 1) 121 | (1, 1) -> (1, 0) 122 | (1, 0) -> (0, 0) 123 | (0, 0) -> (0, 1) 124 | (0, 1) -> (0, 2) 125 | (0, 2) -> (1, 2) 126 | (1, 2) -> (1, 1) 127 | (1, 1) -> (1, 0) 128 | (1, 0) -> (0, 0) 129 | (0, 0) -> (0, 1) 130 | (0, 1) -> (0, 2) 131 | (0, 2) -> (1, 2) 132 | (1, 2) -> (1, 1) 133 | (1, 1) -> (1, 0) 134 | (1, 0) -> (0, 0) 135 | (0, 0) -> (0, 1) 136 | (0, 1) -> (0, 2) 137 | (0, 2) -> (1, 2) 138 | (1, 2) -> (1, 1) 139 | (1, 1) -> (1, 0) 140 | (1, 0) -> (0, 0) 141 | (0, 0) -> (0, 1) 142 | (0, 1) -> (0, 2) 143 | (0, 2) -> (1, 2) 144 | (1, 2) -> (1, 1) 145 | (1, 1) -> (1, 0) 146 | (1, 0) -> (0, 0) 147 | (0, 0) -> (0, 1) 148 | (0, 1) -> (0, 2) 149 | (0, 2) -> (1, 2) 150 | (1, 2) -> (1, 1) 151 | (1, 1) -> (1, 0) 152 | (1, 0) -> (0, 0) 153 | (0, 0) -> (0, 1) 154 | (0, 1) -> (0, 2) 155 | (0, 2) -> (1, 2) 156 | (1, 2) -> (1, 1) 157 | (1, 1) -> (1, 0) 158 | (1, 0) -> (0, 0) 159 | (0, 0) -> (0, 1) 160 | (0, 1) -> (0, 2) 161 | (0, 2) -> (1, 2) 162 | (1, 2) -> (1, 1) 163 | (1, 1) -> (1, 0) 164 | (1, 0) -> (0, 0) 165 | (0, 0) -> (0, 1) 166 | (0, 1) -> (0, 2) 167 | (0, 2) -> (1, 2) 168 | (1, 2) -> (1, 1) 169 | (1, 1) -> (1, 0) 170 | (1, 0) -> (0, 0) 171 | (0, 0) -> (0, 1) 172 | (0, 1) -> (0, 2) 173 | (0, 2) -> (1, 2) 174 | (1, 2) -> (1, 1) 175 | (1, 1) -> (1, 0) 176 | (1, 0) -> (0, 0) 177 | (0, 0) -> (0, 1) 178 | (0, 1) -> (0, 2) 179 | (0, 2) -> (1, 2) 180 | (1, 2) -> (1, 1) 181 | (1, 1) -> (1, 0) 182 | (1, 0) -> (0, 0) 183 | (0, 0) -> (0, 1) 184 | (0, 1) -> (0, 2) 185 | (0, 2) -> (1, 2) 186 | (1, 2) -> (1, 1) 187 | (1, 1) -> (1, 0) 188 | (1, 0) -> (0, 0) 189 | (0, 0) -> (0, 1) 190 | (0, 1) -> (0, 2) 191 | (0, 2) -> (1, 2) 192 | (1, 2) -> (1, 1) 193 | (1, 1) -> (1, 0) 194 | (1, 0) -> (0, 0) 195 | (0, 0) -> (0, 1) 196 | (0, 1) -> (0, 2) 197 | (0, 2) -> (1, 2) 198 | (1, 2) -> (1, 1) 199 | (1, 1) -> (1, 0) 200 | (1, 0) -> (0, 0) 201 | (0, 0) -> (0, 1) 202 | (0, 1) -> (0, 2) 203 | (0, 2) -> (1, 2) 204 | (1, 2) -> (1, 1) 205 | (1, 1) -> (1, 0) 206 | (1, 0) -> (0, 0) 207 | (0, 0) -> (0, 1) 208 | (0, 1) -> (0, 2) 209 | (0, 2) -> (1, 2) 210 | (1, 2) -> (1, 1) 211 | (1, 1) -> (1, 0) 212 | (1, 0) -> (0, 0) 213 | (0, 0) -> (0, 1) 214 | (0, 1) -> (0, 2) 215 | (0, 2) -> (1, 2) 216 | (1, 2) -> (1, 1) 217 | (1, 1) -> (1, 0) 218 | (1, 0) -> (0, 0) 219 | (0, 0) -> (0, 1) 220 | (0, 1) -> (0, 2) 221 | (0, 2) -> (1, 2) 222 | (1, 2) -> (1, 1) 223 | (1, 1) -> (1, 0) 224 | (1, 0) -> (0, 0) 225 | (0, 0) -> (0, 1) 226 | (0, 1) -> (0, 2) 227 | (0, 2) -> (1, 2) 228 | (1, 2) -> (1, 1) 229 | (1, 1) -> (1, 0) 230 | (1, 0) -> (0, 0) 231 | (0, 0) -> (0, 1) 232 | (0, 1) -> (0, 2) 233 | (0, 2) -> (1, 2) 234 | (1, 2) -> (1, 1) 235 | (1, 1) -> (1, 0) 236 | (1, 0) -> (0, 0) 237 | (0, 0) -> (0, 1) 238 | (0, 1) -> (0, 2) 239 | (0, 2) -> (1, 2) 240 | (1, 2) -> (1, 1) 241 | (1, 1) -> (1, 0) 242 | (1, 0) -> (0, 0) 243 | (0, 0) -> (0, 1) 244 | (0, 1) -> (0, 2) 245 | (0, 2) -> (1, 2) 246 | (1, 2) -> (1, 1) 247 | (1, 1) -> (1, 0) 248 | (1, 0) -> (0, 0) 249 | (0, 0) -> (0, 1) 250 | (0, 1) -> (0, 2) 251 | (0, 2) -> (1, 2) 252 | (1, 2) -> (1, 1) 253 | (1, 1) -> (1, 0) 254 | (1, 0) -> (0, 0) 255 | (0, 0) -> (0, 1) 256 | (0, 1) -> (0, 2) 257 | (0, 2) -> (1, 2) 258 | (1, 2) -> (1, 1) 259 | (1, 1) -> (1, 0) 260 | (1, 0) -> (0, 0) 261 | (0, 0) -> (0, 1) 262 | (0, 1) -> (0, 2) 263 | (0, 2) -> (1, 2) 264 | (1, 2) -> (1, 1) 265 | (1, 1) -> (1, 0) 266 | (1, 0) -> (0, 0) 267 | (0, 0) -> (0, 1) 268 | (0, 1) -> (0, 2) 269 | (0, 2) -> (1, 2) 270 | (1, 2) -> (1, 1) 271 | (1, 1) -> (1, 0) 272 | (1, 0) -> (0, 0) 273 | (0, 0) -> (0, 1) 274 | (0, 1) -> (0, 2) 275 | (0, 2) -> (1, 2) 276 | (1, 2) -> (1, 1) 277 | (1, 1) -> (1, 0) 278 | (1, 0) -> (0, 0) 279 | (0, 0) -> (0, 1) 280 | (0, 1) -> (0, 2) 281 | (0, 2) -> (1, 2) 282 | (1, 2) -> (1, 1) 283 | (1, 1) -> (1, 0) 284 | (1, 0) -> (0, 0) 285 | (0, 0) -> (0, 1) 286 | (0, 1) -> (0, 2) 287 | (0, 2) -> (1, 2) 288 | (1, 2) -> (1, 1) 289 | (1, 1) -> (1, 0) 290 | (1, 0) -> (0, 0) 291 | (0, 0) -> (0, 1) 292 | (0, 1) -> (0, 2) 293 | (0, 2) -> (1, 2) 294 | (1, 2) -> (1, 1) 295 | (1, 1) -> (1, 0) 296 | (1, 0) -> (0, 0) 297 | (0, 0) -> (0, 1) 298 | (0, 1) -> (0, 2) 299 | (0, 2) -> (1, 2) 300 | (1, 2) -> (1, 1) 301 | (1, 1) -> (1, 0) 302 | (1, 0) -> (0, 0) 303 | (0, 0) -> (0, 1) 304 | (0, 1) -> (0, 2) 305 | (0, 2) -> (1, 2) 306 | (1, 2) -> (1, 1) 307 | (1, 1) -> (1, 0) 308 | (1, 0) -> (0, 0) 309 | (0, 0) -> (0, 1) 310 | (0, 1) -> (0, 2) 311 | (0, 2) -> (1, 2) 312 | (1, 2) -> (1, 1) 313 | (1, 1) -> (1, 0) 314 | (1, 0) -> (0, 0) 315 | (0, 0) -> (0, 1) 316 | (0, 1) -> (0, 2) 317 | (0, 2) -> (1, 2) 318 | (1, 2) -> (1, 1) 319 | (1, 1) -> (1, 0) 320 | (1, 0) -> (0, 0) 321 | (0, 0) -> (0, 1) 322 | (0, 1) -> (0, 2) 323 | (0, 2) -> (1, 2) 324 | (1, 2) -> (1, 1) 325 | (1, 1) -> (1, 0) 326 | (1, 0) -> (0, 0) 327 | (0, 0) -> (0, 1) 328 | (0, 1) -> (0, 2) 329 | (0, 2) -> (1, 2) 330 | (1, 2) -> (1, 1) 331 | (1, 1) -> (1, 0) 332 | (1, 0) -> (0, 0) 333 | (0, 0) -> (0, 1) 334 | (0, 1) -> (0, 2) 335 | maximum recursion depth exceeded 336 | maximum recursion depth exceeded 337 | -------------------------------------------------------------------------------- /sudoku.txt: -------------------------------------------------------------------------------- 1 | Grid 01 2 | 003020600 3 | 900305001 4 | 001806400 5 | 008102900 6 | 700000008 7 | 006708200 8 | 002609500 9 | 800203009 10 | 005010300 11 | Grid 02 12 | 200080300 13 | 060070084 14 | 030500209 15 | 000105408 16 | 000000000 17 | 402706000 18 | 301007040 19 | 720040060 20 | 004010003 21 | Grid 03 22 | 000000907 23 | 000420180 24 | 000705026 25 | 100904000 26 | 050000040 27 | 000507009 28 | 920108000 29 | 034059000 30 | 507000000 31 | Grid 04 32 | 030050040 33 | 008010500 34 | 460000012 35 | 070502080 36 | 000603000 37 | 040109030 38 | 250000098 39 | 001020600 40 | 080060020 41 | Grid 05 42 | 020810740 43 | 700003100 44 | 090002805 45 | 009040087 46 | 400208003 47 | 160030200 48 | 302700060 49 | 005600008 50 | 076051090 51 | Grid 06 52 | 100920000 53 | 524010000 54 | 000000070 55 | 050008102 56 | 000000000 57 | 402700090 58 | 060000000 59 | 000030945 60 | 000071006 61 | Grid 07 62 | 043080250 63 | 600000000 64 | 000001094 65 | 900004070 66 | 000608000 67 | 010200003 68 | 820500000 69 | 000000005 70 | 034090710 71 | Grid 08 72 | 480006902 73 | 002008001 74 | 900370060 75 | 840010200 76 | 003704100 77 | 001060049 78 | 020085007 79 | 700900600 80 | 609200018 81 | Grid 09 82 | 000900002 83 | 050123400 84 | 030000160 85 | 908000000 86 | 070000090 87 | 000000205 88 | 091000050 89 | 007439020 90 | 400007000 91 | Grid 10 92 | 001900003 93 | 900700160 94 | 030005007 95 | 050000009 96 | 004302600 97 | 200000070 98 | 600100030 99 | 042007006 100 | 500006800 101 | Grid 11 102 | 000125400 103 | 008400000 104 | 420800000 105 | 030000095 106 | 060902010 107 | 510000060 108 | 000003049 109 | 000007200 110 | 001298000 111 | Grid 12 112 | 062340750 113 | 100005600 114 | 570000040 115 | 000094800 116 | 400000006 117 | 005830000 118 | 030000091 119 | 006400007 120 | 059083260 121 | Grid 13 122 | 300000000 123 | 005009000 124 | 200504000 125 | 020000700 126 | 160000058 127 | 704310600 128 | 000890100 129 | 000067080 130 | 000005437 131 | Grid 14 132 | 630000000 133 | 000500008 134 | 005674000 135 | 000020000 136 | 003401020 137 | 000000345 138 | 000007004 139 | 080300902 140 | 947100080 141 | Grid 15 142 | 000020040 143 | 008035000 144 | 000070602 145 | 031046970 146 | 200000000 147 | 000501203 148 | 049000730 149 | 000000010 150 | 800004000 151 | Grid 16 152 | 361025900 153 | 080960010 154 | 400000057 155 | 008000471 156 | 000603000 157 | 259000800 158 | 740000005 159 | 020018060 160 | 005470329 161 | Grid 17 162 | 050807020 163 | 600010090 164 | 702540006 165 | 070020301 166 | 504000908 167 | 103080070 168 | 900076205 169 | 060090003 170 | 080103040 171 | Grid 18 172 | 080005000 173 | 000003457 174 | 000070809 175 | 060400903 176 | 007010500 177 | 408007020 178 | 901020000 179 | 842300000 180 | 000100080 181 | Grid 19 182 | 003502900 183 | 000040000 184 | 106000305 185 | 900251008 186 | 070408030 187 | 800763001 188 | 308000104 189 | 000020000 190 | 005104800 191 | Grid 20 192 | 000000000 193 | 009805100 194 | 051907420 195 | 290401065 196 | 000000000 197 | 140508093 198 | 026709580 199 | 005103600 200 | 000000000 201 | Grid 21 202 | 020030090 203 | 000907000 204 | 900208005 205 | 004806500 206 | 607000208 207 | 003102900 208 | 800605007 209 | 000309000 210 | 030020050 211 | Grid 22 212 | 005000006 213 | 070009020 214 | 000500107 215 | 804150000 216 | 000803000 217 | 000092805 218 | 907006000 219 | 030400010 220 | 200000600 221 | Grid 23 222 | 040000050 223 | 001943600 224 | 009000300 225 | 600050002 226 | 103000506 227 | 800020007 228 | 005000200 229 | 002436700 230 | 030000040 231 | Grid 24 232 | 004000000 233 | 000030002 234 | 390700080 235 | 400009001 236 | 209801307 237 | 600200008 238 | 010008053 239 | 900040000 240 | 000000800 241 | Grid 25 242 | 360020089 243 | 000361000 244 | 000000000 245 | 803000602 246 | 400603007 247 | 607000108 248 | 000000000 249 | 000418000 250 | 970030014 251 | Grid 26 252 | 500400060 253 | 009000800 254 | 640020000 255 | 000001008 256 | 208000501 257 | 700500000 258 | 000090084 259 | 003000600 260 | 060003002 261 | Grid 27 262 | 007256400 263 | 400000005 264 | 010030060 265 | 000508000 266 | 008060200 267 | 000107000 268 | 030070090 269 | 200000004 270 | 006312700 271 | Grid 28 272 | 000000000 273 | 079050180 274 | 800000007 275 | 007306800 276 | 450708096 277 | 003502700 278 | 700000005 279 | 016030420 280 | 000000000 281 | Grid 29 282 | 030000080 283 | 009000500 284 | 007509200 285 | 700105008 286 | 020090030 287 | 900402001 288 | 004207100 289 | 002000800 290 | 070000090 291 | Grid 30 292 | 200170603 293 | 050000100 294 | 000006079 295 | 000040700 296 | 000801000 297 | 009050000 298 | 310400000 299 | 005000060 300 | 906037002 301 | Grid 31 302 | 000000080 303 | 800701040 304 | 040020030 305 | 374000900 306 | 000030000 307 | 005000321 308 | 010060050 309 | 050802006 310 | 080000000 311 | Grid 32 312 | 000000085 313 | 000210009 314 | 960080100 315 | 500800016 316 | 000000000 317 | 890006007 318 | 009070052 319 | 300054000 320 | 480000000 321 | Grid 33 322 | 608070502 323 | 050608070 324 | 002000300 325 | 500090006 326 | 040302050 327 | 800050003 328 | 005000200 329 | 010704090 330 | 409060701 331 | Grid 34 332 | 050010040 333 | 107000602 334 | 000905000 335 | 208030501 336 | 040070020 337 | 901080406 338 | 000401000 339 | 304000709 340 | 020060010 341 | Grid 35 342 | 053000790 343 | 009753400 344 | 100000002 345 | 090080010 346 | 000907000 347 | 080030070 348 | 500000003 349 | 007641200 350 | 061000940 351 | Grid 36 352 | 006080300 353 | 049070250 354 | 000405000 355 | 600317004 356 | 007000800 357 | 100826009 358 | 000702000 359 | 075040190 360 | 003090600 361 | Grid 37 362 | 005080700 363 | 700204005 364 | 320000084 365 | 060105040 366 | 008000500 367 | 070803010 368 | 450000091 369 | 600508007 370 | 003010600 371 | Grid 38 372 | 000900800 373 | 128006400 374 | 070800060 375 | 800430007 376 | 500000009 377 | 600079008 378 | 090004010 379 | 003600284 380 | 001007000 381 | Grid 39 382 | 000080000 383 | 270000054 384 | 095000810 385 | 009806400 386 | 020403060 387 | 006905100 388 | 017000620 389 | 460000038 390 | 000090000 391 | Grid 40 392 | 000602000 393 | 400050001 394 | 085010620 395 | 038206710 396 | 000000000 397 | 019407350 398 | 026040530 399 | 900020007 400 | 000809000 401 | Grid 41 402 | 000900002 403 | 050123400 404 | 030000160 405 | 908000000 406 | 070000090 407 | 000000205 408 | 091000050 409 | 007439020 410 | 400007000 411 | Grid 42 412 | 380000000 413 | 000400785 414 | 009020300 415 | 060090000 416 | 800302009 417 | 000040070 418 | 001070500 419 | 495006000 420 | 000000092 421 | Grid 43 422 | 000158000 423 | 002060800 424 | 030000040 425 | 027030510 426 | 000000000 427 | 046080790 428 | 050000080 429 | 004070100 430 | 000325000 431 | Grid 44 432 | 010500200 433 | 900001000 434 | 002008030 435 | 500030007 436 | 008000500 437 | 600080004 438 | 040100700 439 | 000700006 440 | 003004050 441 | Grid 45 442 | 080000040 443 | 000469000 444 | 400000007 445 | 005904600 446 | 070608030 447 | 008502100 448 | 900000005 449 | 000781000 450 | 060000010 451 | Grid 46 452 | 904200007 453 | 010000000 454 | 000706500 455 | 000800090 456 | 020904060 457 | 040002000 458 | 001607000 459 | 000000030 460 | 300005702 461 | Grid 47 462 | 000700800 463 | 006000031 464 | 040002000 465 | 024070000 466 | 010030080 467 | 000060290 468 | 000800070 469 | 860000500 470 | 002006000 471 | Grid 48 472 | 001007090 473 | 590080001 474 | 030000080 475 | 000005800 476 | 050060020 477 | 004100000 478 | 080000030 479 | 100020079 480 | 020700400 481 | Grid 49 482 | 000003017 483 | 015009008 484 | 060000000 485 | 100007000 486 | 009000200 487 | 000500004 488 | 000000020 489 | 500600340 490 | 340200000 491 | Grid 50 492 | 300200000 493 | 000107000 494 | 706030500 495 | 070009080 496 | 900020004 497 | 010800050 498 | 009040301 499 | 000702000 500 | 000008006 -------------------------------------------------------------------------------- /euler.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from copy import deepcopy 4 | def deepcopied(f): 5 | '''Deepcopy passed-in arguments to avoid side effects. ''' 6 | return lambda *k: f(*(map(deepcopy, k))) 7 | 8 | def memoized(f): 9 | '''Memoization decorator for referentially transparent function.''' 10 | m = {} # storage for key -> value pair 11 | l = lambda *k: m[k] if k in m else m.setdefault(k, f(*k)) 12 | l.cached = m 13 | return l 14 | 15 | 16 | def memoziedsequence(g): 17 | '''Decorate a generator and return a function that remembers its result. 18 | 19 | The generator produces a sequence which is cached and accessed by position. 20 | The decorated function is called to fetch cached results from previous 21 | calculation or call the generator to produce new result and cache it. 22 | ''' 23 | g, l = g(), [] 24 | def f(n): 25 | #def f(n, g=g(), l=[]): # TRICK: mutable default value 26 | d = n - len(l) # position is 0-based indexed 27 | if d >= 0: l.extend(g.next() for _ in range(d+1)) 28 | return l[n] 29 | return f 30 | 31 | from lazy import lazylist 32 | 33 | @lazylist 34 | def fibonacci(): 35 | '''Generate Fibonacci number sequentially.''' 36 | a, b = 0, 1 37 | while True: 38 | yield a 39 | a, b = b, a+b 40 | fibonacci = fibonacci() 41 | 42 | @lazylist 43 | def factorial(): 44 | '''Generate factorial number sequentially.''' 45 | a, b = 1, 1 46 | while True: 47 | yield a 48 | a, b = a*b, b+1 49 | factorial = factorial() 50 | 51 | 52 | def product(s): 53 | return reduce(lambda x,y:x*y, s, 1) 54 | 55 | def ispalindromic(s): 56 | '''Check if a sequence is palindromic. 57 | 58 | A palindromic sequence reads the same both from left and right 59 | ''' 60 | return all(s[i] == s[~i] for i in range(len(s)//2)) # ~0 == -1, ~1 == -2 61 | 62 | def pythagorean(n): 63 | '''Generate Pythagorean triplet (a, b, c). 64 | 65 | such that 66 | 1) a < b < c <= n 67 | 2) a**2 + b**2 == c**2 68 | ''' 69 | for a in range(1,n+1): 70 | for b in range(a+1, n+1): 71 | s = a**2 + b**2 72 | c = int(s**.5) 73 | if (s == c**2) and (c <= n): 74 | yield (a,b,c) 75 | 76 | 77 | @lazylist 78 | def prime(): 79 | '''Prime sequence generator.''' 80 | 81 | def hexstep(): 82 | '''Generate 6n-1, 6n+1 sequence. ''' 83 | n = 1 84 | while True: 85 | hex = 6*n 86 | yield hex-1 87 | yield hex+1 88 | n += 1 89 | 90 | def isprime(n): 91 | for p in primes: 92 | if n%p==0: return False 93 | if p**2>n: return True # p**2>n is faster than p>n**.5 94 | 95 | yield 2 96 | yield 3 97 | primes = [3] # hexstep generates odd numbers, so 2 is unneccessary 98 | # this list is interal cache of calcuated primes 99 | 100 | for n in hexstep(): # all primes (except 2 and 3) are 6n-1 or 6n+1 101 | if isprime(n): 102 | yield n 103 | primes.append(n) 104 | prime = prime() 105 | 106 | 107 | 108 | def primefactors(n): 109 | '''Generate all prime factors of n.''' 110 | f = 2 111 | while f * f <= n: 112 | while not n % f: 113 | yield f 114 | n //= f 115 | f += 1 116 | if n > 1: 117 | yield n 118 | 119 | 120 | def upf(n): 121 | 'Unique prime factors of n' 122 | return set(primefactors(n)) 123 | 124 | 125 | 126 | def primefactors_slow(n): 127 | '''Generate all prime factors of n.''' 128 | for p in prime: 129 | if n > 1: 130 | while not (n % p): # n can be evenly divided by prime p 131 | n //= p 132 | yield p 133 | else: 134 | break 135 | 136 | 137 | from utils import groupcount 138 | def uniprimefact(n): 139 | ''' Return the Unique Prime-Factorization representation of n 140 | 141 | let n = (a**x) * (b**y) * (c**z) * ... 142 | return {a: x, b: y, c: z, ...} 143 | ''' 144 | 145 | return groupcount(primefactors(n)) 146 | 147 | 148 | 149 | def totient(n): 150 | ''' Euler's totient function: # of coprimes of n in [1, n) ''' 151 | return product((p-1)*(p**(k-1)) for (p, k) in uniprimefact(n).items()) 152 | 153 | 154 | from math import sqrt 155 | 156 | def primesieve(n): 157 | '''Sieve of Eratosthenes 158 | 159 | Return a list of all primes less than n 160 | ''' 161 | l = range(n) 162 | l[1]= 0 163 | for i in range(2, int(sqrt(n)) + 1): 164 | if l[i]: 165 | l[i**2::i] = [0] * ((n - 1 - i**2)//i + 1) 166 | 167 | return [x for x in l if x] 168 | 169 | 170 | def isprime(x): 171 | if x<5: return x==2 or x==3 172 | return x%2 and x%3 and all(x%(6*k-1) and x%(6*k+1) 173 | for k in range(1, int((x**.5 + 1)/6)+1)) 174 | 175 | 176 | def properdivisors(n): 177 | '''Generate a list of proper divisors of n 178 | 179 | If 2 is a PD of n, so is n/2. If 3 is a PD of n, so is n/3. Thus you only 180 | check until n**.5. 181 | ''' 182 | yield 1 183 | for i in xrange(2, int(n**.5)+1): 184 | if n % i == 0: 185 | yield i 186 | k = n // i 187 | if i != k: 188 | yield k 189 | 190 | 191 | def circulars(s): 192 | '''Generate circulars of sequence s 193 | 194 | eg. s = '123' => '123','231','312' 195 | ''' 196 | return (s[i:] + s[:i] for i in range(len(s))) 197 | 198 | 199 | def dec2bin(n): 200 | '''Return binary representation of decimal number n. ''' 201 | s = '' 202 | while n: 203 | s = str(n%2) + s 204 | n >>= 1 205 | return s if s!='' else '0' 206 | 207 | def permutate(s): 208 | '''Recursively generate all permutations of set s 209 | 210 | eg. 211 | s = [1,2,3] 212 | permutate(s) = [each element] + permutate(s without that element) 213 | ''' 214 | s = set(s) 215 | if s: 216 | for each in s: 217 | for rest in permutate(s - set([each])): 218 | yield [each] + rest 219 | else: 220 | yield [] 221 | 222 | def combinate(s, k): 223 | ''' Return k-combination from list s ''' 224 | n = len(s) 225 | #print 'k=%d, n=%d' % (k, n) 226 | if n == 0 or k == 0 or k > n: 227 | yield [] 228 | else: 229 | assert 1 <= k <= n 230 | 231 | if k == 1: 232 | for each in s: 233 | yield [each] 234 | else: 235 | for i in range(n): 236 | each, others = s[i], s[i+1:] 237 | for other in combinate(others, k-1): 238 | if other != []: 239 | yield [each] + other 240 | 241 | 242 | def divisors(n): 243 | 244 | def decompose(n): 245 | for (prime, power) in uniprimefact(n).items(): 246 | ls = [] 247 | for i in range(power+1): 248 | ls.append(prime**i) 249 | yield ls 250 | 251 | def vectorproduct(s1, s2): 252 | for e1 in s1: 253 | for e2 in s2: 254 | yield e1*e2 255 | 256 | def vectorloop(s): 257 | ts = [1] 258 | for each in s: 259 | ts = vectorproduct(ts, each) 260 | return ts 261 | 262 | def fnchain(a, fs): 263 | for f in fs: 264 | a = f(a) 265 | return a 266 | 267 | return fnchain(n, [decompose, vectorloop, sorted]) 268 | # == return sorted(vectorloop(decompose(n))) 269 | 270 | def properdivisors2(n): 271 | # this is significantly slower than the previous method 272 | assert n > 1 273 | return divisors(n)[:-1] 274 | 275 | 276 | def permutation(n, k): 277 | '''Number of permutations of k elements out of n elements.''' 278 | return factorial(n) // factorial(n - k) 279 | 280 | def combination(n, k): 281 | '''Number of combinations of k elements out of n elements.''' 282 | return factorial(n) // (factorial(k) * factorial(n-k)) 283 | 284 | 285 | from itertools import imap, izip 286 | def isarithmetic(s): 287 | '''Determine a sequence if it is an arithemtic sequence. 288 | 289 | An arithmetic sequence, [a, b, c, d] has constant difference between two 290 | consecutive elements 291 | ''' 292 | if len(s) < 3: 293 | return False 294 | else: 295 | d = s[1] - s[0] 296 | return all(imap(lambda (x,y): d==(y-x), izip(s, s[1:]))) 297 | 298 | def triplepermutate(ls): 299 | '''A special permutation 300 | 301 | ls = [a, b, c, d, e] # in asc order 302 | produce: 303 | abc abd abe acd ace ade 304 | bcd bce bde 305 | cde 306 | ''' 307 | for i in range(len(ls)): 308 | for j in range(i+1, len(ls)): 309 | for k in range(j+1, len(ls)): 310 | yield [ls[i], ls[j], ls[k]] 311 | 312 | 313 | def gcd(a, b): 314 | '''Return Greatest Common Divisor of a and b. ''' 315 | while b: 316 | a, b = b, a % b 317 | return a 318 | hcf = gcd # gcd also known as Highest Common Factor 319 | 320 | def lcm(a, b): 321 | '''Return the Least Common Multiple of a and b''' 322 | return a/gcd(a, b)*b # (a*b)/gcd(a,b) => a/gcd(a,b)*b faster for big a,b 323 | 324 | def ispandigital(n): 325 | '''Pandigital numbers contain all digits from 0 to 9''' 326 | return set(str(n)) == set('0123456789') 327 | 328 | 329 | # Graph Theory 330 | 331 | def dijkstra(g, s, d): 332 | '''Dijkstra's Shortest Path Algorithm. 333 | 334 | Find the shortest path from source s to destination d in graph g 335 | 336 | Dijkastra is a special case of A* (A-star) path searching algorithm w/o 337 | heuristic (F = G + H, with H=0) 338 | 339 | A*: http://www.policyalmanac.org/games/aStarTutorial.htm 340 | 341 | Input: 342 | 343 | g: a graph as a dict of {node: {neighbor: weight, ...}, ...} 344 | s: source node 345 | d: destination node 346 | ''' 347 | 348 | def tracetosource(n, p): 349 | ''' 350 | produce a path tracing back to source according to precedecssor p 351 | ''' 352 | path = [] 353 | path.append(n) 354 | while n in p: 355 | n = p[n] 356 | path.append(n) 357 | return path 358 | 359 | open = set([s]) 360 | closed = set() 361 | predecessor = {} 362 | cost = {s:0} # cost of path to node from s 363 | 364 | while open: 365 | mincost, current = min((cost[each], each) for each in open) 366 | open.remove(current) 367 | closed.add(current) 368 | if current==d: 369 | break 370 | for neighbor in g[current]: 371 | if neighbor in closed: 372 | continue 373 | if neighbor in open: 374 | newcost = cost[current] + g[current][neighbor] 375 | if newcost < cost[neighbor]: 376 | predecessor[neighbor] = current 377 | cost[neighbor] = newcost 378 | else: 379 | open.add(neighbor) 380 | predecessor[neighbor] = current 381 | cost[neighbor] = cost[current] + g[current][neighbor] 382 | 383 | return tracetosource(d, predecessor)[::-1] # reverse the traceback 384 | 385 | 386 | def prim(g): 387 | '''Prim's Minimum Spanning Tree Algorithm. 388 | 389 | g: a graph as a dict of {node: {neighbor: weight, ...}, ...} 390 | 391 | (Only works for undirected graph, eg. for any i, j g[i][j] = g[j][i]) 392 | ''' 393 | solved = set() 394 | mst = set() 395 | edges = set() 396 | 397 | current = g.keys()[0] # choose arbitrary node to start 398 | while True: 399 | for neighbor in g[current]: 400 | edge = (g[current][neighbor], frozenset([current, neighbor])) 401 | # use frozenset to store unorderd pair in set 402 | if edge in mst: continue 403 | edges.remove(edge) if edge in edges else edges.add(edge) 404 | 405 | if edges: 406 | edge = min(edges) 407 | edges.remove(edge) 408 | mst.add(edge) 409 | 410 | _, (a, b) = edge 411 | solved.add(current) 412 | current = a if b in solved else b 413 | else: 414 | break 415 | 416 | return dict((pair, cost) for (cost,pair) in mst) # set -> dict 417 | 418 | 419 | 420 | 421 | 422 | def pentagonal(n): 423 | 'Pentagonal number' 424 | return n*(3*n-1)/2 425 | 426 | 427 | 428 | @memoized 429 | def partition(n): 430 | ''' 431 | # of ways to partition integer n 432 | 433 | Find the # of ways to partition a number 434 | 435 | http://www.math.temple.edu/~melkamu/html/partition.pdf 436 | 437 | p(<0) = 0 438 | p(0) = 1 439 | p(n) = p(n-1) + p(n-2) - p(n-5) - p(n-7) + p(n-12) + p(n-15) - p(n-22) - p(n-26) + ... 440 | 441 | # of ways to partition n 442 | p(n) = \sum_{k=1}^{\infinity} (-1)^(k+1) * { p(n-f(k)) + p(n-f(-k)) } 443 | 444 | ''' 445 | 446 | if n < 0: 447 | s = 0 448 | elif n == 0: 449 | s = 1 450 | else: 451 | s = 0 452 | k = 0 453 | while True: 454 | k += 1 455 | sign= -1 if k%2==0 else 1 456 | m1 = n - pentagonal(k) 457 | m2 = n - pentagonal(-k) 458 | s += sign * (partition(m1) + partition(m2)) 459 | if m1 <= 0 or m2 <= 0: 460 | break 461 | 462 | return s 463 | 464 | 465 | -------------------------------------------------------------------------------- /triangle.txt: -------------------------------------------------------------------------------- 1 | 59 2 | 73 41 3 | 52 40 09 4 | 26 53 06 34 5 | 10 51 87 86 81 6 | 61 95 66 57 25 68 7 | 90 81 80 38 92 67 73 8 | 30 28 51 76 81 18 75 44 9 | 84 14 95 87 62 81 17 78 58 10 | 21 46 71 58 02 79 62 39 31 09 11 | 56 34 35 53 78 31 81 18 90 93 15 12 | 78 53 04 21 84 93 32 13 97 11 37 51 13 | 45 03 81 79 05 18 78 86 13 30 63 99 95 14 | 39 87 96 28 03 38 42 17 82 87 58 07 22 57 15 | 06 17 51 17 07 93 09 07 75 97 95 78 87 08 53 16 | 67 66 59 60 88 99 94 65 55 77 55 34 27 53 78 28 17 | 76 40 41 04 87 16 09 42 75 69 23 97 30 60 10 79 87 18 | 12 10 44 26 21 36 32 84 98 60 13 12 36 16 63 31 91 35 19 | 70 39 06 05 55 27 38 48 28 22 34 35 62 62 15 14 94 89 86 20 | 66 56 68 84 96 21 34 34 34 81 62 40 65 54 62 05 98 03 02 60 21 | 38 89 46 37 99 54 34 53 36 14 70 26 02 90 45 13 31 61 83 73 47 22 | 36 10 63 96 60 49 41 05 37 42 14 58 84 93 96 17 09 43 05 43 06 59 23 | 66 57 87 57 61 28 37 51 84 73 79 15 39 95 88 87 43 39 11 86 77 74 18 24 | 54 42 05 79 30 49 99 73 46 37 50 02 45 09 54 52 27 95 27 65 19 45 26 45 25 | 71 39 17 78 76 29 52 90 18 99 78 19 35 62 71 19 23 65 93 85 49 33 75 09 02 26 | 33 24 47 61 60 55 32 88 57 55 91 54 46 57 07 77 98 52 80 99 24 25 46 78 79 05 27 | 92 09 13 55 10 67 26 78 76 82 63 49 51 31 24 68 05 57 07 54 69 21 67 43 17 63 12 28 | 24 59 06 08 98 74 66 26 61 60 13 03 09 09 24 30 71 08 88 70 72 70 29 90 11 82 41 34 29 | 66 82 67 04 36 60 92 77 91 85 62 49 59 61 30 90 29 94 26 41 89 04 53 22 83 41 09 74 90 30 | 48 28 26 37 28 52 77 26 51 32 18 98 79 36 62 13 17 08 19 54 89 29 73 68 42 14 08 16 70 37 31 | 37 60 69 70 72 71 09 59 13 60 38 13 57 36 09 30 43 89 30 39 15 02 44 73 05 73 26 63 56 86 12 32 | 55 55 85 50 62 99 84 77 28 85 03 21 27 22 19 26 82 69 54 04 13 07 85 14 01 15 70 59 89 95 10 19 33 | 04 09 31 92 91 38 92 86 98 75 21 05 64 42 62 84 36 20 73 42 21 23 22 51 51 79 25 45 85 53 03 43 22 34 | 75 63 02 49 14 12 89 14 60 78 92 16 44 82 38 30 72 11 46 52 90 27 08 65 78 03 85 41 57 79 39 52 33 48 35 | 78 27 56 56 39 13 19 43 86 72 58 95 39 07 04 34 21 98 39 15 39 84 89 69 84 46 37 57 59 35 59 50 26 15 93 36 | 42 89 36 27 78 91 24 11 17 41 05 94 07 69 51 96 03 96 47 90 90 45 91 20 50 56 10 32 36 49 04 53 85 92 25 65 37 | 52 09 61 30 61 97 66 21 96 92 98 90 06 34 96 60 32 69 68 33 75 84 18 31 71 50 84 63 03 03 19 11 28 42 75 45 45 38 | 61 31 61 68 96 34 49 39 05 71 76 59 62 67 06 47 96 99 34 21 32 47 52 07 71 60 42 72 94 56 82 83 84 40 94 87 82 46 39 | 01 20 60 14 17 38 26 78 66 81 45 95 18 51 98 81 48 16 53 88 37 52 69 95 72 93 22 34 98 20 54 27 73 61 56 63 60 34 63 40 | 93 42 94 83 47 61 27 51 79 79 45 01 44 73 31 70 83 42 88 25 53 51 30 15 65 94 80 44 61 84 12 77 02 62 02 65 94 42 14 94 41 | 32 73 09 67 68 29 74 98 10 19 85 48 38 31 85 67 53 93 93 77 47 67 39 72 94 53 18 43 77 40 78 32 29 59 24 06 02 83 50 60 66 42 | 32 01 44 30 16 51 15 81 98 15 10 62 86 79 50 62 45 60 70 38 31 85 65 61 64 06 69 84 14 22 56 43 09 48 66 69 83 91 60 40 36 61 43 | 92 48 22 99 15 95 64 43 01 16 94 02 99 19 17 69 11 58 97 56 89 31 77 45 67 96 12 73 08 20 36 47 81 44 50 64 68 85 40 81 85 52 09 44 | 91 35 92 45 32 84 62 15 19 64 21 66 06 01 52 80 62 59 12 25 88 28 91 50 40 16 22 99 92 79 87 51 21 77 74 77 07 42 38 42 74 83 02 05 45 | 46 19 77 66 24 18 05 32 02 84 31 99 92 58 96 72 91 36 62 99 55 29 53 42 12 37 26 58 89 50 66 19 82 75 12 48 24 87 91 85 02 07 03 76 86 46 | 99 98 84 93 07 17 33 61 92 20 66 60 24 66 40 30 67 05 37 29 24 96 03 27 70 62 13 04 45 47 59 88 43 20 66 15 46 92 30 04 71 66 78 70 53 99 47 | 67 60 38 06 88 04 17 72 10 99 71 07 42 25 54 05 26 64 91 50 45 71 06 30 67 48 69 82 08 56 80 67 18 46 66 63 01 20 08 80 47 07 91 16 03 79 87 48 | 18 54 78 49 80 48 77 40 68 23 60 88 58 80 33 57 11 69 55 53 64 02 94 49 60 92 16 35 81 21 82 96 25 24 96 18 02 05 49 03 50 77 06 32 84 27 18 38 49 | 68 01 50 04 03 21 42 94 53 24 89 05 92 26 52 36 68 11 85 01 04 42 02 45 15 06 50 04 53 73 25 74 81 88 98 21 67 84 79 97 99 20 95 04 40 46 02 58 87 50 | 94 10 02 78 88 52 21 03 88 60 06 53 49 71 20 91 12 65 07 49 21 22 11 41 58 99 36 16 09 48 17 24 52 36 23 15 72 16 84 56 02 99 43 76 81 71 29 39 49 17 51 | 64 39 59 84 86 16 17 66 03 09 43 06 64 18 63 29 68 06 23 07 87 14 26 35 17 12 98 41 53 64 78 18 98 27 28 84 80 67 75 62 10 11 76 90 54 10 05 54 41 39 66 52 | 43 83 18 37 32 31 52 29 95 47 08 76 35 11 04 53 35 43 34 10 52 57 12 36 20 39 40 55 78 44 07 31 38 26 08 15 56 88 86 01 52 62 10 24 32 05 60 65 53 28 57 99 53 | 03 50 03 52 07 73 49 92 66 80 01 46 08 67 25 36 73 93 07 42 25 53 13 96 76 83 87 90 54 89 78 22 78 91 73 51 69 09 79 94 83 53 09 40 69 62 10 79 49 47 03 81 30 54 | 71 54 73 33 51 76 59 54 79 37 56 45 84 17 62 21 98 69 41 95 65 24 39 37 62 03 24 48 54 64 46 82 71 78 33 67 09 16 96 68 52 74 79 68 32 21 13 78 96 60 09 69 20 36 55 | 73 26 21 44 46 38 17 83 65 98 07 23 52 46 61 97 33 13 60 31 70 15 36 77 31 58 56 93 75 68 21 36 69 53 90 75 25 82 39 50 65 94 29 30 11 33 11 13 96 02 56 47 07 49 02 56 | 76 46 73 30 10 20 60 70 14 56 34 26 37 39 48 24 55 76 84 91 39 86 95 61 50 14 53 93 64 67 37 31 10 84 42 70 48 20 10 72 60 61 84 79 69 65 99 73 89 25 85 48 92 56 97 16 57 | 03 14 80 27 22 30 44 27 67 75 79 32 51 54 81 29 65 14 19 04 13 82 04 91 43 40 12 52 29 99 07 76 60 25 01 07 61 71 37 92 40 47 99 66 57 01 43 44 22 40 53 53 09 69 26 81 07 58 | 49 80 56 90 93 87 47 13 75 28 87 23 72 79 32 18 27 20 28 10 37 59 21 18 70 04 79 96 03 31 45 71 81 06 14 18 17 05 31 50 92 79 23 47 09 39 47 91 43 54 69 47 42 95 62 46 32 85 59 | 37 18 62 85 87 28 64 05 77 51 47 26 30 65 05 70 65 75 59 80 42 52 25 20 44 10 92 17 71 95 52 14 77 13 24 55 11 65 26 91 01 30 63 15 49 48 41 17 67 47 03 68 20 90 98 32 04 40 68 60 | 90 51 58 60 06 55 23 68 05 19 76 94 82 36 96 43 38 90 87 28 33 83 05 17 70 83 96 93 06 04 78 47 80 06 23 84 75 23 87 72 99 14 50 98 92 38 90 64 61 58 76 94 36 66 87 80 51 35 61 38 61 | 57 95 64 06 53 36 82 51 40 33 47 14 07 98 78 65 39 58 53 06 50 53 04 69 40 68 36 69 75 78 75 60 03 32 39 24 74 47 26 90 13 40 44 71 90 76 51 24 36 50 25 45 70 80 61 80 61 43 90 64 11 62 | 18 29 86 56 68 42 79 10 42 44 30 12 96 18 23 18 52 59 02 99 67 46 60 86 43 38 55 17 44 93 42 21 55 14 47 34 55 16 49 24 23 29 96 51 55 10 46 53 27 92 27 46 63 57 30 65 43 27 21 20 24 83 63 | 81 72 93 19 69 52 48 01 13 83 92 69 20 48 69 59 20 62 05 42 28 89 90 99 32 72 84 17 08 87 36 03 60 31 36 36 81 26 97 36 48 54 56 56 27 16 91 08 23 11 87 99 33 47 02 14 44 73 70 99 43 35 33 64 | 90 56 61 86 56 12 70 59 63 32 01 15 81 47 71 76 95 32 65 80 54 70 34 51 40 45 33 04 64 55 78 68 88 47 31 47 68 87 03 84 23 44 89 72 35 08 31 76 63 26 90 85 96 67 65 91 19 14 17 86 04 71 32 95 65 | 37 13 04 22 64 37 37 28 56 62 86 33 07 37 10 44 52 82 52 06 19 52 57 75 90 26 91 24 06 21 14 67 76 30 46 14 35 89 89 41 03 64 56 97 87 63 22 34 03 79 17 45 11 53 25 56 96 61 23 18 63 31 37 37 47 66 | 77 23 26 70 72 76 77 04 28 64 71 69 14 85 96 54 95 48 06 62 99 83 86 77 97 75 71 66 30 19 57 90 33 01 60 61 14 12 90 99 32 77 56 41 18 14 87 49 10 14 90 64 18 50 21 74 14 16 88 05 45 73 82 47 74 44 67 | 22 97 41 13 34 31 54 61 56 94 03 24 59 27 98 77 04 09 37 40 12 26 87 09 71 70 07 18 64 57 80 21 12 71 83 94 60 39 73 79 73 19 97 32 64 29 41 07 48 84 85 67 12 74 95 20 24 52 41 67 56 61 29 93 35 72 69 68 | 72 23 63 66 01 11 07 30 52 56 95 16 65 26 83 90 50 74 60 18 16 48 43 77 37 11 99 98 30 94 91 26 62 73 45 12 87 73 47 27 01 88 66 99 21 41 95 80 02 53 23 32 61 48 32 43 43 83 14 66 95 91 19 81 80 67 25 88 69 | 08 62 32 18 92 14 83 71 37 96 11 83 39 99 05 16 23 27 10 67 02 25 44 11 55 31 46 64 41 56 44 74 26 81 51 31 45 85 87 09 81 95 22 28 76 69 46 48 64 87 67 76 27 89 31 11 74 16 62 03 60 94 42 47 09 34 94 93 72 70 | 56 18 90 18 42 17 42 32 14 86 06 53 33 95 99 35 29 15 44 20 49 59 25 54 34 59 84 21 23 54 35 90 78 16 93 13 37 88 54 19 86 67 68 55 66 84 65 42 98 37 87 56 33 28 58 38 28 38 66 27 52 21 81 15 08 22 97 32 85 27 71 | 91 53 40 28 13 34 91 25 01 63 50 37 22 49 71 58 32 28 30 18 68 94 23 83 63 62 94 76 80 41 90 22 82 52 29 12 18 56 10 08 35 14 37 57 23 65 67 40 72 39 93 39 70 89 40 34 07 46 94 22 20 05 53 64 56 30 05 56 61 88 27 72 | 23 95 11 12 37 69 68 24 66 10 87 70 43 50 75 07 62 41 83 58 95 93 89 79 45 39 02 22 05 22 95 43 62 11 68 29 17 40 26 44 25 71 87 16 70 85 19 25 59 94 90 41 41 80 61 70 55 60 84 33 95 76 42 63 15 09 03 40 38 12 03 32 73 | 09 84 56 80 61 55 85 97 16 94 82 94 98 57 84 30 84 48 93 90 71 05 95 90 73 17 30 98 40 64 65 89 07 79 09 19 56 36 42 30 23 69 73 72 07 05 27 61 24 31 43 48 71 84 21 28 26 65 65 59 65 74 77 20 10 81 61 84 95 08 52 23 70 74 | 47 81 28 09 98 51 67 64 35 51 59 36 92 82 77 65 80 24 72 53 22 07 27 10 21 28 30 22 48 82 80 48 56 20 14 43 18 25 50 95 90 31 77 08 09 48 44 80 90 22 93 45 82 17 13 96 25 26 08 73 34 99 06 49 24 06 83 51 40 14 15 10 25 01 75 | 54 25 10 81 30 64 24 74 75 80 36 75 82 60 22 69 72 91 45 67 03 62 79 54 89 74 44 83 64 96 66 73 44 30 74 50 37 05 09 97 70 01 60 46 37 91 39 75 75 18 58 52 72 78 51 81 86 52 08 97 01 46 43 66 98 62 81 18 70 93 73 08 32 46 34 76 | 96 80 82 07 59 71 92 53 19 20 88 66 03 26 26 10 24 27 50 82 94 73 63 08 51 33 22 45 19 13 58 33 90 15 22 50 36 13 55 06 35 47 82 52 33 61 36 27 28 46 98 14 73 20 73 32 16 26 80 53 47 66 76 38 94 45 02 01 22 52 47 96 64 58 52 39 77 | 88 46 23 39 74 63 81 64 20 90 33 33 76 55 58 26 10 46 42 26 74 74 12 83 32 43 09 02 73 55 86 54 85 34 28 23 29 79 91 62 47 41 82 87 99 22 48 90 20 05 96 75 95 04 43 28 81 39 81 01 28 42 78 25 39 77 90 57 58 98 17 36 73 22 63 74 51 78 | 29 39 74 94 95 78 64 24 38 86 63 87 93 06 70 92 22 16 80 64 29 52 20 27 23 50 14 13 87 15 72 96 81 22 08 49 72 30 70 24 79 31 16 64 59 21 89 34 96 91 48 76 43 53 88 01 57 80 23 81 90 79 58 01 80 87 17 99 86 90 72 63 32 69 14 28 88 69 79 | 37 17 71 95 56 93 71 35 43 45 04 98 92 94 84 96 11 30 31 27 31 60 92 03 48 05 98 91 86 94 35 90 90 08 48 19 33 28 68 37 59 26 65 96 50 68 22 07 09 49 34 31 77 49 43 06 75 17 81 87 61 79 52 26 27 72 29 50 07 98 86 01 17 10 46 64 24 18 56 80 | 51 30 25 94 88 85 79 91 40 33 63 84 49 67 98 92 15 26 75 19 82 05 18 78 65 93 61 48 91 43 59 41 70 51 22 15 92 81 67 91 46 98 11 11 65 31 66 10 98 65 83 21 05 56 05 98 73 67 46 74 69 34 08 30 05 52 07 98 32 95 30 94 65 50 24 63 28 81 99 57 81 | 19 23 61 36 09 89 71 98 65 17 30 29 89 26 79 74 94 11 44 48 97 54 81 55 39 66 69 45 28 47 13 86 15 76 74 70 84 32 36 33 79 20 78 14 41 47 89 28 81 05 99 66 81 86 38 26 06 25 13 60 54 55 23 53 27 05 89 25 23 11 13 54 59 54 56 34 16 24 53 44 06 82 | 13 40 57 72 21 15 60 08 04 19 11 98 34 45 09 97 86 71 03 15 56 19 15 44 97 31 90 04 87 87 76 08 12 30 24 62 84 28 12 85 82 53 99 52 13 94 06 65 97 86 09 50 94 68 69 74 30 67 87 94 63 07 78 27 80 36 69 41 06 92 32 78 37 82 30 05 18 87 99 72 19 99 83 | 44 20 55 77 69 91 27 31 28 81 80 27 02 07 97 23 95 98 12 25 75 29 47 71 07 47 78 39 41 59 27 76 13 15 66 61 68 35 69 86 16 53 67 63 99 85 41 56 08 28 33 40 94 76 90 85 31 70 24 65 84 65 99 82 19 25 54 37 21 46 33 02 52 99 51 33 26 04 87 02 08 18 96 84 | 54 42 61 45 91 06 64 79 80 82 32 16 83 63 42 49 19 78 65 97 40 42 14 61 49 34 04 18 25 98 59 30 82 72 26 88 54 36 21 75 03 88 99 53 46 51 55 78 22 94 34 40 68 87 84 25 30 76 25 08 92 84 42 61 40 38 09 99 40 23 29 39 46 55 10 90 35 84 56 70 63 23 91 39 85 | 52 92 03 71 89 07 09 37 68 66 58 20 44 92 51 56 13 71 79 99 26 37 02 06 16 67 36 52 58 16 79 73 56 60 59 27 44 77 94 82 20 50 98 33 09 87 94 37 40 83 64 83 58 85 17 76 53 02 83 52 22 27 39 20 48 92 45 21 09 42 24 23 12 37 52 28 50 78 79 20 86 62 73 20 59 86 | 54 96 80 15 91 90 99 70 10 09 58 90 93 50 81 99 54 38 36 10 30 11 35 84 16 45 82 18 11 97 36 43 96 79 97 65 40 48 23 19 17 31 64 52 65 65 37 32 65 76 99 79 34 65 79 27 55 33 03 01 33 27 61 28 66 08 04 70 49 46 48 83 01 45 19 96 13 81 14 21 31 79 93 85 50 05 87 | 92 92 48 84 59 98 31 53 23 27 15 22 79 95 24 76 05 79 16 93 97 89 38 89 42 83 02 88 94 95 82 21 01 97 48 39 31 78 09 65 50 56 97 61 01 07 65 27 21 23 14 15 80 97 44 78 49 35 33 45 81 74 34 05 31 57 09 38 94 07 69 54 69 32 65 68 46 68 78 90 24 28 49 51 45 86 35 88 | 41 63 89 76 87 31 86 09 46 14 87 82 22 29 47 16 13 10 70 72 82 95 48 64 58 43 13 75 42 69 21 12 67 13 64 85 58 23 98 09 37 76 05 22 31 12 66 50 29 99 86 72 45 25 10 28 19 06 90 43 29 31 67 79 46 25 74 14 97 35 76 37 65 46 23 82 06 22 30 76 93 66 94 17 96 13 20 72 89 | 63 40 78 08 52 09 90 41 70 28 36 14 46 44 85 96 24 52 58 15 87 37 05 98 99 39 13 61 76 38 44 99 83 74 90 22 53 80 56 98 30 51 63 39 44 30 91 91 04 22 27 73 17 35 53 18 35 45 54 56 27 78 48 13 69 36 44 38 71 25 30 56 15 22 73 43 32 69 59 25 93 83 45 11 34 94 44 39 92 90 | 12 36 56 88 13 96 16 12 55 54 11 47 19 78 17 17 68 81 77 51 42 55 99 85 66 27 81 79 93 42 65 61 69 74 14 01 18 56 12 01 58 37 91 22 42 66 83 25 19 04 96 41 25 45 18 69 96 88 36 93 10 12 98 32 44 83 83 04 72 91 04 27 73 07 34 37 71 60 59 31 01 54 54 44 96 93 83 36 04 45 91 | 30 18 22 20 42 96 65 79 17 41 55 69 94 81 29 80 91 31 85 25 47 26 43 49 02 99 34 67 99 76 16 14 15 93 08 32 99 44 61 77 67 50 43 55 87 55 53 72 17 46 62 25 50 99 73 05 93 48 17 31 70 80 59 09 44 59 45 13 74 66 58 94 87 73 16 14 85 38 74 99 64 23 79 28 71 42 20 37 82 31 23 92 | 51 96 39 65 46 71 56 13 29 68 53 86 45 33 51 49 12 91 21 21 76 85 02 17 98 15 46 12 60 21 88 30 92 83 44 59 42 50 27 88 46 86 94 73 45 54 23 24 14 10 94 21 20 34 23 51 04 83 99 75 90 63 60 16 22 33 83 70 11 32 10 50 29 30 83 46 11 05 31 17 86 42 49 01 44 63 28 60 07 78 95 40 93 | 44 61 89 59 04 49 51 27 69 71 46 76 44 04 09 34 56 39 15 06 94 91 75 90 65 27 56 23 74 06 23 33 36 69 14 39 05 34 35 57 33 22 76 46 56 10 61 65 98 09 16 69 04 62 65 18 99 76 49 18 72 66 73 83 82 40 76 31 89 91 27 88 17 35 41 35 32 51 32 67 52 68 74 85 80 57 07 11 62 66 47 22 67 94 | 65 37 19 97 26 17 16 24 24 17 50 37 64 82 24 36 32 11 68 34 69 31 32 89 79 93 96 68 49 90 14 23 04 04 67 99 81 74 70 74 36 96 68 09 64 39 88 35 54 89 96 58 66 27 88 97 32 14 06 35 78 20 71 06 85 66 57 02 58 91 72 05 29 56 73 48 86 52 09 93 22 57 79 42 12 01 31 68 17 59 63 76 07 77 95 | 73 81 14 13 17 20 11 09 01 83 08 85 91 70 84 63 62 77 37 07 47 01 59 95 39 69 39 21 99 09 87 02 97 16 92 36 74 71 90 66 33 73 73 75 52 91 11 12 26 53 05 26 26 48 61 50 90 65 01 87 42 47 74 35 22 73 24 26 56 70 52 05 48 41 31 18 83 27 21 39 80 85 26 08 44 02 71 07 63 22 05 52 19 08 20 96 | 17 25 21 11 72 93 33 49 64 23 53 82 03 13 91 65 85 02 40 05 42 31 77 42 05 36 06 54 04 58 07 76 87 83 25 57 66 12 74 33 85 37 74 32 20 69 03 97 91 68 82 44 19 14 89 28 85 85 80 53 34 87 58 98 88 78 48 65 98 40 11 57 10 67 70 81 60 79 74 72 97 59 79 47 30 20 54 80 89 91 14 05 33 36 79 39 97 | 60 85 59 39 60 07 57 76 77 92 06 35 15 72 23 41 45 52 95 18 64 79 86 53 56 31 69 11 91 31 84 50 44 82 22 81 41 40 30 42 30 91 48 94 74 76 64 58 74 25 96 57 14 19 03 99 28 83 15 75 99 01 89 85 79 50 03 95 32 67 44 08 07 41 62 64 29 20 14 76 26 55 48 71 69 66 19 72 44 25 14 01 48 74 12 98 07 98 | 64 66 84 24 18 16 27 48 20 14 47 69 30 86 48 40 23 16 61 21 51 50 26 47 35 33 91 28 78 64 43 68 04 79 51 08 19 60 52 95 06 68 46 86 35 97 27 58 04 65 30 58 99 12 12 75 91 39 50 31 42 64 70 04 46 07 98 73 98 93 37 89 77 91 64 71 64 65 66 21 78 62 81 74 42 20 83 70 73 95 78 45 92 27 34 53 71 15 99 | 30 11 85 31 34 71 13 48 05 14 44 03 19 67 23 73 19 57 06 90 94 72 57 69 81 62 59 68 88 57 55 69 49 13 07 87 97 80 89 05 71 05 05 26 38 40 16 62 45 99 18 38 98 24 21 26 62 74 69 04 85 57 77 35 58 67 91 79 79 57 86 28 66 34 72 51 76 78 36 95 63 90 08 78 47 63 45 31 22 70 52 48 79 94 15 77 61 67 68 100 | 23 33 44 81 80 92 93 75 94 88 23 61 39 76 22 03 28 94 32 06 49 65 41 34 18 23 08 47 62 60 03 63 33 13 80 52 31 54 73 43 70 26 16 69 57 87 83 31 03 93 70 81 47 95 77 44 29 68 39 51 56 59 63 07 25 70 07 77 43 53 64 03 94 42 95 39 18 01 66 21 16 97 20 50 90 16 70 10 95 69 29 06 25 61 41 26 15 59 63 35 101 | -------------------------------------------------------------------------------- /words.txt: -------------------------------------------------------------------------------- 1 | "A","ABILITY","ABLE","ABOUT","ABOVE","ABSENCE","ABSOLUTELY","ACADEMIC","ACCEPT","ACCESS","ACCIDENT","ACCOMPANY","ACCORDING","ACCOUNT","ACHIEVE","ACHIEVEMENT","ACID","ACQUIRE","ACROSS","ACT","ACTION","ACTIVE","ACTIVITY","ACTUAL","ACTUALLY","ADD","ADDITION","ADDITIONAL","ADDRESS","ADMINISTRATION","ADMIT","ADOPT","ADULT","ADVANCE","ADVANTAGE","ADVICE","ADVISE","AFFAIR","AFFECT","AFFORD","AFRAID","AFTER","AFTERNOON","AFTERWARDS","AGAIN","AGAINST","AGE","AGENCY","AGENT","AGO","AGREE","AGREEMENT","AHEAD","AID","AIM","AIR","AIRCRAFT","ALL","ALLOW","ALMOST","ALONE","ALONG","ALREADY","ALRIGHT","ALSO","ALTERNATIVE","ALTHOUGH","ALWAYS","AMONG","AMONGST","AMOUNT","AN","ANALYSIS","ANCIENT","AND","ANIMAL","ANNOUNCE","ANNUAL","ANOTHER","ANSWER","ANY","ANYBODY","ANYONE","ANYTHING","ANYWAY","APART","APPARENT","APPARENTLY","APPEAL","APPEAR","APPEARANCE","APPLICATION","APPLY","APPOINT","APPOINTMENT","APPROACH","APPROPRIATE","APPROVE","AREA","ARGUE","ARGUMENT","ARISE","ARM","ARMY","AROUND","ARRANGE","ARRANGEMENT","ARRIVE","ART","ARTICLE","ARTIST","AS","ASK","ASPECT","ASSEMBLY","ASSESS","ASSESSMENT","ASSET","ASSOCIATE","ASSOCIATION","ASSUME","ASSUMPTION","AT","ATMOSPHERE","ATTACH","ATTACK","ATTEMPT","ATTEND","ATTENTION","ATTITUDE","ATTRACT","ATTRACTIVE","AUDIENCE","AUTHOR","AUTHORITY","AVAILABLE","AVERAGE","AVOID","AWARD","AWARE","AWAY","AYE","BABY","BACK","BACKGROUND","BAD","BAG","BALANCE","BALL","BAND","BANK","BAR","BASE","BASIC","BASIS","BATTLE","BE","BEAR","BEAT","BEAUTIFUL","BECAUSE","BECOME","BED","BEDROOM","BEFORE","BEGIN","BEGINNING","BEHAVIOUR","BEHIND","BELIEF","BELIEVE","BELONG","BELOW","BENEATH","BENEFIT","BESIDE","BEST","BETTER","BETWEEN","BEYOND","BIG","BILL","BIND","BIRD","BIRTH","BIT","BLACK","BLOCK","BLOOD","BLOODY","BLOW","BLUE","BOARD","BOAT","BODY","BONE","BOOK","BORDER","BOTH","BOTTLE","BOTTOM","BOX","BOY","BRAIN","BRANCH","BREAK","BREATH","BRIDGE","BRIEF","BRIGHT","BRING","BROAD","BROTHER","BUDGET","BUILD","BUILDING","BURN","BUS","BUSINESS","BUSY","BUT","BUY","BY","CABINET","CALL","CAMPAIGN","CAN","CANDIDATE","CAPABLE","CAPACITY","CAPITAL","CAR","CARD","CARE","CAREER","CAREFUL","CAREFULLY","CARRY","CASE","CASH","CAT","CATCH","CATEGORY","CAUSE","CELL","CENTRAL","CENTRE","CENTURY","CERTAIN","CERTAINLY","CHAIN","CHAIR","CHAIRMAN","CHALLENGE","CHANCE","CHANGE","CHANNEL","CHAPTER","CHARACTER","CHARACTERISTIC","CHARGE","CHEAP","CHECK","CHEMICAL","CHIEF","CHILD","CHOICE","CHOOSE","CHURCH","CIRCLE","CIRCUMSTANCE","CITIZEN","CITY","CIVIL","CLAIM","CLASS","CLEAN","CLEAR","CLEARLY","CLIENT","CLIMB","CLOSE","CLOSELY","CLOTHES","CLUB","COAL","CODE","COFFEE","COLD","COLLEAGUE","COLLECT","COLLECTION","COLLEGE","COLOUR","COMBINATION","COMBINE","COME","COMMENT","COMMERCIAL","COMMISSION","COMMIT","COMMITMENT","COMMITTEE","COMMON","COMMUNICATION","COMMUNITY","COMPANY","COMPARE","COMPARISON","COMPETITION","COMPLETE","COMPLETELY","COMPLEX","COMPONENT","COMPUTER","CONCENTRATE","CONCENTRATION","CONCEPT","CONCERN","CONCERNED","CONCLUDE","CONCLUSION","CONDITION","CONDUCT","CONFERENCE","CONFIDENCE","CONFIRM","CONFLICT","CONGRESS","CONNECT","CONNECTION","CONSEQUENCE","CONSERVATIVE","CONSIDER","CONSIDERABLE","CONSIDERATION","CONSIST","CONSTANT","CONSTRUCTION","CONSUMER","CONTACT","CONTAIN","CONTENT","CONTEXT","CONTINUE","CONTRACT","CONTRAST","CONTRIBUTE","CONTRIBUTION","CONTROL","CONVENTION","CONVERSATION","COPY","CORNER","CORPORATE","CORRECT","COS","COST","COULD","COUNCIL","COUNT","COUNTRY","COUNTY","COUPLE","COURSE","COURT","COVER","CREATE","CREATION","CREDIT","CRIME","CRIMINAL","CRISIS","CRITERION","CRITICAL","CRITICISM","CROSS","CROWD","CRY","CULTURAL","CULTURE","CUP","CURRENT","CURRENTLY","CURRICULUM","CUSTOMER","CUT","DAMAGE","DANGER","DANGEROUS","DARK","DATA","DATE","DAUGHTER","DAY","DEAD","DEAL","DEATH","DEBATE","DEBT","DECADE","DECIDE","DECISION","DECLARE","DEEP","DEFENCE","DEFENDANT","DEFINE","DEFINITION","DEGREE","DELIVER","DEMAND","DEMOCRATIC","DEMONSTRATE","DENY","DEPARTMENT","DEPEND","DEPUTY","DERIVE","DESCRIBE","DESCRIPTION","DESIGN","DESIRE","DESK","DESPITE","DESTROY","DETAIL","DETAILED","DETERMINE","DEVELOP","DEVELOPMENT","DEVICE","DIE","DIFFERENCE","DIFFERENT","DIFFICULT","DIFFICULTY","DINNER","DIRECT","DIRECTION","DIRECTLY","DIRECTOR","DISAPPEAR","DISCIPLINE","DISCOVER","DISCUSS","DISCUSSION","DISEASE","DISPLAY","DISTANCE","DISTINCTION","DISTRIBUTION","DISTRICT","DIVIDE","DIVISION","DO","DOCTOR","DOCUMENT","DOG","DOMESTIC","DOOR","DOUBLE","DOUBT","DOWN","DRAW","DRAWING","DREAM","DRESS","DRINK","DRIVE","DRIVER","DROP","DRUG","DRY","DUE","DURING","DUTY","EACH","EAR","EARLY","EARN","EARTH","EASILY","EAST","EASY","EAT","ECONOMIC","ECONOMY","EDGE","EDITOR","EDUCATION","EDUCATIONAL","EFFECT","EFFECTIVE","EFFECTIVELY","EFFORT","EGG","EITHER","ELDERLY","ELECTION","ELEMENT","ELSE","ELSEWHERE","EMERGE","EMPHASIS","EMPLOY","EMPLOYEE","EMPLOYER","EMPLOYMENT","EMPTY","ENABLE","ENCOURAGE","END","ENEMY","ENERGY","ENGINE","ENGINEERING","ENJOY","ENOUGH","ENSURE","ENTER","ENTERPRISE","ENTIRE","ENTIRELY","ENTITLE","ENTRY","ENVIRONMENT","ENVIRONMENTAL","EQUAL","EQUALLY","EQUIPMENT","ERROR","ESCAPE","ESPECIALLY","ESSENTIAL","ESTABLISH","ESTABLISHMENT","ESTATE","ESTIMATE","EVEN","EVENING","EVENT","EVENTUALLY","EVER","EVERY","EVERYBODY","EVERYONE","EVERYTHING","EVIDENCE","EXACTLY","EXAMINATION","EXAMINE","EXAMPLE","EXCELLENT","EXCEPT","EXCHANGE","EXECUTIVE","EXERCISE","EXHIBITION","EXIST","EXISTENCE","EXISTING","EXPECT","EXPECTATION","EXPENDITURE","EXPENSE","EXPENSIVE","EXPERIENCE","EXPERIMENT","EXPERT","EXPLAIN","EXPLANATION","EXPLORE","EXPRESS","EXPRESSION","EXTEND","EXTENT","EXTERNAL","EXTRA","EXTREMELY","EYE","FACE","FACILITY","FACT","FACTOR","FACTORY","FAIL","FAILURE","FAIR","FAIRLY","FAITH","FALL","FAMILIAR","FAMILY","FAMOUS","FAR","FARM","FARMER","FASHION","FAST","FATHER","FAVOUR","FEAR","FEATURE","FEE","FEEL","FEELING","FEMALE","FEW","FIELD","FIGHT","FIGURE","FILE","FILL","FILM","FINAL","FINALLY","FINANCE","FINANCIAL","FIND","FINDING","FINE","FINGER","FINISH","FIRE","FIRM","FIRST","FISH","FIT","FIX","FLAT","FLIGHT","FLOOR","FLOW","FLOWER","FLY","FOCUS","FOLLOW","FOLLOWING","FOOD","FOOT","FOOTBALL","FOR","FORCE","FOREIGN","FOREST","FORGET","FORM","FORMAL","FORMER","FORWARD","FOUNDATION","FREE","FREEDOM","FREQUENTLY","FRESH","FRIEND","FROM","FRONT","FRUIT","FUEL","FULL","FULLY","FUNCTION","FUND","FUNNY","FURTHER","FUTURE","GAIN","GAME","GARDEN","GAS","GATE","GATHER","GENERAL","GENERALLY","GENERATE","GENERATION","GENTLEMAN","GET","GIRL","GIVE","GLASS","GO","GOAL","GOD","GOLD","GOOD","GOVERNMENT","GRANT","GREAT","GREEN","GREY","GROUND","GROUP","GROW","GROWING","GROWTH","GUEST","GUIDE","GUN","HAIR","HALF","HALL","HAND","HANDLE","HANG","HAPPEN","HAPPY","HARD","HARDLY","HATE","HAVE","HE","HEAD","HEALTH","HEAR","HEART","HEAT","HEAVY","HELL","HELP","HENCE","HER","HERE","HERSELF","HIDE","HIGH","HIGHLY","HILL","HIM","HIMSELF","HIS","HISTORICAL","HISTORY","HIT","HOLD","HOLE","HOLIDAY","HOME","HOPE","HORSE","HOSPITAL","HOT","HOTEL","HOUR","HOUSE","HOUSEHOLD","HOUSING","HOW","HOWEVER","HUGE","HUMAN","HURT","HUSBAND","I","IDEA","IDENTIFY","IF","IGNORE","ILLUSTRATE","IMAGE","IMAGINE","IMMEDIATE","IMMEDIATELY","IMPACT","IMPLICATION","IMPLY","IMPORTANCE","IMPORTANT","IMPOSE","IMPOSSIBLE","IMPRESSION","IMPROVE","IMPROVEMENT","IN","INCIDENT","INCLUDE","INCLUDING","INCOME","INCREASE","INCREASED","INCREASINGLY","INDEED","INDEPENDENT","INDEX","INDICATE","INDIVIDUAL","INDUSTRIAL","INDUSTRY","INFLUENCE","INFORM","INFORMATION","INITIAL","INITIATIVE","INJURY","INSIDE","INSIST","INSTANCE","INSTEAD","INSTITUTE","INSTITUTION","INSTRUCTION","INSTRUMENT","INSURANCE","INTEND","INTENTION","INTEREST","INTERESTED","INTERESTING","INTERNAL","INTERNATIONAL","INTERPRETATION","INTERVIEW","INTO","INTRODUCE","INTRODUCTION","INVESTIGATE","INVESTIGATION","INVESTMENT","INVITE","INVOLVE","IRON","IS","ISLAND","ISSUE","IT","ITEM","ITS","ITSELF","JOB","JOIN","JOINT","JOURNEY","JUDGE","JUMP","JUST","JUSTICE","KEEP","KEY","KID","KILL","KIND","KING","KITCHEN","KNEE","KNOW","KNOWLEDGE","LABOUR","LACK","LADY","LAND","LANGUAGE","LARGE","LARGELY","LAST","LATE","LATER","LATTER","LAUGH","LAUNCH","LAW","LAWYER","LAY","LEAD","LEADER","LEADERSHIP","LEADING","LEAF","LEAGUE","LEAN","LEARN","LEAST","LEAVE","LEFT","LEG","LEGAL","LEGISLATION","LENGTH","LESS","LET","LETTER","LEVEL","LIABILITY","LIBERAL","LIBRARY","LIE","LIFE","LIFT","LIGHT","LIKE","LIKELY","LIMIT","LIMITED","LINE","LINK","LIP","LIST","LISTEN","LITERATURE","LITTLE","LIVE","LIVING","LOAN","LOCAL","LOCATION","LONG","LOOK","LORD","LOSE","LOSS","LOT","LOVE","LOVELY","LOW","LUNCH","MACHINE","MAGAZINE","MAIN","MAINLY","MAINTAIN","MAJOR","MAJORITY","MAKE","MALE","MAN","MANAGE","MANAGEMENT","MANAGER","MANNER","MANY","MAP","MARK","MARKET","MARRIAGE","MARRIED","MARRY","MASS","MASTER","MATCH","MATERIAL","MATTER","MAY","MAYBE","ME","MEAL","MEAN","MEANING","MEANS","MEANWHILE","MEASURE","MECHANISM","MEDIA","MEDICAL","MEET","MEETING","MEMBER","MEMBERSHIP","MEMORY","MENTAL","MENTION","MERELY","MESSAGE","METAL","METHOD","MIDDLE","MIGHT","MILE","MILITARY","MILK","MIND","MINE","MINISTER","MINISTRY","MINUTE","MISS","MISTAKE","MODEL","MODERN","MODULE","MOMENT","MONEY","MONTH","MORE","MORNING","MOST","MOTHER","MOTION","MOTOR","MOUNTAIN","MOUTH","MOVE","MOVEMENT","MUCH","MURDER","MUSEUM","MUSIC","MUST","MY","MYSELF","NAME","NARROW","NATION","NATIONAL","NATURAL","NATURE","NEAR","NEARLY","NECESSARILY","NECESSARY","NECK","NEED","NEGOTIATION","NEIGHBOUR","NEITHER","NETWORK","NEVER","NEVERTHELESS","NEW","NEWS","NEWSPAPER","NEXT","NICE","NIGHT","NO","NOBODY","NOD","NOISE","NONE","NOR","NORMAL","NORMALLY","NORTH","NORTHERN","NOSE","NOT","NOTE","NOTHING","NOTICE","NOTION","NOW","NUCLEAR","NUMBER","NURSE","OBJECT","OBJECTIVE","OBSERVATION","OBSERVE","OBTAIN","OBVIOUS","OBVIOUSLY","OCCASION","OCCUR","ODD","OF","OFF","OFFENCE","OFFER","OFFICE","OFFICER","OFFICIAL","OFTEN","OIL","OKAY","OLD","ON","ONCE","ONE","ONLY","ONTO","OPEN","OPERATE","OPERATION","OPINION","OPPORTUNITY","OPPOSITION","OPTION","OR","ORDER","ORDINARY","ORGANISATION","ORGANISE","ORGANIZATION","ORIGIN","ORIGINAL","OTHER","OTHERWISE","OUGHT","OUR","OURSELVES","OUT","OUTCOME","OUTPUT","OUTSIDE","OVER","OVERALL","OWN","OWNER","PACKAGE","PAGE","PAIN","PAINT","PAINTING","PAIR","PANEL","PAPER","PARENT","PARK","PARLIAMENT","PART","PARTICULAR","PARTICULARLY","PARTLY","PARTNER","PARTY","PASS","PASSAGE","PAST","PATH","PATIENT","PATTERN","PAY","PAYMENT","PEACE","PENSION","PEOPLE","PER","PERCENT","PERFECT","PERFORM","PERFORMANCE","PERHAPS","PERIOD","PERMANENT","PERSON","PERSONAL","PERSUADE","PHASE","PHONE","PHOTOGRAPH","PHYSICAL","PICK","PICTURE","PIECE","PLACE","PLAN","PLANNING","PLANT","PLASTIC","PLATE","PLAY","PLAYER","PLEASE","PLEASURE","PLENTY","PLUS","POCKET","POINT","POLICE","POLICY","POLITICAL","POLITICS","POOL","POOR","POPULAR","POPULATION","POSITION","POSITIVE","POSSIBILITY","POSSIBLE","POSSIBLY","POST","POTENTIAL","POUND","POWER","POWERFUL","PRACTICAL","PRACTICE","PREFER","PREPARE","PRESENCE","PRESENT","PRESIDENT","PRESS","PRESSURE","PRETTY","PREVENT","PREVIOUS","PREVIOUSLY","PRICE","PRIMARY","PRIME","PRINCIPLE","PRIORITY","PRISON","PRISONER","PRIVATE","PROBABLY","PROBLEM","PROCEDURE","PROCESS","PRODUCE","PRODUCT","PRODUCTION","PROFESSIONAL","PROFIT","PROGRAM","PROGRAMME","PROGRESS","PROJECT","PROMISE","PROMOTE","PROPER","PROPERLY","PROPERTY","PROPORTION","PROPOSE","PROPOSAL","PROSPECT","PROTECT","PROTECTION","PROVE","PROVIDE","PROVIDED","PROVISION","PUB","PUBLIC","PUBLICATION","PUBLISH","PULL","PUPIL","PURPOSE","PUSH","PUT","QUALITY","QUARTER","QUESTION","QUICK","QUICKLY","QUIET","QUITE","RACE","RADIO","RAILWAY","RAIN","RAISE","RANGE","RAPIDLY","RARE","RATE","RATHER","REACH","REACTION","READ","READER","READING","READY","REAL","REALISE","REALITY","REALIZE","REALLY","REASON","REASONABLE","RECALL","RECEIVE","RECENT","RECENTLY","RECOGNISE","RECOGNITION","RECOGNIZE","RECOMMEND","RECORD","RECOVER","RED","REDUCE","REDUCTION","REFER","REFERENCE","REFLECT","REFORM","REFUSE","REGARD","REGION","REGIONAL","REGULAR","REGULATION","REJECT","RELATE","RELATION","RELATIONSHIP","RELATIVE","RELATIVELY","RELEASE","RELEVANT","RELIEF","RELIGION","RELIGIOUS","RELY","REMAIN","REMEMBER","REMIND","REMOVE","REPEAT","REPLACE","REPLY","REPORT","REPRESENT","REPRESENTATION","REPRESENTATIVE","REQUEST","REQUIRE","REQUIREMENT","RESEARCH","RESOURCE","RESPECT","RESPOND","RESPONSE","RESPONSIBILITY","RESPONSIBLE","REST","RESTAURANT","RESULT","RETAIN","RETURN","REVEAL","REVENUE","REVIEW","REVOLUTION","RICH","RIDE","RIGHT","RING","RISE","RISK","RIVER","ROAD","ROCK","ROLE","ROLL","ROOF","ROOM","ROUND","ROUTE","ROW","ROYAL","RULE","RUN","RURAL","SAFE","SAFETY","SALE","SAME","SAMPLE","SATISFY","SAVE","SAY","SCALE","SCENE","SCHEME","SCHOOL","SCIENCE","SCIENTIFIC","SCIENTIST","SCORE","SCREEN","SEA","SEARCH","SEASON","SEAT","SECOND","SECONDARY","SECRETARY","SECTION","SECTOR","SECURE","SECURITY","SEE","SEEK","SEEM","SELECT","SELECTION","SELL","SEND","SENIOR","SENSE","SENTENCE","SEPARATE","SEQUENCE","SERIES","SERIOUS","SERIOUSLY","SERVANT","SERVE","SERVICE","SESSION","SET","SETTLE","SETTLEMENT","SEVERAL","SEVERE","SEX","SEXUAL","SHAKE","SHALL","SHAPE","SHARE","SHE","SHEET","SHIP","SHOE","SHOOT","SHOP","SHORT","SHOT","SHOULD","SHOULDER","SHOUT","SHOW","SHUT","SIDE","SIGHT","SIGN","SIGNAL","SIGNIFICANCE","SIGNIFICANT","SILENCE","SIMILAR","SIMPLE","SIMPLY","SINCE","SING","SINGLE","SIR","SISTER","SIT","SITE","SITUATION","SIZE","SKILL","SKIN","SKY","SLEEP","SLIGHTLY","SLIP","SLOW","SLOWLY","SMALL","SMILE","SO","SOCIAL","SOCIETY","SOFT","SOFTWARE","SOIL","SOLDIER","SOLICITOR","SOLUTION","SOME","SOMEBODY","SOMEONE","SOMETHING","SOMETIMES","SOMEWHAT","SOMEWHERE","SON","SONG","SOON","SORRY","SORT","SOUND","SOURCE","SOUTH","SOUTHERN","SPACE","SPEAK","SPEAKER","SPECIAL","SPECIES","SPECIFIC","SPEECH","SPEED","SPEND","SPIRIT","SPORT","SPOT","SPREAD","SPRING","STAFF","STAGE","STAND","STANDARD","STAR","START","STATE","STATEMENT","STATION","STATUS","STAY","STEAL","STEP","STICK","STILL","STOCK","STONE","STOP","STORE","STORY","STRAIGHT","STRANGE","STRATEGY","STREET","STRENGTH","STRIKE","STRONG","STRONGLY","STRUCTURE","STUDENT","STUDIO","STUDY","STUFF","STYLE","SUBJECT","SUBSTANTIAL","SUCCEED","SUCCESS","SUCCESSFUL","SUCH","SUDDENLY","SUFFER","SUFFICIENT","SUGGEST","SUGGESTION","SUITABLE","SUM","SUMMER","SUN","SUPPLY","SUPPORT","SUPPOSE","SURE","SURELY","SURFACE","SURPRISE","SURROUND","SURVEY","SURVIVE","SWITCH","SYSTEM","TABLE","TAKE","TALK","TALL","TAPE","TARGET","TASK","TAX","TEA","TEACH","TEACHER","TEACHING","TEAM","TEAR","TECHNICAL","TECHNIQUE","TECHNOLOGY","TELEPHONE","TELEVISION","TELL","TEMPERATURE","TEND","TERM","TERMS","TERRIBLE","TEST","TEXT","THAN","THANK","THANKS","THAT","THE","THEATRE","THEIR","THEM","THEME","THEMSELVES","THEN","THEORY","THERE","THEREFORE","THESE","THEY","THIN","THING","THINK","THIS","THOSE","THOUGH","THOUGHT","THREAT","THREATEN","THROUGH","THROUGHOUT","THROW","THUS","TICKET","TIME","TINY","TITLE","TO","TODAY","TOGETHER","TOMORROW","TONE","TONIGHT","TOO","TOOL","TOOTH","TOP","TOTAL","TOTALLY","TOUCH","TOUR","TOWARDS","TOWN","TRACK","TRADE","TRADITION","TRADITIONAL","TRAFFIC","TRAIN","TRAINING","TRANSFER","TRANSPORT","TRAVEL","TREAT","TREATMENT","TREATY","TREE","TREND","TRIAL","TRIP","TROOP","TROUBLE","TRUE","TRUST","TRUTH","TRY","TURN","TWICE","TYPE","TYPICAL","UNABLE","UNDER","UNDERSTAND","UNDERSTANDING","UNDERTAKE","UNEMPLOYMENT","UNFORTUNATELY","UNION","UNIT","UNITED","UNIVERSITY","UNLESS","UNLIKELY","UNTIL","UP","UPON","UPPER","URBAN","US","USE","USED","USEFUL","USER","USUAL","USUALLY","VALUE","VARIATION","VARIETY","VARIOUS","VARY","VAST","VEHICLE","VERSION","VERY","VIA","VICTIM","VICTORY","VIDEO","VIEW","VILLAGE","VIOLENCE","VISION","VISIT","VISITOR","VITAL","VOICE","VOLUME","VOTE","WAGE","WAIT","WALK","WALL","WANT","WAR","WARM","WARN","WASH","WATCH","WATER","WAVE","WAY","WE","WEAK","WEAPON","WEAR","WEATHER","WEEK","WEEKEND","WEIGHT","WELCOME","WELFARE","WELL","WEST","WESTERN","WHAT","WHATEVER","WHEN","WHERE","WHEREAS","WHETHER","WHICH","WHILE","WHILST","WHITE","WHO","WHOLE","WHOM","WHOSE","WHY","WIDE","WIDELY","WIFE","WILD","WILL","WIN","WIND","WINDOW","WINE","WING","WINNER","WINTER","WISH","WITH","WITHDRAW","WITHIN","WITHOUT","WOMAN","WONDER","WONDERFUL","WOOD","WORD","WORK","WORKER","WORKING","WORKS","WORLD","WORRY","WORTH","WOULD","WRITE","WRITER","WRITING","WRONG","YARD","YEAH","YEAR","YES","YESTERDAY","YET","YOU","YOUNG","YOUR","YOURSELF","YOUTH" --------------------------------------------------------------------------------