Archivio

Archivio per la categoria ‘Project Euler’

Project Euler #53

21 Dicembre 2012 Commenti chiusi
There are exactly ten ways of selecting three from five, 12345:
123, 124, 125, 134, 135, 145, 234, 235, 245, and 345

In combinatorics, we use the notation, 5C3 = 10.
In general,
nCr = n!/r!(n−r)!
,where r <= n, n! = n*(n-1)*...*3*2*1, and 0! = 1.

It is not until n = 23, that a value exceeds one-million: 23C10 = 1144066.
How many, not necessarily distinct, values of  nCr, for 1 <= n <= 100,
are greater than one-million?

python:

import time
from math import factorial as f

ts = time.time()

def extract(base, sel):
    return f(base)/(f(sel)*f(base - sel))

res = 0
for base in range(1, 101):
    for sel in range(1, base):
        ways = extract(base, sel)
        if ways > 10**6:
            res += 1

print "problem euler 53: {} \nelapsed time: {}sec".format(res, time.time() - ts)

Categorie:Project Euler, python Tag:

Project Euler #52

21 Dicembre 2012 Commenti chiusi
It can be seen that the number, 125874, and its double, 251748,
contain exactly the same digits, but in a different order.
Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x,
contain the same digits.

python:

import time

ts = time.time()

def is_magic(n):
    return sorted(str(n)) == sorted(str(2*n)) == sorted(str(3*n)) == \
           sorted(str(4*n)) == sorted(str(5*n)) == sorted(str(6*n))

res = 125874
while res > 0:
    if is_magic(res):
        break
    res += 1

print "problem euler 52: {} \nelapsed time: {}sec".format(res, time.time() - ts)
Categorie:Project Euler, python Tag:

Problem euler #55

19 Dicembre 2012 Commenti chiusi
If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.
Not all numbers produce palindromes so quickly. For example,

349 + 943 = 1292,
1292 + 2921 = 4213
4213 + 3124 = 7337

That is, 349 took three iterations to arrive at a palindrome.

Although no one has proved it yet, it is thought that some numbers, like 196,
never produce a palindrome. A number that never forms a palindrome through the
reverse and add process is called a Lychrel number. Due to the theoretical
nature of these numbers, and for the purpose of this problem, we shall assume
that a number is Lychrel until proven otherwise. In addition you are given that
for every number below ten-thousand, it will either (i) become a palindrome in
less than fifty iterations, or, (ii) no one, with all the computing power that
exists, has managed so far to map it to a palindrome. In fact, 10677 is the
first number to be shown to require over fifty iterations before producing a
palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).

Surprisingly, there are palindromic numbers that are themselves Lychrel
numbers; the first example is 4994.

How many Lychrel numbers are there below ten-thousand?

NOTE: Wording was modified slightly on 24 April 2007 to emphasise the
theoretical nature of Lychrel numbers.

Analisi:

python:

import time

ts = time.time()

def is_palindromic(n):
    return str(n) == str(n)[::-1]

def is_lychrel(n):
    sn = n
    count = 0
    while True:
        if is_palindromic(n) and count > 0:
            return False
        else:
            count += 1
            n += int(str(n)[::-1])
        if count > 50:
            return True

res = 0
for n in range(10, 10000):
    if is_lychrel(n):
        res += 1

print "problem euler 55: {} \nelapsed time: {}sec".format(res, time.time() - ts)
Categorie:Project Euler, python Tag:

Project euler #51

19 Dicembre 2012 Commenti chiusi
By replacing the 1st digit of *3, it turns out that six of the nine possible values:
13, 23, 43, 53, 73, and 83, are all prime.

By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit number
is the first example having seven primes among the ten generated numbers, yielding
the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993.
Consequently 56003, being the first member of this family,
is the smallest prime with this property.

Find the smallest prime which, by replacing part of the number
(not necessarily adjacent digits) with the same digit, is part of an eight prime value family.

Analisi:

1) Dal testo si deduce che le cifre da sostituire sono 3 o più.
2) Grazie a Google sappiamo che sostituendo 2 o 4 cifre al numero di 6 cifre,
non raggiungeremo mai una famiglia di 8 primi perchè si avrebbero numeri divisibili
per 3, quindi non primi (almeno 3):

