CodeWords

Code, in words.

Project Euler Problem #12 Solution

leave a comment »

By the use of a theorem and a (relatively) efficient factorization algorithm, we can solve this problem fairly quickly. First, the theorem:

Theorem. If n = p_1^{\alpha_1} \cdots p_s^{\alpha_s}, then

\displaystyle d(n) = (\alpha_1 + 1)(\alpha_2 + 1) \cdots (\alpha_s + 1) = \prod_{i=1}^s (\alpha_i + 1).

This theorem tells us that if we can decompose n into its prime factors, we can efficiently calculate the number of divisors of n. It remains, therefore, for us to find a sufficiently efficient factorization algorithm. How about this:

def prime_factorization(n):
	divisor = 2
	while n > 1:
		factors = []
		while n % divisor == 0:
			factors.append(divisor)
			n /= divisor
		if factors:
			yield factors
		divisor += 1

This algorithm starts with a divisor of 2 and, if n is divisible by the divisor, it divides n by the divisor as long as n is still divisible by the divisor. When n no longer is, it increments the divisor and tries again until n is reduced to 1. Furthermore, each of the prime factors of n that equal each other are grouped into subsequences. That is, for n = 1701, we get [[3, 3, 3, 3, 3], [7]]. This makes it easier to use the theorem above.

We use a generator function to yield the triangle numbers, and a divisor-counting function that makes use of the theorem above, to get the desired number. All of the code, then, together, is:

def triangle_numbers():
	n = 1
	while True:
		yield n * (n + 1) / 2
		n += 1

def prime_factorization(n):
	candidate_factor = 2
	while n > 1:
		factors = []
		while n % candidate_factor == 0:
			factors.append(candidate_factor)
			n /= candidate_factor
		if factors:
			yield factors
		candidate_factor += 1

def count_divisors(n):
	count = 1
	for tuple in prime_factorization(n):
		count *= (len(tuple) + 1) 
	return count

for t in triangle_numbers():
	if count_divisors(t) > 500:
		print t
		break

Written by Jeff

13 February 2011 at 9:14 pm

Project Euler Problem #14 Solution

leave a comment »

We calculate the length of each Collatz sequence with starting number n \in [1, 10^6) \cap \mathbb{N} and find the value of n for which the length is maximum.

Note that we actually calculate one less than the length of each sequence, but since that subtraction is applied to each length, it doesn’t matter.

def is_even(n):
	return n % 2 == 0

def collatz_length(n):
	length = 0
	while n > 1:
		length += 1
		if is_even(n):
			n /= 2
		else:
			n = 3 * n + 1
	return length

max_n = 0
max_len = 0
for n in range(1, 1000000):
	len = collatz_length(n)
	if len > max_len:
		max_len = len
		max_n = n

print max_n

Written by Jeff

11 February 2011 at 10:21 pm

Project Euler Problem #24 Solution

leave a comment »

This code gets the millionth lexicographic permutation of (0, 1, 2, 3, 4, 5, 6, 7, 8, 9):

from itertools import permutations

MILLIONTH = 10 ** 6 - 1

print reduce(lambda x, y: str(x) + str(y), list(permutations(range(10), 10))[MILLIONTH])

Written by Jeff

8 February 2011 at 8:56 pm

Project Euler Problem #29 Solution

leave a comment »

Pretty self-explanatory:

import itertools

products = set()

for pair in itertools.product(range(2, 101), range(2, 101)):
	products.add(pair[0] ** pair[1])

print len(products)

This code takes advantage of the fact that the set object silently rejects duplicates when an attempt is made to add one.

Written by Jeff

7 February 2011 at 9:39 pm

Project Euler Problem #56 Solution

leave a comment »

We effectively search a 100 × 100 grid and find the cell with the greatest digital sum. Using some functional magic, we can do this:

from itertools import *

pairs = product(range(1, 100), range(1, 100))
exponentials = imap(lambda pair: pair[0] ** pair[1], pairs)
strings = imap(lambda exponential: str(exponential), exponentials)
sums = imap(lambda string: sum(map(lambda digit: int(digit), string)), strings)

print max(sums)

Written by Jeff

6 February 2011 at 4:30 pm

Project Euler Problem #28 Solution

leave a comment »

This algorithm calculates the sum of the diagonal numbers in a 1001 × 1001 spiral:

current = 0
step = 2

sum = 0
limit = 1001 ** 2

spiral = range(1, limit + 1)

while current < limit:
	for i in range(4):
		if current > limit:
			break
		sum += spiral[current]
		current += step
	step += 2

print sum

Written by Jeff

6 February 2011 at 4:30 pm

Project Euler Problem #40 Solution

leave a comment »

Simple:

digits = ""

for n in range(1, 1000001):
	digits += str(n)

product = 1
for i in range(7):
	product *= int(digits[10 ** i - 1])

print product

Written by Jeff

6 February 2011 at 4:30 pm

Project Euler Problem #53 Solution

leave a comment »

Simply iterate over each _nC_r where 1 \le n \le 100 and 1 \le r \le n and count which ones are greater than 1,000,000. In Python:

import operator

def factorial(n):
	return 1 if n == 0 else reduce(operator.mul, range(1, n + 1))

def combo(n, r):
	return factorial(n) / (factorial(r) * factorial(n - r))

count = 0

for n in range(1, 101):
	for r in range(1, n):
		if combo(n, r) > 1000000:
			count += 1

print count

Written by Jeff

6 February 2011 at 4:30 pm

Project Euler Problem #42 Solution

leave a comment »

Read the file of words, calculate their scores, and see which are triangular numbers. Note the use of an iterator function on line 4:

CAPITAL_LETTER_A = 'A'
COMMA = ","

def triangular_numbers():
	n = 1
	while True:
		yield n * (n + 1) / 2
		n += 1

def score_char(char):
	return ord(char) - ord(CAPITAL_LETTER_A) + 1

def score(word):
	return sum(map(score_char, word))

def is_triangular(num):
	for n in triangular_numbers():
		if n > num:
			return False;
		else:
			if n == num:
				return True
	return False

with open("words.txt") as f:
	text = f.read()
	words = map(lambda word: word[1:-1], text.strip().split(COMMA))
	scores = map(lambda word: score(word), words)
	
	print len(filter(lambda score: is_triangular(score), scores))

Written by Jeff

5 February 2011 at 8:58 pm

Project Euler Problem #45 Solution

leave a comment »

This program starts at n = 286 and calculates triangle numbers from that point, checking whether the triangle number is also pentagonal and hexagonal:

public static void Main(string[] args)
{
    for (var n = 286L; ; n++)
    {
        var triangleNumber = TriangleNumber(n);
        if (IsPentagonal(triangleNumber) && IsHexagonal(triangleNumber))
        {
            Console.WriteLine(triangleNumber);
            break;
        }
    }
    Console.ReadKey();
}

public static bool IsPentagonal(long triangleNumber)
{
    var pentagonal = 0L;
    for (var n = 1L; pentagonal <= triangleNumber; n++)
    {
        pentagonal = n * (3 * n - 1) / 2;
        if (pentagonal == triangleNumber)
            return true;
    }
    return false;
}

public static bool IsHexagonal(long triangleNumber)
{
    var hexagonal = 0L;
    for (var n = 1L; hexagonal <= triangleNumber; n++)
    {
        hexagonal = n * (2 * n - 1);
        if (hexagonal == triangleNumber)
            return true;
    }
    return false;
}

private static long TriangleNumber(long n)
{
    return n * (n + 1) / 2;
}

Written by Jeff

5 February 2011 at 3:16 pm

Follow

Get every new post delivered to your Inbox.