Project Euler

Table of Contents

Answer

http://projecteuler.net/

    #1
    sum = 0
    for i in range(1,1000):
        if i % 3 == 0 or i % 5 == 0:
            sum += i
    print sum

    #--------------
    #sum = (s+e)*n/2=(d + d*int(x/d)) * int(x/d) /2
    #sum = d * int(x/d) * (1 + int(x/d)) / 2
    sum = 3*int(999/3)*(1+int(999/3))/2 + 
    5*int(999/5)*(1+int(999/5))/2 - 
    15*int(999/15)*(1+int(999/15))/2

    #2
    sum = 0
    a = 1
    b = 2
    while b < 4e6:
        if b % 2 == 0:
            sum += b
        next = a + b
        a = b
        b = next

    print sum
    #--------------
    """
    The Fibonacci series is:
    1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610...
    Now, replacing an odd number with O and an even with E, we get:
    O, O, E, O, O, E, O, O, E, O, O, E, O, O, E...
    And so each third number is even.  We don't need to calculate the odd numbers.
    Starting from an two odd terms x, y, the series is:
    x, y, x + y, x + 2y, 2x + 3y, 3x + 5y
    """

    x = y = 1
    sum = 0
    while ((x + y) < 4e6):
        sum += (x + y)
        x, y = x + 2 * y, 2 * x + 3 * y
        print  x,y
    print sum

    #3
    import math
    def isprime(num, primelist):
        num_sqrt = math.sqrt(num)
        for prime in primelist:
            if num % prime == 0:
                return 0
            if prime > num_sqrt:
                break
        return 1

    primelist = []
    primelist.append(2)
    lim = 600851475143
    i = 3
    ret = []
    while i < lim:
        if isprime(i, primelist):
            primelist.append(i)
            while lim % i == 0:
                lim = lim / i
                ret.append(i)
        i += 2

    ret.append(lim)
    print max(ret)

    #4
    import sys
    for upnum in range(999, 99, -1):
        str_num = str(upnum) + str(upnum)[::-1]
        for div in range(100, 1000):
            if int(str_num) % div == 0:
                res = int(str_num) / div
                if len(str(res)) == 3:
                    print str_num
                    sys.exit(0)

    #5
    ret_factor = []

    ret = 2
    ret_factor.append(2)

    def get_factor(num, factors):
        ret = num
        for i in factors:
            if ret % i == 0:
                ret /= i
        return ret

    for i in range(3, 20):
        if ret % i:
            new_factor = get_factor(i, ret_factor)
            ret_factor.append(new_factor)
            ret *= new_factor
    print ret

    #6
    # squre_sum = n(n+1)(2n+1)/6
    # sum = (1+n)*n/2
    def diff_num(n):
        sum = (1+n)*n/2
        squre_sum = n*(n+1)*(2*n+1)/6
        return sum**2 - squre_sum

    print diff_num(100)

    #7
    import math
    def isprime(num, primelist):
        num_sqrt = math.sqrt(num)
        for prime in primelist:
            if num % prime == 0:
                return 0
            if prime > num_sqrt:
                break
        return 1

    primelist = []
    primelist.append(2)

    i = 1
    number = 3
    while i < 10001:
        if isprime(number, primelist):
            primelist.append(number)
            i += 1
        number += 2
    print primelist[-1]

  #8
  def compute_product(digit_list, start):
      pdt = 1
      for i in range(5):
          pdt *= digit_list[start + i]
      return pdt

  digit_list = []

  with open('problem8.txt', 'r') as ifile:
      c = ifile.read(1)
      while c:
          if c == '\n':
              c = ifile.read(1)
              continue
          digit_list.append(int(c))
          c = ifile.read(1)
      ifile.close()

  max_product = 0
  i = 0
  while i < len(digit_list) - 5:
      if digit_list[i] == 0:
          i += 5
          continue
      product = compute_product(digit_list, i)
      if product > max_product:
          max_product = product
      i += 1
      print max_product

#9
import sys
for a in range(1, 500):
    for b in range(1, 500):
        c = 1000 - a - b
        if a ** 2 + b ** 2 == c ** 2:
            print a*b*c
            sys.exit(0)
