import sys,time,random,re,math
sys.dont_write_bytecode=True # don't make .pyc files
from the import *
from demo import *

#---- Standard maths stuff -------------------------

e = math.e
log = math.log
any = random.uniform
rand = random.random
shuffle = random.shuffle

def weibull(x,l,k):
  if x <= 0: return 0
  k *= 1.0; x *= 1.0; l *= 1.0
  return k/l*((x/l)**(k-1))*e**(-1*(x/l)**k)

#---- Collection stuff -----------------------------

def first(x) : return x[0]
def second(x): return x[1]

def mostest(d, sortBy=second,reverse=True):
  "Return a dictionary string, sorted by values."
  l = [(k,v) for k,v in sorted(d.items())]
  l = sorted(l,key= sortBy,reverse=reverse)
  l = [':%s %s' % (k,v) for k,v in l]
  return ' '.join(l)

def median(l,ordered=False):
  if not ordered:
    lst = sorted(l)
  n = len(l)
  i = n/2
  return l[i] if n % 2 else (l[i] + l[i+1])/2.0

def pairs(lst):
  last=lst[0]
  for i in lst[1:]:
    yield last,i
    last = i

class AutoDict(dict):
  def __init__(i,default):
    i.default= default
  def __getitem__(i,key):
    if key in i:
      return i.get(key)
    return i.setdefault(key,i.default())


class Deep(dict):
  def __getitem__(i, item):  
    try:
      return dict.__getitem__(i, item)
    except KeyError:
      value = self[item] = type(i)()
      return value

#---- timing --------------------------
def msecs(f):
  t1 = time.time()
  f()
  return (time.time() - t1)*1000.0

#---- Stochastic sampling --------------------------

def resetSeed(n=The.math.seed): 
   """
   Important: before running any code
   that does any random sampling, reset the
   seed (so you can debug crashes)
   """
   random.seed(n)

def one(lst) :
  "Return any one item in a list"
  return lst[int(any(0,len(lst)))]

def few(lst,n):
  "Return any n items in a list, no repeats."
  m = len(lst)
  where = []
  for _ in range(n*5): # try a few times
    x = int(any(0,m))
    if not x in where: where += [x]
    if len(where) == n: break
  return [lst[x] for x in where]

def some(d,enough=10**32):
  """
  Given a dictionary d{k1=n1, k2=n2, ...},
  return enough keys ki at probability 
  pi = ni/n where n = n1+n2+..
  e.g.
     for key in some({'box':30,'circle':20,'line':10},20)
         print key
  
  will return around twice as many boxes as anything else,
  circles 1/3rd of the time and lines 1/6th of the time. 
  """
  n, lst = 0, []
  for x in d: 
    n   += d[x]
    lst += [(d[x],x)]
  lst = sorted(lst, reverse=True)
  while enough > 0:
    r = random.random()
    for freq,thing in lst:
      r -= freq*1.0/n
      if r <= 0:
        yield thing
        enough -= 1
        break

#---- Print stuff ----------------------------------

def gs(lst,f='%4.3f'):
  "Print a list of numbers in abbreviated format." 
  return ', '.join([f % x for x in lst])

def say(*lst):
  """"Write n arguments to standard output with 
   no new line at the end."""
  sys.stdout.write(','.join(map(str,lst)))
  sys.stdout.flush()

#---- Iterators  ---------------------------------

def item(x) : 
  "Return all non-list items in a nested list"
  if isinstance(x,(tuple,list)):
    for y in x:
      for z in item(y): yield z
  else: yield x

#---- plotting  ---------------------------------

def plot2d(x,y,xlabel="x",ylabel="y",
             title="Plot",file=None,
             width=3,
             height=3):
  "Print a 2d plot. If 'file' not given, show on screen"
  print title,file
  import matplotlib.pyplot as plt
  plt.xlabel(xlabel)
  plt.ylabel(ylabel)
  plt.title(title)
  plt.gcf().set_size_inches(width,height)
  plt.plot(x, y, 'ro')
  plt.subplots_adjust(bottom=0.2,left=0.2)
  plt.savefig(file) if file else plt.show()

