# Author : Stephane Vialette, LIGM, Universite Paris-Est Marne La Vallee

import intseqdb

# a function that return a function defining a generator
# for the Fibonacci nimbers: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
# http://fr.wikipedia.org/wiki/Suite_de_Fibonacci
def fibonacci_gen():
	def wrapper_fibonacci_gen():
		f_n_1 = 1 # F_{-1} = 1
		f_n = 0
		# F_0 = 0
		yield f_n
		while True:
			f_n_1, f_n = f_n, f_n + f_n_1
			yield f_n
	return wrapper_fibonacci_gen
# a function that returns defining a generator
# for the Catalan numbers: 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, ...
# http://fr.wikipedia.org/wiki/Nombre_de_Catalan
def catalan_gen():
	def wrapper_catalan_gen():
		i = 0
		val = 1
		while True:
			yield val
			val = val * (2 * (2*i + 1)) / (i + 2)
			i = i + 1

	# only return the function defining the generator
	return wrapper_catalan_gen

# a function that returns a function defining a generator
# for the powers of n: n^0, n^1, n^2, n^3, ...
def power_gen(n):
	def wrapper_power_gen():
		val = 1
		while True:
			yield val
			val = val * n
	# only return the function defining the generator
	return wrapper_power_gen


if __name__=='__main__':

	# create a database (only print the 10 first elements of each sequence)
	db = intseqdb.Database(10)
	# add some integer sequences into the database
	db.add_sequence(intseqdb.Sequence("Powers of 1", power_gen(1)))
	db.add_sequence(intseqdb.Sequence("Powers of 2", power_gen(2)))
	db.add_sequence(intseqdb.Sequence("Powers of 4", power_gen(4)))
	db.add_sequence(intseqdb.Sequence("Catalan numbers", catalan_gen()))
	db.add_sequence(intseqdb.Sequence("Fibonacci numbers", fibonacci_gen()))
	# print everything, i.e., all sequences stored in the database
	print '=*=*=*=*=*=*=*=*=*=*=*=*='
	print "number of sequences in the database: %d" % len(db)
	# db in iter context returns an iterator
	print 'iter(db):', iter(db)
	# example
	for sequence in db:
		print sequence
	print '=*=*=*=*=*=*=*=*=*=*=*=*='
	print 'all sequences which description contains \'Powers\' in their description'
	# Database.search_by_seq() returns an iterator
	print 'Database.search_by_name():', db.search_by_name('Power')
	# example
	for sequence in db.search_by_name('Power'):
		print sequence
	# search and print all sequences that begin as 1, 1
	print '=*=*=*=*=*=*=*=*=*=*=*=*='
	print 'all sequences that begin as 1, 1'
	# Database.search_by_seq() returns an iterator
	print 'Database.search_by_seq():', db.search_by_seq([1, 1])
	# example
	for sequence in db.search_by_seq([1, 1]):
		print sequence
	# search and print all sequences that begin as 1, 1, 2
	print '=*=*=*=*=*=*=*=*=*=*=*=*='
	print 'all sequences that begin as 1, 1, 2'
	for sequence in db.search_by_seq([1, 1, 2]):
		print sequence
	# search and print all sequences that begin as 1, 1, 2, 3
	print '=*=*=*=*=*=*=*=*=*=*=*=*='
	print 'all sequences that begin as 1, 1, 2, 3'

	for sequence in db.search_by_seq([1, 1, 2, 3]):
		print sequence
	print '=*=*=*=*=*=*=*=*=*=*=*=*='
	# search and print all sequences that begin as 1, 2 with maximum shift 3
	print 'all sequences that begin as 1, 2 with maximum shift 3'
	# Database.search_by_seq_with_shift() returns an iterator
	print 'Database.search_by_seq_with_shift():', db.search_by_seq_with_shift([1, 2], 3)
	for sequence in db.search_by_seq_with_shift([1, 2], 3):
		print sequence
	print '=*=*=*=*=*=*=*=*=*=*=*=*='
	