test 2-4 cifre:

def three_divisible(low, hi, qty):
    results = []
    for n in range(low, hi):
        res = []
        for d in '0123456789':
            num = d * qty + str(n)
            a = sum([int(i) for i in str(num)])
            if a % 3 == 0:
                res.append(n)
        if len(res) <  3: # at least 8 primes
            results.append(res)
    return len(results)

for low, hi, qty in ((10, 99, 4), (1000, 9999, 2)):
    print 'length for non 3-divisible list with {} replaced dig : {}'.format(
        qty, three_divisible(low, hi, qty))

3) L’ultima cifra deve fare parte del gruppo ‘1379’ per non fare perdere
al numero di 6 cifre, la propria primalità.

Dobbiamo conoscere le varie combinazioni (posizioni) delle cifre da sostituire.
Ci avvaliamo di itertools:

for pattern in it.permutations('abxxx'):

nota:
la cifra c non la contemplo poichè la aggiungerò alla fine, sapendo che è limitata
al gruppo ‘1379’
Essendo le ‘x’ le cifre uguali pescate da ‘0123456789’, non mi rimane che ciclare
su ‘a’ e ‘b’, quindi da 11 a 99.

python:

import time
import itertools as it

ts = time.time()

def is_prime(num):
    if num <= 1: return False
    elif num == 2: return True
    elif num % 2 == 0: return False
    else:
        d = 3
        r = int(num**0.5)
        while d <= r:
            if num % d == 0: return False
            d += 2
        return True

def get_subs_primes(n, ptrn):
    pattern = ''.join(ptrn)
    digits = '0123456789'
    values = []
    sn = pattern.replace('a', n[0]).replace('b', n[1])
    for d in digits:
        snr = sn.replace('x', d) + n[2]
        if is_prime(int(snr)) and snr[0] != '0': # '0' leading excluded
            values.append(int(snr))
    return values

results = []
patterns = [''.join(p) for p in it.permutations('abxxx') # pattern combinations
            if ''.join(p).find('a') < ''.join(p).find('b')]
for pattern in patterns:
    for n in xrange(11, 99): # 'a' and 'b'
        for lastd in '1379': # last digit
            num = str(n) + lastd
            a = get_subs_primes(num, pattern)
            if len(a) == 8:
                results.append(min(a))
try:
    res = min(results)
    print "problem euler 51: {} \nelapsed time: {}sec".format(res, time.time() - ts)
except ValueError:
    print "No result found"


Categorie:Project Euler, python Tag:

Problem euler #50

12 Dicembre 2012 Commenti chiusi
The prime 41, can be written as the sum of six consecutive primes:
41 = 2 + 3 + 5 + 7 + 11 + 13
This is the longest sum of consecutive primes that adds to a prime below
one-hundred.
The longest sum of consecutive primes below one-thousand that adds to a prime,
contains 21 terms, and is equal to 953.
Which prime, below one-million, can be written as the sum of the most
consecutive primes?

Analisi:

Con un ordine di grandezza di un milione di primi, ho optato per un generatore.
Ho creato anche una lista di numeri primi limitata, da usare come punto di partenza
per i generatori di primi.
In sostanza ciclo sui vari punti di partenza per originare i miei generatori.
Prima utilizzo un generatore con range (2, limite max), poi range (3, limite max),
range (5, limite max) e così via.
Da ogni generatore, sommo tutti i primi fino al limite stabilito (10**6).
Quando la somma è un primo ed è l’ultima prima del limite, memorizzo il numero
di primi che ho sommato ed il valore della somma ottenuta, su due variabili
esterne ai cicli innestati.
Poi proseguo con un nuovo generatore che parta da un primo maggiore.
Alla fine dei cicli for, avrò la massima somma per il numero massimo di
primi consecutivi.
Il tiro dei limiti massimi, è stato aggiustato una volta trovato il risultato.
Potrebbe essere affinato ancora, ma il tempo di esecuzione è più che soddisfacente.

python:

import time

ts = time.time()

def is_prime(num):
    if num <= 1: return False
    elif num == 2: return True
    elif num % 2 == 0: return False
    else:
        d = 3
        r = int(num**0.5)
        while d <= r:
            if num % d == 0: return False
            d += 2
        return True

limit = 10**4
start = [x for x in xrange(1, 10) if is_prime(x)]

maxsum = cmax = 0
for s in start:
    primes = (x for x in xrange(s, limit) if is_prime(x))
    count = 0
    psum = 0
    for p in primes:
        psum += p
        count += 1
        if is_prime(psum) and psum < 10**6:
            if psum > maxsum:
                maxsum, cmax = psum, count

print maxsum, cmax       
print "problem euler 50: {} \nelapsed time: {}sec".format(maxsum, time.time() - ts)

Categorie:Project Euler, python Tag:

Problem euler #49

11 Dicembre 2012 Commenti chiusi
The arithmetic sequence, 1487, 4817, 8147, in which each of the terms
increases by 3330, is unusual in two ways: (i) each of the three terms
are prime, and, (ii) each of the 4-digit numbers are permutations of one
another.

There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes,
exhibiting this property, but there is one other 4-digit increasing sequence.

What 12-digit number do you form by concatenating the three terms in this
sequence?

Analisi:

Per prima cosa ho creato una lista di primi di 4 cifre, partendo da 1009.
Seconda cosa ho creato un dizionario con le permutazioni di ogni primo.
Poi ciclando sulle chiavi del dizionario, ho estratto i valori:
chiave, valore_1, valore_2 per i quali la differenza è sempre la
stessa.
In pratica ogni valore di una chiave viene sottratto con tutti gli
altri valori della stessa chiave. Ogni differenza, viene aggiunta ad
una lista di appoggio solo se assente dalla lista stessa.
Se la differenza è già in lista, allora ho trovato la terzina.

python:

import time
from itertools import permutations as perm 
ts = time.time()

def is_prime(num):
    if num <= 1: return False
    elif num == 2: return True
    elif num % 2 == 0: return False
    else:
        d = 3
        r = int(num**0.5)
        while d <= r:
            if num % d == 0: return False
            d += 2
        return True
    
def prime_perm(n):
        '''List of n-permutations, n excleded'''
        return [int(''.join(i)) for i in perm(str(n)) if is_prime(int(''.join(i)))][1:]

def is_magic(d):
    for key in d:
        diffs = []
        for n in d[key]:
            for m in d[key]:
                if n<m: # equal digit numbers excluded
                    if not abs(n-m) in diffs:
                        diffs.append(abs(n-m))
                    elif m - n == n - key:
                        return '{}{}{}'.format(key, n, m)
            
primes = [x for x in xrange(1009, 10000, 2) if is_prime(x)]
dp = {p: sorted(set(prime_perm(p))) for p in primes}
dp.pop(1487) # example in problem test

res = is_magic(dp)
print "problem euler 49: {} \nelapsed time: {}sec".format(res, time.time() - ts)
Categorie:Project Euler, python Tag:

Problem euler #48

11 Dicembre 2012 Commenti chiusi
The series, 1^1 + 2^2 + 3^3 + ... + 10^10 = 10405071317.
Find the last ten digits of the series, 1^1 + 2^2 + 3^3 + ... + 1000^1000.

python:

import time

ts = time.time()

print "problem euler 48: {} \nelapsed time: {}sec".format(
          str(sum([i**i for i in xrange(1, 1001)]))[-10:], time.time() - ts)
Categorie:Project Euler, python Tag:

Problem Euler #47

10 Dicembre 2012 Commenti chiusi
The first two consecutive numbers to have two distinct prime factors are:

14 = 2 * 7
15 = 3 * 5

The first three consecutive numbers to have three distinct prime factors are:

644 = 2^2 * 7 * 23
645 = 3 * 5 * 43
646 = 2 * 17 * 19.

Find the first four consecutive integers to have four distinct primes factors.
What is the first of these numbers?

Analisi:
partiamo a ciclare dal minimo numero con 4 diversi fattori primi:
2*3*5*10 = 210

