ACSE-1

Exercise: Amicable numbers

The following code will work, although it could be improved in places. The parameter N controls how high the script searches.

""" Script to search for pairs of amicable numbers"""

# standard imports
import itertools
s
# numpy etc
import numpy as np

def prime_factors(x, primes=None):
    """Find the prime factors of an integer, x."""
    factors = []
    primes = primes_up_to(x, primes)
    if primes[-1]==x:
        return [x]
    while x>1:
        for p in primes:
            while x%p==0:
                factors.append(p)
                x/=p
    return factors

def primes_up_to(x, primes=None):
    """Find the primes up to the value x."""
    primes = primes or [2]
    test = primes[-1]+1
    while test<=x:
        for p in primes:
            if p**2>test:
                primes.append(test)
                break
            if test%p==0:
                break
        test += 1
    return primes


def all_factors(x, primes=None):
    """Find all the factors of the integer x."""
    pfs = prime_factors(x, primes)
    if not pfs:
        return [1]
    unique_primes = set(pfs)
    coefficients = []
    for p in unique_primes:
        # this could be more efficient (count isn't particularly fast)
        coefficients.append(tuple(range(pfs.count(p)+1)))

    all_factors = []

    # itertools.product gives every possible combination (a,b,c,...)
    # with a from its first argment, b from the 2nd, etc.
    for coeffs in itertools.product(*coefficients):
        all_factors.append(np.prod([up**c for up, c in zip(unique_primes,
                                                       coeffs)]))

    # x is not a factor of itself (this isn't very fast either).
    all_factors.remove(x)
    # no real need to sort, but it's neater.
    return sorted(all_factors)

N=10000
for i in range(N):
    # cache the primes we need before we start
    primes = primes_up_to(N)
    if i<2:
        continue
    y = sum(all_factors(i))
    if y<2:
        continue 
    k = sum(all_factors(y)) 
        
    if k==i and y>i:
        print(i, y)

Exercise: Alphabetized numbers

This one is mostly an exercise in book work, logic and conditionals, although we do some fun integer arithmatic. There are of course several different arrangements which will work equally well.
""" Output an alphabetized list of the numbers from 0 to 100 in words."""

ONES = {0:'zero',
        1:'one',
        2:'two',
        3:'three',
        4:'four',
        5:'five',
        6:'six',
        7:'seven',
        8:'eight',
        9:'nine'}

TENS={2:'twenty',
      3:'thirty',
      4:'forty',
      5:'fifty',
      6:'sixty',
      7:'seventy',
      8:'eighty',
      9:'ninety'}

EXTRAS={10:'ten',
        11:'eleven',
        12:'twelve',
        13:'thirteen',
        14:'fourteen',
        15:'fifteen',
        16:'sixteen',
        17:'seventeen',
        18:'eighteen',
        19:'nineteen'}

a = []

for i in range(101):
    s = ''
    hundreds = i//100
    tens = (i%100)//10
    ones = i%10
    if hundreds:
        s = ONES[hundreds]+' hundred'
        if hundreds and tens+ones>0:
            s +=' and '
    if tens==1:
        s += EXTRAS[10*tens+ones]
    elif tens>1:
        s+=TENS[tens]
        if ones:
            s+='-'
    if (not tens==1) and ones:
        s+=ONES[ones]
    if hundreds+tens+ones==0:
        s+='zero'

    a.append(s)

print(sorted(a))

Exercise: inverted image

This is actually an arrays problem, pretending to be a graphics problem.

There isn't really much code, but it's surprisingly tricky to write

"""Invert a .png and add a transparency gradient."""

# imports from the standard library
import sys

# numpy and friends
import matplotlib.pyplot as pyplot
import numpy as np

# read in the image.
X = pyplot.imread(sys.argv[1])

Y = np.empty((X.shape[0], X.shape[1], 4))


# we use meshgrid to get the linear gradient the right size.
x, y = np.meshgrid(np.linspace(1,1,X.shape[0]),
                   np.linspace(1,0,X.shape[1]))


# turn the image array upside down by slicing through the rows back to front.
Y[:,:,:3] = X[-1::-1,:,:3]
# set the alpha channel to the gradient
Y[:,:,3] = y

# all done, time to save.

base_name, extension = sys.argv[1].rsplit('.', 1)
pyplot.imsave(base_name+'_inverted.'+extension, Y)