The 3n+1 Problem

Consider the following algorithm to generate a sequence of numbers. Start with an integer n. If n is even, divide by 2. If n is odd, multiply by 3 and add 1. Repeat this process with the new value of n, terminating when n = 1. For example, the following sequence of numbers will be generated for n = 22: 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 It is conjectured (but not yet proven) that this algorithm will terminate at n = 1 for every integer n. Still, the conjecture holds for all integers up to at least 1, 000, 000. For an input n, the cycle-length of n is the number of numbers generated up to and including the 1. In the example above, the cycle length of 22 is 16. Given any two numbers i and j, you are to determine the maximum cycle length over all numbers between i and j, including both endpoints.

Sample Input
1 10
100 200
201 210
900 1000

Sample Output
1 10 20
100 200 125
201 210 89
900 1000 174


In [31]:
## memoization cache decorator
def memcache(f):
    cache = {}
    def _helper(arg):
        if arg not in cache:
            cache[arg] = f(arg)
        return cache[arg]
    return _helper
## test it
@memcache
def fib(n):
    if n == 0 or n == 1:
        return n
    else:
        return fib(n-1) + fib(n-2)
assert fib(10) == 55
%timeit fib(30)


1000000 loops, best of 3: 288 ns per loop

In [32]:
## get the cycle-length
@memcache
def cycle_len(n):
    if n == 1:
        return 1
    elif n % 2 == 0:
        return 1 + cycle_len(n / 2)
    else:
        return 1 + cycle_len(3 * n + 1)
assert cycle_len(22) == 16

In [33]:
def max_cycle_len(lower, upper):
    return max(map(cycle_len, xrange(lower, upper+1)))
assert max_cycle_len(1, 10) == 20
assert max_cycle_len(100, 200) == 125
assert max_cycle_len(201, 210) == 89
assert max_cycle_len(900, 1000) == 174

Minesweeper

Have you ever played Minesweeper? This cute little game comes with a certain op- erating system whose name we can’t remember. The goal of the game is to find where all the mines are located within a M × N field. The game shows a number in a square which tells you how many mines there are adjacent to that square. Each square has at most eight adjacent squares. The 4 × 4 field on the left contains two mines, each represented by a “*” character. If we represent the same field by the hint numbers described above, we end up with the field on the right:

    Sample Input
44 
    *... 
    .... 
    .*.. 
    .... 
35 
    **... 
    ..... 
    .*... 
00
Sample Output
Field #1:
*100
2210
1*10
1110
Field #2:
**100
33200
1*100


In [52]:
def wrap(grid, ROWS, COLS):
    return (['.' * (COLS+2)] +
           ['.'+r+'.' for r in grid] +
           ['.' * (COLS+2)])
def neighbor(r, c, grid):
    if grid[r][c] == '*':
        return '*'
    else:
        neighbors = [(-1,-1), (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0)]
        #print [n for n in map(lambda (dr,dc): grid[r+dr][c+dc], neighbors)]
        return str(len([n for n in map(lambda (dr,dc): grid[r+dr][c+dc], neighbors) if n == '*']))
def mines_counter(grid):
    grid = [r.strip() for r in grid.split("\n") if len(r) > 0]
    ROWS, COLS = len(grid), len(grid[0])
    wrapped_grid = wrap(grid, ROWS, COLS)
    #print wrapped_grid
    #print neighbor(1, 2, wrapped_grid)
    return ([''.join([neighbor(r+1, c+1, wrapped_grid) 
                for c in xrange(COLS)])
            for r in xrange(ROWS)])
print mines_counter("""
    *... 
    .... 
    .*.. 
    ....""")
print mines_counter("""
**... 
..... 
.*...
""")


['*100', '2210', '1*10', '1110']
['**100', '33200', '1*100']

In [ ]: