def find_fuel(car):
    best = None
    best_len = 1e100
    best_solver = 'nobody'
    
    for f in [solve_brute_force, 
              solve_monte_carlo_size2,
              #solve_monte_carlo_size3,
              #solve_monte_carlo_size6,
              solve_LP]:
        print f,
        fuel = f(car)
        if fuel is not None:
            assert car.test_on_fuel(fuel), fuel
            l = len(fuel_to_stream(fuel))
            print 'solved', l
            if l < best_len:
                best_len = l
                best = fuel
                best_solver = f
            if f == solve_brute_force: # brute force always finds best solution
                break
        else:
            print
    
    who_solved[best_solver] += 1
    print 'solvers stats:'
    pprint(dict(who_solved))      
      
    return best
def find_fuel_stream(car):
    if USE_CACHE:
        load_cache()
        if car.representation in cache:
            return cache[car.representation]
    
    fuel = find_fuel(car)
    if fuel == None:
        return
        
    print(fuel) 
    suffix = fuel_to_stream(fuel)
    
    load_cache()
    cached = cache.get(car.representation)
    if cached is None or len(cached) > len(car.representation):
        cache[car.representation] = suffix
        save_cache()
    else:
        return cached
        
    return suffix
def solve_monte_carlo(car, size=2, timeout=1.0):
    best = None
    best_len = 1e100
    
    fuel = [zeros((size,size), dtype=object) for i in range(car.num_tanks)]

    start = clock()
    
    for attempt in xrange(10000000):
        if clock()-start > timeout:
            break
        for i in range(car.num_tanks):
            for j in range(size):
                for k in range(size):
                    fuel[i][j,k] = randrange(3)
            fuel[i][0,0] += 1
        if car.test_on_fuel(fuel):
            l = len(fuel_to_stream(fuel))
            if l < best_len:
                best_len = l
                best = deepcopy(fuel)
                 
    return best
from time import clock
from math import *
from itertools import *

from car import fuel_to_stream, numpy_fuel

print 'prepairing fuels for brute force...',
fuels_to_search = {}
for i in range(1, 7):
    n = 40000
    limit = int(0.5 + exp(log(n)/i))
    
    fuels = list(product(*[range(1,limit)]*i))
    fuel_lens = dict((fuel,len(fuel_to_stream(list(fuel)))) for fuel in fuels)

    fuels = sorted(fuels, key = fuel_lens.get)
    #print [(f, fuel_lens[f]) for f in fuels[:10]]
    fuels_to_search[i] = map(numpy_fuel, fuels)
print 'done'     

def solve_brute_force(car):
    timeout = 1.0
    start = clock()
    
    for fuel in fuels_to_search[car.num_tanks]:
        if clock()-start > timeout:
            break
        if car.test_on_fuel(fuel):
            return list(fuel)