"""
Without programming:

a= 2mn; b= m^2 -n^2; c= m^2 + n^2;
a + b + c = 1000;

2mn + (m^2 -n^2) + (m^2 + n^2) = 1000;
2mn + 2m^2 = 1000;
2m(m+n) = 1000;
m(m+n) = 500;

m>n;
m= 20; n= 5;

a= 200; b= 375; c= 425;
"""

#10
import math
def isprime(num, primelist):
    num_sqrt = math.sqrt(num)
    for prime in primelist:
        if num % prime == 0:
            return 0
        if prime > num_sqrt:
            break
    return 1

primelist = []
primelist.append(2)
i = 3
sum_primes = 2
while i < 2e6:
    if isprime(i, primelist):
        primelist.append(i)
        sum_primes += i
    i += 2
print sum_primes

#11
NUM_NUMBER = 4

def strlist_to_intlist(strlist):
    intlist = []
    for ie in strlist:
        intlist.append(int(ie))
    return intlist

def compute_right_product(grid, row, col, cols):
    product = 1
    if col + NUM_NUMBER - 1 >= cols:
        return product
    for j in range(col, col + NUM_NUMBER):
        product *= grid[row][j]
    return product

def compute_down_product(grid, row, col, rows):
    product = 1
    if row + NUM_NUMBER - 1 >= rows:
        return product
    for i in range(row, row + NUM_NUMBER):
        product *= grid[i][col]
    return product

def compute_diagonal_product(grid, row, col, rows, cols):
    right_diagonal = 1
    left_diagonal = 1
    if row + NUM_NUMBER - 1 < rows and col + NUM_NUMBER - 1 < cols:
        for i in range(NUM_NUMBER):
            right_diagonal *= grid[row + i][col + i]
    if row + NUM_NUMBER - 1 < rows and col - NUM_NUMBER + 1 >= 0:
        for i in range(NUM_NUMBER):
            left_diagonal *= grid[row + i][col - i]
    if right_diagonal > left_diagonal:
        return right_diagonal
    else:
        return left_diagonal


grid = []

with open('problem11.txt', 'r') as ifile:
    for line in ifile:
        line_list = line.strip('\n').split(' ')
        grid.append(strlist_to_intlist(line_list))

COLS = 20
ROWS = 20
max_product = 0
for i in range(COLS):
    for j in range(ROWS):
        right_product = compute_right_product(grid, i, j, COLS)
        down_product = compute_down_product(grid, i, j, ROWS)
        diagonal_product = compute_diagonal_product(grid, i, j, ROWS, COLS)
        for product in right_product, down_product, diagonal_product:
            if product > max_product:
                max_product = product
print max_product

#12
import math

def num_divisors(number):
    num = 2 # 1 and self
    number_sqrt = int(math.sqrt(number))

    if number % number_sqrt == 0:
        num += 1
    for i in range(2, number_sqrt):
        if number % i == 0:
            num += 2
    return num
LIM = 100000
tri_number = 0
for i in range(1, LIM):
    tri_number += i
    if num_divisors(tri_number) > 500:
        print tri_number
        break

#13
sum = 0
with open('problem13.txt', 'r') as ifile:
    for line in ifile:
        line = line.strip('\n')
        number = long(line)
        sum += number

print str(sum)[0:10]

#14
LIM = 1000000

chains_array = []
for i in range(0, LIM+1):
    chains_array.append(0)

max_num_chains = 0
max_start_num = 0
for i in range(2, LIM+1):
    num = i
    num_chains = 0
    while num != 1 and num >= i:
        num_chains += 1
        if num % 2 == 0:
            num /= 2
        else:
            num = (num*3) + 1
    chains_array[i] = num_chains + chains_array[num]
    if chains_array[i] > max_num_chains:
        max_num_chains = chains_array[i]
        max_start_num = i

print max_start_num, max_num_chains

#15
COLS = 21
ROWS = 21

routes_array = [[0 for j in range(COLS)] for i in range(COLS)]

for i in range(ROWS):
    routes_array[i][0] = 1
for j in range(COLS):
    routes_array[0][j] = 1

for i in range(1, ROWS):
    for j in range(1, COLS):
        routes_array[i][j] = routes_array[i-1][j] + routes_array[i][j-1]
print routes_array[ROWS-1][COLS-1]


#16
num = 2**1000
sum = 0
while num > 0:
    sum += num % 10
    num /= 10
print sum

#17
"""
number 1-9
3 + 3 + 5 +4 + 4 +3 +5 +5 +4 = 36

number 10-19
3 + 6 + 6 + 8 + 8 + 7 + 7 + 9 + 8 + 8 = 70

number 20-99
x0-x9: 10*(6 + 6 + 5 + 5 + 5 + 7 + 6 + 6) = 460
       8 * 36 = 288
460 + 288 = 748

number 1-99
36 + 70 + 748= 854

number 100-999
1. 100-199: 100*len(one)
   36 * 100 = 3600
2. 1-99, 9 times
   9 * 854 = 7686
3. 100, 200 - 900, 'hundred'
   7*9 = 63
4. "hundred and"  9*99 times
   9*99*10=8910
 3600 + 7686 + 63 + 8910= 20259

all:  854 + 20259 + 11 = 21124
"""


class ConvertToWords:
    __worddict = {}
    __ONETHOUSAND = 1000
    __ONEMILLION = 1000000

    def convert_to_words(self, number):
        if number < 0 or number > self.__ONEMILLION:
            raise ValueError("Out of range")
        self._ensure_worddict_init();
        return self._convert_to_words(number)

    def _ensure_worddict_init(self):
        if self.__worddict == {}:
            self.__worddict = {
                0: "zero",
                1: "one",
                2: "two",
                3: "three",
                4: "four",
                5: "five",
                6: "six",
                7: "seven",
                8: "eight",
                9: "nine",
                10: "ten",
                11: "eleven",
                12: "twelve",
                13: "thirteen",
                14: "fourteen",
                15: "fifteen",
                16: "sixteen",
                17: "seventeen",
                18: "eighteen",
                19: "nineteen",
                20: "twenty",
                30: "thirty",
                40: "forty",
                50: "fifty",
                60: "sixty",
                70: "seventy",
                80: "eighty",
                90: "ninety",
                100: "hundred",
                self.__ONETHOUSAND: "thousand",
                self.__ONEMILLION: "million"
                }


    def _convert_to_words(self, number):
        if 0 <= number and number <= 20:
            return self.__worddict[number]
        if 20 < number and number < 100:
            return self._process_tens(number)
        if 100 <= number and number < self.__ONETHOUSAND:
            return self. _process_hundreds(number)
        if self.__ONETHOUSAND <= number and number < self.__ONEMILLION:
            return self. _process_large_number(number, self.__ONETHOUSAND)

    def _process_tens(self, number):
        tens = (number / 10) * 10
        units = number % 10
        convert_words = self.__worddict[tens]
        if units > 0:
            convert_words += self.__worddict[units]
        return convert_words

    def _process_hundreds(self, number):
        hundreds = number / 100
        remainder = number % 100
        convert_words = self.__worddict[hundreds] + self.__worddict[100]
        if remainder > 0:
            convert_words += 'and'
            convert_words += self._convert_to_words(remainder)
        return convert_words

    def _process_large_number(self, number, base_unit):
        number_of_baseunit = number / base_unit
        remainder = number % base_unit
        convert_words = self.__worddict[number_of_baseunit] + self.__worddict[base_unit]
        if remainder > 0:
            convert_words += 'and'
            convert_words += self._convert_to_words(remainder)
        return convert_words


sum_letters = 0
convet_to_words = ConvertToWords();
for i in range(1, 1001):
    sum_letters += len(convet_to_words.convert_to_words(i))

print sum_letters

#18
def strlist_to_intlist(strlist):
    intlist = []
    for c in strlist:
        intlist.append(int(c))
    return intlist


pre_counts = [0]

with open('problem18.txt', 'r') as ifile:
    for line in ifile:
        current_counts = line.strip('\n').split(' ')
        current_counts = strlist_to_intlist(current_counts)

        current_counts[0] += pre_counts[0]

        length_path = len(current_counts)
        for i in range(1, length_path-1):
            current_counts[i] += max(pre_counts[i-1], pre_counts[i])
        if length_path > 1:
            current_counts[length_path-1] += pre_counts[length_path-2]
        pre_counts = current_counts

print max(current_counts)

#19
def is_leap_year(year):
    if year % 400 == 0:
        return True
    elif year % 100 == 0:
        return False
    elif year % 4 == 0:
        return True
    else:
        return False

def days_of_month(isleap_year, month):

    if month in [9, 4, 6, 11]:
        return 30
    if month == 2:
        if isleap_year:
            return 29
        else:
            return 28
    else:
        return 31

num_sun_in_first_month = 0
days = 1
DAYS_ONE_WEEK = 7
for year in [1900]:
    isleap_year = is_leap_year(year)
    for month in range(2,13):
        days += days_of_month(isleap_year, month-1)

for year in range(1901, 2001):
    isleap_year = is_leap_year(year)
    for month in range(1, 13):
        days += days_of_month(isleap_year, month-1)
        if days % DAYS_ONE_WEEK == 0:
            num_sun_in_first_month += 1
print num_sun_in_first_month



#20
number_product = 1

for i in range(1, 101):
    number_product *= i

sum = 0
while number_product > 0:
    sum += number_product % 10
    number_product /= 10
print sum

#21
import math

def sum_proper_divisors(num):
    sum = 1
    sqrt_num = int(math.sqrt(num))
    for i in range(2, sqrt_num+1):
        if num % i == 0:
            sum += i
            sum += num / i
    if sqrt_num ** 2 == num:
        sum -= sqrt_num
    return sum

sum_all_amicable_numbers = 0
for i in range(4, 10000):
    temp_sum = sum_proper_divisors(i)
    if temp_sum != i and sum_proper_divisors(temp_sum) == i:
        sum_all_amicable_numbers += i

print sum_all_amicable_numbers

#22
def score_name(name):
    name = name.strip('"')
    score = 0
    ord_A = ord('A')
    for letter in name:
        score += ord(letter) - ord_A + 1
    return score


with open('names.txt', 'r') as ifile:
    line = ifile.readline()
    line_list = line.split(',')
    line_list.sort()

n = 1
total_name_scores = 0
for name in line_list:
    total_name_scores += n * score_name(name)
    n += 1

print total_name_scores

#23
import math
import bisect

def sum_proper_divisors(num):
    sum = 1
    sqrt_num = int(math.sqrt(num))
    for i in range(2, sqrt_num + 1):
        if num % i == 0:
            sum += i
            sum += num / i
    if sqrt_num ** 2 == num:
        sum -= sqrt_num
    return sum

def can_be_written(num, abundant_list):
    index_high =  bisect.bisect(abundant_list, num)
    i = 0
    j = index_high - 1
    while i <= j:
        sum_num = abundant_list[i] + abundant_list[j]
        if sum_num == num:
            return True
        elif sum_num < num:
            i += 1
        else:
            j -= 1
    return False

abundant_numbers = []
LIM = 28123
for i in range(1, LIM + 1):
    if sum_proper_divisors(i) > i:
        abundant_numbers.append(i)

sum_cannot_be_written = 0
for i in range(1, LIM + 1):
    if not can_be_written(i, abundant_numbers):
        sum_cannot_be_written += i
print sum_cannot_be_written

#24
import math

def nthPermutationCore(num_list, n, nth_num):
    len_sum = len(num_list) - 1
    fac_num = math.factorial(len_sum)
    if n < fac_num:
        nth_num += num_list[0]
        num_list.remove(num_list[0])
        return nthPermutationCore(num_list, n, nth_num)
    nth = n / fac_num
    nth_num += num_list[nth]
    num_list.remove(num_list[nth])
    n -= nth * fac_num
    if n == 0:
        return nth_num
    return nthPermutationCore(num_list, n, nth_num)

def nthPermutation(num_list, n):
    nth_num = ''
    nth_num = nthPermutationCore(num_list, n, nth_num)
    for i in range(len(num_list)):
        nth_num += num_list[i]
    return nth_num

num_list = []
for i in range(10):
    num_list.append(str(i))
print num_list

n_millionth_num = nthPermutation(num_list, 1000000 - 1)
print n_millionth_num

#25
a = 1
b = 1
i = 1
while a < 10**999:
    tmp = b
    b = a + b
    a = tmp
    i += 1
print i

#26
import math

def nReciprocalCycles(num):
    div = 1
    div_list = []
    len_res = 0
    div *= (10 ** (int(math.log(num/div, 10) + 1)))
    while True:
        div = div % num
        if div == 0:
            len_res = 0
            break
        if div in div_list:
            break
        div_list.append(div)
        n = int(math.log(num/div, 10)) + 1
        len_res += (n + 1)
        div *= (10 ** n)
    return len_res

max_len = 1
res = 0
for i in range(2, 1000):
    n = nReciprocalCycles(i)
    if n > max_len:
        max_len = n
        res = i
print res

#27
import math

def is_prime(num):
    if num <= 1:
        return False
    sqrt_num = int(math.sqrt(num))
    for i in range(2, sqrt_num + 1):
        if num % i == 0:
            return False
    return True

def consecutive_prime(a, b):
    n = 0
    while 1:
        ret = n ** 2 + a * n + b
        if not is_prime(ret):
            break
        n += 1
    return n

max_consecutive = 0
coeff_a = 0
coeff_b = 0
for a in range(-999, 1000, 2):
    if a < 0:
        start = -a
    else:
        start = 3
    for b in range(start, 1000, 2):
        n = consecutive_prime(a, b)
        if n > max_consecutive:
            max_consecutive = n
            coeff_a = a
            coeff_b = b
print coeff_a * coeff_b

#28

interval = 2
DIAGONAL_NUM = 4
sum_diagonals = 1
number = 1

while (interval + 1) <= 1001:
    for n in range(DIAGONAL_NUM):
        number += interval
        sum_diagonals += number
    interval += 2
print sum_diagonals

#29
from sets import Set
num_distinct_terms = 0

num_list = []
for i in range(0, 101):
    num_list.append(1)

i = 2
while i <= 100:
    if num_list[i] == 0:
        i += 1
        continue
    num_exp = 1
    num_set = Set([])
    while i ** num_exp <= 100:
        num_list[i ** num_exp] = 0
        for j in range(2*num_exp, 100*num_exp + 1, num_exp):
            num_set.add(j)
        num_exp += 1

    num_distinct_terms += len(num_set)
    i += 1

print num_distinct_terms

#30

def can_sum_of_fifth_powers(num):
    num_local = num
    sum_digits = 0
    while num_local > 0:
        r = num_local % 10
        num_local /= 10
        sum_digits += r ** 5
    if sum_digits == num:
        return True
    return False



upbound = 1
lim = 9 * 5 
sum_fifth_power = 0
num = 2
while num <= lim:
    if can_sum_of_fifth_powers(num):
        sum_fifth_power += num
    if num >= upbound:
        upbound *= 10 
        lim += 9 ** 5
    num += 1
print sum_fifth_power
#31
import copy
def compound_money(pound_list, currency, ways):
    if currency == 0:
        ways += 1
        return ways
    if not pound_list  or  len(pound_list) == 0:
        return ways
    store_pound_list = pound_list[1:]

    if currency >= pound_list[0]:
        ways = compound_money(pound_list, currency - pound_list[0], ways)

    ways = compound_money(store_pound_list, currency, ways)
    return ways

pound_list = [1, 2, 5 ,10, 20, 50, 100, 200]
currency = 200
ways = 0
ways = compound_money(pound_list, currency, 0)
print ways
#32
"""
m, n ==> (m+n)-1 or (m+n)
2(m+n)-1 = 9 or 2(m+n) = 9
m+n=5
m,n = 1, 4 or 2,3
"""
from sets import Set

def all_perms(str):
    if len(str) <= 1:
        yield str
    else:
        for perm in all_perms(str[1:]):
            for i in range(len(str)+1):
                yield perm[:i] + str[0:1] + perm[i:]

products = Set()

for perm in all_perms('123456789'):
    m_and_n = perm[:5]
    product = perm[5:]

    allowed_position = [1, 2]
    for pos in allowed_position:
        m = m_and_n[:pos]
        n = m_and_n[pos:]
        if int(m) * int (n) == int(product):
            products.add(int(product))

print sum(products)
#33
"""
(10i+n)/(10d+i) = n/d ==> 9d(n-i) = i(d-n)
d>n, then d>n>i
n - i = i/9 - in/9d
n - i >= 1
i < 9, i/9 - in/9d < 1, so this equation has no solution.

(10n+i)/(10i+d) = n/d ==> 9n(d-i) = i(n-d)
d > n then n<d<i
"""

def gcd(m, n):
    M = max(m,n)
    N = min(m,n)
    while(N != 0):
        R = M % N
        M = N
        N = R
    return M

product_numerator = 1
product_denominator = 1

for i in range(1, 10):
    for d in range(1, i):
        for n in range(1, d):
            if (10*n + i) * d == (10*i + d) * n:
                product_numerator *= n
                product_denominator *= d
print product_denominator / gcd(product_numerator, product_denominator)
#34
import math

math.factorial(2)

def is_curious_num(num):
    sum_factorial = 0
    m = num
    while m > 0:
        sum_factorial += math.factorial(m % 10)
        m /= 10
    if sum_factorial == num:
        return True
    else:
        return False

lim = math.factorial(9)
check_point = 100
number = 11
sum_numbers = 0
while number < lim:
    if is_curious_num(number):
        sum_numbers += number
    if number > check_point:
        check_point *= 10
        lim += math.factorial(9)
    number += 1
print sum_numbers
#35
import math
import sets
def all_circulars(str):
    for i in range(len(str)):
        yield str[i:] + str[:i]

def is_prime(number, primes_list):
    number_sqrt = int(math.sqrt(number))
    for factor in primes_list:
        if factor > (number_sqrt + 1):
            return True
        if number % factor == 0:
            return False
    while factor <= (number_sqrt + 1):
        if number % factor == 0:
            return False
        factor += 2
    return True

primes_list = [2]
circular_primes_list = sets.Set()
circular_primes_list.add('2')


for n in range(3, 1000000, 2):
    if str(n) in circular_primes_list:
        primes_list.append(n)
        continue
    if not is_prime(n, primes_list):
        continue
    primes_list.append(n)

    tmp_list = []
    is_circular = True
    for perm in all_circulars(str(n)):
        if not is_prime(int(perm), primes_list):
            is_circular = False
            break
        tmp_list.append(perm)
    if is_circular:
        for circular_prime in tmp_list:
            circular_primes_list.add(circular_prime)

print circular_primes_list
print len(circular_primes_list)
#36
def is_palindromic_base10(num):
    num_str = str(num)
    h = len(num_str) - 1
    l = 0
    while l < h:
        if num_str[l] != num_str[h]:
            return False
        l += 1
        h -= 1
    return True

def is_palindromic_base2(num):
    num_str = ''
    while (num / 2) != 0:
        if num % 2 == 1:
            num_str = '1' + num_str
        else:
            num_str = '0' + num_str
        num = num / 2
    num_str = '1' + num_str
    h = len(num_str) - 1
    l = 0
    while l < h:
        if num_str[l] != num_str[h]:
            return False
        l += 1
        h -= 1
    return True

sum = 0
for i in range(1, 1000000):
    if is_palindromic_base10(i) and is_palindromic_base2(i):
        sum += i
        print i
print sum
#37
import math

def isprime(num, primelist):
    num_sqrt = math.sqrt(num)
    for prime in primelist:
        if num % prime == 0:
            return False
        if prime > num_sqrt:
            break
    return True

def isPrime(num):
    if num == 1:
        return False

    num_sqrt = int(math.sqrt(num))
    i = 2
    while i <= num_sqrt:
        if num % i == 0:
            return False
        i += 1
    return True

def isTruncatablePrime(num):
    left_trunk = 0
    right_trunk = num
    multiplier = 1
    while right_trunk > 0:
        left_trunk += multiplier * (right_trunk % 10)
        right_trunk /= 10
        if not isPrime(left_trunk) or not isPrime(right_trunk):
            return False
        multiplier *= 10
    return True

primelist = [2, 3, 5, 7]
count = 0
sum = 0
num = 11
while count < 11:
    if isprime(num, primelist):
        primelist.append(num)
        if isTruncatablePrime(num):
            sum += num
            count += 1
    num += 2

print sum

Author: Shi Shougang

Created: 2015-03-05 Thu 23:20

Emacs 24.3.1 (Org mode 8.2.10)

Validate