Project Euler – Problem 23 – Non-abundant sums

Problem

A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.

A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.

As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.

Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.

Solution

Solution based on 3 steps
– Generate abundant numbers
– Generate numbers which can be sum of two abundant numbers
– Minus them off the total sum up to upper limit

def proper_divisors(n):
    ns = [1]

    for i in range(2, int(n**0.5)+1):
        if not n%i: ns += [i, n/i]

    return sorted(set(ns))

def is_abundant(n):
    return sum(proper_divisors(n))>n

abds = [i for i in range(10, 28123) if is_abundant(i)]
abds_sum = []

while len(abds):
    abd = abds[0]
    for i in abds:
        if abd+i<28123: abds_sum.append(abd+i)
        else: break
    abds = abds[1:]

print sum(range(28123)) - sum(set(abds_sum))

Project Euler – Problem 24 – Lexicographic permutations

Problem

A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:

012   021   102   120   201   210

What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

Solution

ds = '0123456789'
n = ''

c = 1000000 # Counter
f = 1*2*3*4*5*6*7*8*9*10 # Factorial

### For 10 different places
for i in range(10):
    f /= 10-i

    ### If yet to reach perfect fit
    if c:
        p = c/f # position of the next character
        c %= f # left over positions

        ### If reach perfect fit
        ### means havent used up the next number
        if not c: p-=1
    else:
        p = len(ds)-1

    n += ds[p]
    ds = ds[:p]+ds[p+1:]

print n

Explanation

This solution generates the any lexicographic permutation of any group of digits. This is based on the simple logic of finding the next biggest number that fits the bill.

For example, there is 10 digits in total. This means that the first 362880(9!) terms will have the lowest number as the first digit, 0. The next 362880(9!) terms will have 1 as the first digit. That will cover up to the 725760th (362880*2) term. Hence the millionth term will have the next lowest digit 2 as the first digit.

Following that logic we will continue to find the subsequent digits. But there is a special case when the number of terms left is divisible by the number of possible permutations, this will give us a c value of 0 (refer to code).

What does that mean? Following the above example, when only 0, 4 and 6 are left, the millionth term is 4 terms away, and 2!(2) is just right a factor, so how does it work?

The permutations of 0, 4 and 6 is as follows:
046
064
406
460 (the one that we want)
604
640

Hence, as you can see, when the remaining permutations reaches 0, the digits are inserted from the largest to the smallest, hence 6 first then 0.

Project Euler – Problem 25 – 1000-digit Fibonacci number

Problem

The Fibonacci sequence is defined by the recurrence relation:

Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1.

Hence the first 12 terms will be:

F1 = 1
F2 = 1
F3 = 2
F4 = 3
F5 = 5
F6 = 8
F7 = 13
F8 = 21
F9 = 34
F10 = 55
F11 = 89
F12 = 144

The 12th term, F12, is the first term to contain three digits.

What is the index of the first term in the Fibonacci sequence to contain 1000 digits?

Solution

i, j = 1, 1
n = 2

while len(str(j))<1000:
    i, j = j, i+j
    n += 1
print n

Project Euler – Problem 22 – Names Score

Problem

Using names.txt (right click and ‘Save Link/Target As…’), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.

What is the total of all the name scores in the file?

Solution

names = sorted(["MARY","PATRICIA","LINDA","BARBARA","ELIZABETH", ...])

s = 0
for idx, name in enumerate(names):
    s += (idx+1)*sum([ord(c)-64 for c in name])
print s

Project Euler – Problem 21 – Amicable Numbers

Problem

Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.

For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.

Evaluate the sum of all the amicable numbers under 10000.

Solution

def d(n):
    ds = []
    for i in range(1, int(n**0.5)+1):
        if not n%i: ds += [i, n/i]
    return sum(set(ds))-n

ds = {}
for i in range(1, 10001): ds[i] = d(i)

amicable = []
for i in range(1, 10001):
    d1 = ds[i]
    if ds.get(d1)==i and ds[i]!=i: amicable += [d1, i]
print sum(set(amicable))

Project Euler – Problem 20 – Factorial Digit Sum

Problem

n! means n × (n − 1) × … × 3 × 2 × 1

For example, 10! = 10 × 9 × … × 3 × 2 × 1 = 3628800,
and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.

Find the sum of the digits in the number 100!

Solution

p = 1
for i in range(1, 100): p *= i
print sum([int(i) for i in str(p)])

Project Euler – Problem 19 – Counting Sundays

Problems

You are given the following information, but you may prefer to do some research for yourself.

  • 1 Jan 1900 was a Monday.
  • Thirty days has September,
    April, June and November.
    All the rest have thirty-one,
    Saving February alone,
    Which has twenty-eight, rain or shine.
    And on leap years, twenty-nine.
  • A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.

How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

Solution

Simple counting solution, but gotta take care the counting logic (storing the first of the month VS last day of previous month).

s = 0
d = 1 # 31 Dec 1900 was a Monday
for y in range(1901, 2001):
    for m in range(12):
        if d+1==7: s+= 1

        # n, number of days in that month
        if m==1:
            if y%400==0: n=29
            elif y%100==0: n=28
            elif y%4==0: n=29
            else: n=28
        elif m in [3, 5, 8, 10]: n = 30
        else: n = 31

        d = (d+n)%7
print s