import time

ts = time.time()


def is_prime(num):
    if num <= 1: return False
    elif num == 2: return True
    elif num % 2 == 0: return False
    else:
        d = 3
        r = int(num**0.5)
        while d <= r:
            if num % d == 0: return False
            d += 2
        return True

primes = [pr for pr in xrange(1, 1000000) if is_prime(pr)]

def get_factors(n):
    factors = set()
    while n > 1:
        for p in primes:
            if n % p == 0:
                factors.add(p)
                n /= p
                break
    return factors


count = 1
res = 210 # 2*3*5*7
while count != 4:
    res += 1
    if len(get_factors(res)) == 4:
        count += 1
    else:
        count = 0

print "problem euler 47: {} \nelapsed time: {}sec".format(res-3, time.time() - ts)
Categorie:Project Euler, python Tag:

Problem Euler #46

7 Dicembre 2012 Commenti chiusi
It was proposed by Christian Goldbach that every odd composite number
can be written as the sum of a prime and twice a square.

9 = 7 + 2*1^2
15 = 7 + 2*2^2
21 = 3 + 2*3^2
25 = 7 + 2*3^2
27 = 19 + 2*2^2
33 = 31 + 2*1^2

It turns out that the conjecture was false.
What is the smallest odd composite that cannot be written as the sum of a
prime and twice a square?

python:

import time

ts = time.time()

def is_prime(num):
    if num <= 1: return False
    elif num == 2: return True
    elif num % 2 == 0: return False
    else:
        d = 3
        r = int(num**0.5)
        while d <= r:
            if num % d == 0: return False
            d += 2
        return True

def is_odd_goldbach(n):
    for prime in PRIMES:
        for m in xrange(1, 50):
            if n == prime + 2*m**2:
                return True
    return False

def odds_generator():
    n = 35
    while True:
        if not is_prime(n):
            yield n
        n += 2
            

PRIMES = [i for i in xrange(3, 10000) if is_prime(i)]

for n in odds_generator():
    if not is_odd_goldbach(n):
        res = n
        break

print "problem euler 41: {} \nelapsed time: {}sec".format(res, time.time() - ts)

Categorie:Project Euler, python Tag:

Problem Euler #45

7 Dicembre 2012 Commenti chiusi
riangle, pentagonal, and hexagonal numbers are generated by the following
formulae:
Triangle 	  	Tn=n(n+1)/2 	  	1, 3, 6, 10, 15, ...
Pentagonal 	  	Pn=n(3n-1)/2 	  	1, 5, 12, 22, 35, ...
Hexagonal 	  	Hn=n(2n-1) 	  	1, 6, 15, 28, 45, ...

It can be verified that T285 = P165 = H143 = 40755.
Find the next triangle number that is also pentagonal and hexagonal.

Analisi:

Analogamente al problema 44, dal testo sappiamo che la formula per calcolare un numero
pentagonale è:

Pn=n(3n-1)/2

per il numero triangolare:

Tn=n(n+1)/2

per il numero esagonale:

Hn=n(2n−1)

Da wikipedia ricaviamo le formule per sapere se un numero ‘n’, è
triangolare:

sqrt(8*n + 1) - 1)/2

e pentagonale:

sqrt(24*n + 1) + 1)/6

Ora basta ciclare sui soli numeri esagonali e verificare che il risultato sia
triangolare e pentagonale.

python:

import time
import math

ts = time.time()

def is_triangolar(n):
    res = (math.sqrt(8*n + 1) - 1)/2 # is n triangolar formulae
    return res % 1 == 0

def is_pentagonal(n):
    res = (math.sqrt(24*n + 1) + 1)/6 # is n pentagonal formulae
    return res % 1 == 0

def get_hexagonals():
    n = 144
    while True:
        yield n*(2*n - 1)
        n += 1
        
res = 40755
for i in get_hexagonals():
    if is_triangolar(i) and is_pentagonal(i):
        res = i
        break

print "problem euler 45: {} \nelapsed time: {}sec".format(res, time.time() - ts)

Categorie:Project Euler, python Tag: