From 96aa2f2ace38ddabfac05376738f3d41ee710ef6 Mon Sep 17 00:00:00 2001 From: Sanjay Krishnan Date: Wed, 7 Apr 2021 11:53:35 -0500 Subject: [PATCH] correct schedule for this quarter --- hw2/README.md | 109 +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------ hw2/analyze.py | 14 ++++++++++++++ hw2/auto_grader.py | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------- hw2/core.py | 41 +++++++++++++++++++++++++++++++++++++++++ hw2/data.txt | 10000 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- hw2/encoding.py | 59 ----------------------------------------------------------- hw3/README.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------- hw3/auto_grader.py | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------ hw3/bloom.py | 49 ------------------------------------------------- hw3/data.txt | 10000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw3/encoding.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw4/README.md | 100 +++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------- hw4/analyze.py | 14 -------------- hw4/auto_grader.py | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------- hw4/bloom.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ hw4/core.py | 41 ----------------------------------------- 16 files changed, 10534 insertions(+), 10534 deletions(-) create mode 100644 hw2/analyze.py create mode 100644 hw2/core.py delete mode 100644 hw2/data.txt delete mode 100644 hw2/encoding.py delete mode 100644 hw3/bloom.py create mode 100644 hw3/data.txt create mode 100644 hw3/encoding.py delete mode 100644 hw4/analyze.py create mode 100644 hw4/bloom.py delete mode 100644 hw4/core.py diff --git a/hw2/README.md b/hw2/README.md index 30c1e9f..860fb9d 100644 --- a/hw2/README.md +++ b/hw2/README.md @@ -1,85 +1,74 @@ -# Homework 1. Introduction to Python and File I/O -This homework assignment is meant to be an introduction to Python programming and introduces some basic concepts of encoding and decoding. +# HW3 String Matching -Due Date: *Friday April 17, 2020 11:59 pm* +*Due 5/14/20 11:59 PM* +Entity Resolution is the task of disambiguating manifestations of real world entities in various records or mentions by linking and grouping. For example, there could be different ways of addressing the same person in text, different addresses for businesses, or photos of a particular object. In this assignment, you will link two product catalogs. -## Initial Setup -These initial setup instructions assume you've done ``hw0``. Before you start an assingment you should sync your cloned repository with the online one: +## Getting Started +First, pull the most recent changes from the cmsc13600-public repository: ``` -$ cd cmsc13600-materials $ git pull ``` - -Copy the folder ``hw1`` to your newly cloned submission repository. Enter that repository from the command line and enter the copied ``hw1`` folder. In this homework assignment, you will only modify ``encoding.py``. Once you are done, you must add 'encoding.py' to git: +Then, copy the `hw3` folder to your submission repository. Change directories to enter your submission repository. Your code will go into `analzey.py`. You can the files to the repository using `git add`: ``` -$ git add encoding.py +$ git add analyze.py +$ git commit -m'initialized homework' ``` -After adding your files, to submit your code you must run: +You will also need to fetch the datasets used in this homework assignment: ``` -$ git commit -m"My submission" -$ git push +https://www.dropbox.com/s/vq5dyl5hwfhbw98/Amazon.csv?dl=0 +https://www.dropbox.com/s/fbys7cqnbl3ch1s/Amzon_GoogleProducts_perfectMapping.csv?dl=0 +https://www.dropbox.com/s/o6rqmscmv38rn1v/GoogleProducts.csv?dl=0 ``` -We will NOT grade any code that is not added, committed, and pushed to your submission repository. You can confirm your submission by visiting the web interface[https://mit.cs.uchicago.edu/cmsc13600-spr-20/skr] - -## Delta Encoding -Delta encoding is a way of storing or transmitting data in the form of differences (deltas) between sequential data rather than complete files. -In this first assignment, you will implement a delta encoding module in python. -The module will: -* Load a file of integers -* Delta encode them -* Write back a file in binary form - -The instructions in this assignment are purposefully incomplete for you to read Python's API and to understand how the different functions work. All of the necessary parts that you need to write are marked with *TODO*. +Download each of the files and put it into your `hw3` folder. -## TODO 1. Loading the data file -In `encoding.py`, your first task is to write `load_orig_file`. This function reads from a specified filename and returns a list of integers in the file. You may assume the file is formatted like ``data.txt`` provided with the code, where each line contains a single integer number. The input of this function is a filename and the output is a list of numbers. If the file does not exist you must raise an exception. +Before we can get started, let us understand the main APIs in this project. We have provided a file named `core.py` for you. This file loads and processes the data that you've just downloaded. For example, you can load the Amazon catalog with the `amazon_catalog()` function. This returns an iterator over data tuples in the Amazon catalog. The fields are id, title, description, mfg (manufacturer), and price if any: +``` +>>>for a in amazon_catalog(): +... print(a) +... break -## TODO 2. Compute the basic encoding -In `encoding.py`, your next task is to write `delta_encoding`. This function takes a list of numbers and computes the delta encoding. The delta encoding encodes the list in terms of successive differences from the previous element. The first element is kept as is in the encoding. +{'id': 'b000jz4hqo', 'title': 'clickart 950 000 - premier image pack (dvd-rom)', 'description': '', 'mfg': 'broderbund', 'price': '0'} +``` +You can similarly, do the same for the Google catalog: +``` +>>>for a in google_catalog(): +... print(a) +... break -For example: +{'id': 'http://www.google.com/base/feeds/snippets/11125907881740407428', 'title': 'learning quickbooks 2007', 'description': 'learning quickbooks 2007', 'mfg': 'intuit', 'price': '38.99'} ``` -> data = [1,3,4,3] -> enc = delta_encoding(data) -1,2,1,-1 +A matching is a pairing between id's in the Google catalog and the Amazon catalog that refer to the same product. The ground truth is listed in the file `Amzon_GoogleProducts_perfectMapping.csv`. Your job is to construct a list of pairs (or iterator of pairs) of `(amazon.id, google.id)`. These matchings can be evaluated for accuracy using the `eval_matching` function: ``` +>>> my_matching = [('b000jz4hqo', http://www.google.com/base/feeds/snippets/11125907881740407428'),...] +>>> {'false positive': 0.9768566493955095, 'false negative': 0.43351268255188313, 'accuracy': 0.04446992095577143} +``` +False positive refers to the false positive rate, false negative refers to the false negative rate, and accuracy refers to the overall accuracy. -Or, +## Assignment +Your job is write the `match` function in `analzye.py`. You can run your code by running: +``` +python3 auto_grader.py ``` -> data = [1,0,6,1] -> enc = delta_encoding(data) -1,-1,6,-5 +Running the code will print out a result report as follows (accuracy, precision, and recall): ``` -Your job is to write a function that computes this encoding. Pay close attention to how python passes around references and where you make copies of lists v.s. modify a list in place. +----Accuracy---- +0.5088062622309197 0.6998654104979811 0.3996925441967717 +---- Timing ---- +168.670348 seconds -## TODO 3. Integer Shifting -When we write this data to a file, we will want to represent each encoded value as an unsigned short integer (1 single byte of data). To do so, we have to "shift" all of the values upwards so there are no negatives. You will write a function `shift` that adds a pre-specified offset to each value. +``` +*For full credit, you must write a program that achieves at least 50% accuracy in less than 5 mins on a standard laptop.* -## TODO 4. Write Encoding -Now, we are ready to write the encoded data to disk. In the function `write_encoding`, you will do the following steps: -* Open the specified filename in the function arguments for writing -* Convert the encoded list of numbers into a bytearray -* Write the bytearray to the file -* Close the file +The project is complete unstructured and it is up to you to figure out how to make this happen. Here are some hints: -Reading from such a file is a little tricky, so we've provided that function for you. +* The amazon product database is redundant (multiple same products), the google database is essentially unique. -## TODO 5. Delta Decoding -Finally, you will write a function that takes a delta encoded list and recovers the original data. This should do the opposite of what you did before. Don't forget to unshift the data when you are testing! +* Jaccard similarity will be useful but you may have to consider "n-grams" of words (look at the lecture notes!) and "cleaning" up the strings to strip formatting and punctuation. -For example: -``` -> enc = [1,2,1,-1] -> data = delta_decoding(enc) -1,3,4,3 -``` +* Price and manufacturer will also be important attributes to use. -Or, +## Submission +After you finish the assignment you can submit your code with: ``` -> data = [1,-1,6,-5] -> data = delta_decoding(enc) -1,0,6,1 +$ git push ``` - -## Testing -We've provided a sample dataset ``data.txt`` which can be used to test your code as well as an autograder script `autograder.py` which runs a bunch of interesting tests. The autograder is not comprehensive but it is a good start. It's up to you to figure out what the test do and why they work. diff --git a/hw2/analyze.py b/hw2/analyze.py new file mode 100644 index 0000000..ee71842 --- /dev/null +++ b/hw2/analyze.py @@ -0,0 +1,14 @@ +from core import * +import datetime + +def match(): + ''' + Match must return a list of tuples of amazon ids and google ids. + For example: + [('b000jz4hqo', http://www.google.com/base/feeds/snippets/11125907881740407428'),....] + + ''' + + #YOUR CODE GOES HERE + + return [] \ No newline at end of file diff --git a/hw2/auto_grader.py b/hw2/auto_grader.py index 0b4bebe..0606d63 100644 --- a/hw2/auto_grader.py +++ b/hw2/auto_grader.py @@ -1,82 +1,50 @@ -import random -from encoding import * - -def test_load(): - data = load_orig_file('data.txt') - - try: - assert(sum(data) == 1778744) - except AssertionError: - print('TODO 1. Failure check your load_orig_file function') - -def test_encoding(): - data = load_orig_file('data.txt') - encoded = delta_encoding(data) - - try: - assert(sum(encoded) == data[-1]) - assert(sum(encoded) == 26) - assert(len(data) == len(encoded)) - except AssertionError: - print('TODO 2. Failure check your delta_encoding function') - -def test_shift(): - data = load_orig_file('data.txt') - encoded = delta_encoding(data) - N = len(data) - - try: - assert(sum(shift(data, 10)) == N*10 + sum(data)) - assert(all([d >=0 for d in shift(encoded,4)])) - except AssertionError: - print('TODO 3. Failure check your shift function') - -def test_decoding(): - data = load_orig_file('data.txt') - encoded = delta_encoding(data) - sencoded = shift(encoded ,4) - data_p = delta_decoding(unshift(sencoded,4)) - - try: - assert(data == data_p) - except AssertionError: - print('TODO 5. Cannot recover data with delta_decoding') - -def generate_file(size, seed): - FILE_NAME = 'data.gen.txt' - - f = open(FILE_NAME,'w') - - initial = seed - for i in range(size): - f.write(str(initial) + '\n') - initial += random.randint(-4, 4) - -def generate_random_tests(): - SIZES = (1,1000,16,99) - SEEDS = (240,-3, 9, 1) - - cnt = 0 - for trials in range(10): - generate_file(random.choice(SIZES), random.choice(SEEDS)) - - data = load_orig_file('data.gen.txt') - encoded = delta_encoding(data) - sencoded = shift(encoded ,4) - write_encoding(sencoded, 'data_out.txt') - - loaded = unshift(read_encoding('data_out.txt'),4) - decoded = delta_decoding(loaded) - - cnt += (decoded == data) - - try: - assert(cnt == 10) - except AssertionError: - print('Failed Random Tests', str(10-cnt), 'out of 10') - -test_load() -test_encoding() -test_shift() -test_decoding() -generate_random_tests() \ No newline at end of file +import datetime +import csv +from analyze import match + +def eval_matching(your_matching): + f = open('Amzon_GoogleProducts_perfectMapping.csv', 'r', encoding = "ISO-8859-1") + reader = csv.reader(f, delimiter=',', quotechar='"') + matches = set() + proposed_matches = set() + + tp = set() + fp = set() + fn = set() + tn = set() + + for row in reader: + matches.add((row[0],row[1])) + #print((row[0],row[1])) + + for m in your_matching: + proposed_matches.add(m) + + if m in matches: + tp.add(m) + else: + fp.add(m) + + for m in matches: + if m not in proposed_matches: + fn.add(m) + + if len(your_matching) == 0: + prec = 1.0 + else: + prec = len(tp)/(len(tp) + len(fp)) + + rec = len(tp)/(len(tp) + len(fn)) + + return {'precision': prec, + 'recall': rec, + 'accuracy': 2*(prec*rec)/(prec+rec) } + +#prints out the accuracy +now = datetime.datetime.now() +out = eval_matching(match()) +timing = (datetime.datetime.now()-now).total_seconds() +print("----Accuracy----") +print(out['accuracy'], out['precision'] ,out['recall']) +print("---- Timing ----") +print(timing,"seconds") diff --git a/hw2/core.py b/hw2/core.py new file mode 100644 index 0000000..890c78a --- /dev/null +++ b/hw2/core.py @@ -0,0 +1,41 @@ +''' +The core module sets up the data structures and +and references for this programming assignment. + +2010 +''' + +import platform +import csv + +if platform.system() == 'Windows': + print("This assignment will not work on a windows computer") + exit() + + +#defines an iterator over the google catalog +class Catalog(): + + def __init__(self, filename): + self.filename = filename + + def __iter__(self): + f = open(self.filename, 'r', encoding = "ISO-8859-1") + self.reader = csv.reader(f, delimiter=',', quotechar='"') + next(self.reader) + return self + + def __next__(self): + row = next(self.reader) + return {'id': row[0], + 'title': row[1], + 'description': row[2], + 'mfg': row[3], + 'price': row[4] + } + +def google_catalog(): + return Catalog('GoogleProducts.csv') + +def amazon_catalog(): + return Catalog('Amazon.csv') diff --git a/hw2/data.txt b/hw2/data.txt deleted file mode 100644 index 722754b..0000000 --- a/hw2/data.txt +++ /dev/null @@ -1,10000 +0,0 @@ -107 -105 -106 -103 -105 -108 -109 -112 -110 -110 -109 -111 -109 -106 -110 -112 -115 -114 -116 -118 -117 -116 -113 -112 -115 -111 -114 -118 -122 -124 -127 -125 -123 -124 -126 -128 -130 -134 -131 -133 -129 -129 -129 -130 -127 -130 -130 -128 -131 -131 -129 -126 -125 -124 -121 -117 -118 -120 -117 -117 -118 -116 -118 -120 -124 -123 -122 -125 -124 -123 -123 -126 -126 -124 -120 -117 -117 -118 -116 -118 -115 -115 -111 -115 -114 -115 -115 -115 -114 -118 -115 -116 -116 -116 -117 -114 -111 -113 -117 -116 -119 -115 -115 -114 -111 -113 -115 -111 -110 -114 -113 -115 -119 -122 -122 -121 -125 -126 -130 -126 -128 -131 -131 -132 -134 -133 -135 -131 -130 -132 -134 -134 -138 -134 -131 -131 -133 -136 -134 -133 -129 -133 -131 -130 -126 -127 -125 -125 -127 -130 -128 -130 -133 -136 -139 -141 -142 -138 -142 -142 -143 -145 -149 -153 -152 -149 -145 -148 -144 -147 -147 -148 -147 -150 -152 -148 -152 -152 -152 -150 -152 -153 -155 -159 -158 -162 -164 -160 -162 -166 -167 -165 -165 -168 -172 -171 -170 -170 -173 -175 -175 -173 -172 -173 -173 -176 -177 -175 -172 -175 -174 -174 -171 -172 -168 -169 -165 -164 -163 -162 -163 -161 -161 -161 -158 -159 -163 -162 -158 -162 -160 -160 -163 -161 -159 -163 -163 -164 -165 -168 -165 -169 -166 -164 -160 -161 -165 -168 -166 -167 -167 -171 -167 -170 -173 -172 -175 -178 -180 -177 -173 -177 -180 -178 -182 -186 -182 -179 -180 -182 -180 -177 -177 -174 -175 -178 -179 -175 -173 -173 -170 -173 -171 -169 -166 -164 -166 -169 -165 -161 -162 -160 -162 -162 -159 -161 -165 -161 -163 -167 -163 -159 -160 -156 -154 -154 -156 -153 -151 -147 -144 -144 -140 -141 -144 -147 -143 -144 -146 -147 -146 -147 -150 -150 -151 -149 -150 -147 -147 -148 -148 -149 -148 -148 -144 -147 -144 -145 -144 -147 -143 -142 -142 -144 -140 -142 -142 -141 -143 -141 -143 -145 -144 -148 -150 -146 -144 -148 -146 -143 -140 -144 -148 -146 -143 -143 -139 -142 -145 -146 -145 -142 -142 -144 -141 -143 -145 -142 -140 -141 -138 -139 -136 -137 -136 -134 -138 -142 -140 -138 -138 -139 -137 -136 -133 -136 -137 -133 -137 -137 -133 -132 -131 -135 -131 -128 -128 -132 -136 -132 -134 -130 -128 -126 -122 -120 -117 -117 -120 -120 -123 -126 -130 -126 -129 -128 -125 -127 -124 -124 -125 -122 -123 -125 -124 -125 -129 -127 -131 -132 -128 -127 -130 -128 -125 -126 -130 -132 -128 -132 -133 -137 -133 -133 -131 -129 -130 -126 -122 -124 -120 -123 -121 -119 -119 -122 -125 -125 -128 -125 -123 -126 -126 -124 -124 -120 -124 -121 -120 -121 -120 -120 -121 -117 -114 -110 -114 -112 -108 -104 -102 -106 -104 -108 -104 -105 -105 -108 -111 -114 -111 -113 -114 -112 -113 -116 -119 -120 -120 -121 -117 -114 -113 -112 -115 -113 -115 -111 -113 -113 -109 -110 -110 -109 -108 -110 -106 -104 -107 -107 -107 -111 -109 -109 -110 -108 -110 -110 -110 -108 -106 -108 -105 -104 -106 -108 -111 -114 -114 -117 -117 -113 -111 -110 -111 -112 -114 -117 -117 -121 -117 -115 -116 -120 -116 -112 -110 -106 -108 -111 -107 -110 -111 -107 -104 -106 -107 -111 -111 -112 -116 -118 -120 -123 -121 -119 -116 -112 -112 -116 -119 -118 -116 -112 -111 -115 -113 -112 -110 -113 -112 -114 -115 -111 -109 -110 -106 -109 -110 -107 -109 -110 -113 -115 -119 -115 -116 -118 -119 -118 -116 -119 -115 -115 -113 -113 -111 -109 -112 -108 -106 -103 -102 -101 -104 -108 -105 -102 -101 -98 -98 -96 -92 -93 -89 -89 -91 -89 -88 -90 -93 -89 -85 -84 -84 -86 -89 -89 -89 -86 -87 -87 -83 -85 -86 -85 -83 -87 -83 -80 -80 -80 -84 -83 -87 -91 -95 -94 -95 -93 -97 -100 -103 -106 -110 -106 -106 -107 -105 -103 -102 -100 -101 -98 -96 -100 -103 -104 -101 -97 -93 -90 -90 -88 -91 -93 -93 -93 -93 -90 -88 -86 -84 -84 -88 -87 -83 -84 -88 -92 -90 -93 -96 -96 -97 -98 -95 -98 -96 -99 -95 -98 -98 -98 -97 -94 -93 -93 -94 -91 -89 -86 -82 -82 -81 -82 -78 -79 -79 -77 -81 -85 -84 -81 -84 -87 -83 -80 -78 -74 -75 -77 -73 -70 -73 -71 -75 -72 -68 -66 -70 -73 -77 -77 -74 -71 -74 -74 -70 -66 -68 -71 -74 -77 -76 -78 -79 -79 -75 -79 -75 -74 -75 -77 -81 -84 -86 -82 -80 -81 -80 -76 -74 -71 -67 -66 -70 -73 -71 -73 -71 -75 -74 -72 -76 -79 -79 -75 -78 -77 -80 -76 -76 -73 -75 -75 -77 -76 -74 -77 -76 -77 -75 -76 -80 -76 -74 -73 -71 -70 -71 -67 -66 -69 -68 -68 -67 -66 -62 -64 -66 -68 -68 -69 -70 -70 -66 -67 -63 -64 -68 -67 -70 -74 -70 -74 -72 -71 -70 -68 -64 -62 -62 -58 -56 -52 -52 -49 -50 -48 -45 -44 -47 -49 -45 -47 -45 -44 -44 -43 -47 -48 -46 -50 -46 -45 -49 -53 -54 -53 -50 -52 -49 -47 -51 -48 -51 -53 -53 -51 -54 -56 -56 -55 -51 -48 -45 -49 -52 -56 -60 -59 -61 -64 -61 -59 -61 -62 -61 -65 -67 -70 -69 -67 -71 -68 -67 -63 -61 -64 -67 -67 -67 -70 -74 -70 -71 -69 -65 -64 -60 -64 -63 -66 -64 -60 -60 -61 -62 -64 -62 -65 -68 -72 -73 -69 -70 -72 -71 -72 -75 -76 -73 -74 -71 -69 -68 -71 -68 -65 -65 -66 -70 -72 -74 -72 -75 -71 -67 -65 -68 -72 -72 -74 -71 -75 -74 -70 -71 -68 -71 -69 -69 -67 -71 -67 -66 -68 -68 -65 -61 -63 -62 -60 -64 -66 -68 -72 -70 -74 -75 -71 -70 -66 -68 -64 -67 -64 -60 -59 -62 -65 -66 -67 -69 -71 -71 -68 -65 -66 -69 -71 -68 -64 -66 -67 -70 -66 -69 -65 -66 -70 -71 -72 -73 -72 -69 -73 -77 -73 -77 -78 -78 -74 -78 -78 -77 -80 -79 -75 -73 -71 -70 -68 -72 -70 -68 -65 -61 -61 -65 -65 -66 -66 -70 -67 -71 -69 -68 -71 -67 -70 -72 -70 -66 -68 -65 -68 -65 -64 -62 -60 -60 -63 -61 -57 -56 -58 -57 -59 -62 -64 -63 -62 -60 -62 -61 -62 -58 -62 -64 -60 -58 -54 -56 -58 -55 -55 -51 -51 -51 -52 -51 -53 -57 -53 -53 -55 -53 -54 -55 -58 -54 -51 -54 -52 -50 -47 -44 -45 -43 -45 -48 -46 -44 -41 -44 -42 -46 -50 -48 -49 -48 -46 -47 -47 -43 -42 -45 -46 -43 -44 -45 -42 -39 -41 -44 -45 -46 -43 -45 -46 -49 -51 -54 -58 -56 -57 -59 -60 -62 -66 -68 -71 -68 -68 -71 -71 -69 -73 -73 -70 -69 -72 -70 -72 -71 -73 -71 -73 -77 -77 -76 -74 -75 -77 -75 -76 -75 -75 -71 -69 -66 -68 -70 -73 -69 -65 -62 -59 -61 -58 -59 -61 -64 -66 -67 -71 -71 -69 -72 -74 -78 -78 -82 -78 -74 -78 -77 -76 -80 -82 -85 -88 -88 -85 -86 -89 -90 -89 -91 -89 -93 -95 -94 -94 -90 -87 -84 -86 -84 -84 -86 -89 -91 -90 -92 -96 -93 -91 -94 -91 -90 -89 -89 -87 -86 -85 -89 -88 -86 -85 -85 -82 -82 -81 -83 -87 -84 -81 -79 -81 -83 -84 -81 -80 -82 -84 -85 -86 -88 -89 -87 -91 -89 -92 -90 -89 -90 -89 -93 -96 -94 -98 -95 -98 -97 -94 -91 -89 -92 -92 -95 -92 -88 -91 -89 -87 -84 -82 -83 -83 -85 -85 -81 -85 -88 -85 -81 -83 -84 -87 -86 -90 -94 -94 -96 -97 -95 -91 -91 -93 -97 -98 -100 -103 -103 -107 -105 -102 -99 -95 -98 -100 -100 -102 -98 -102 -98 -100 -98 -101 -105 -104 -108 -110 -113 -112 -116 -120 -118 -114 -114 -117 -118 -118 -115 -112 -115 -112 -112 -113 -115 -112 -115 -114 -118 -119 -115 -115 -111 -113 -113 -111 -113 -113 -114 -114 -118 -116 -112 -110 -109 -111 -108 -104 -100 -102 -101 -103 -100 -103 -106 -109 -107 -108 -104 -107 -111 -114 -115 -115 -115 -117 -117 -119 -122 -119 -118 -115 -116 -115 -114 -111 -115 -114 -112 -109 -110 -109 -109 -111 -113 -109 -105 -106 -103 -103 -104 -108 -109 -111 -114 -112 -116 -113 -113 -117 -115 -111 -114 -115 -113 -116 -114 -116 -118 -114 -115 -118 -122 -125 -127 -126 -125 -124 -124 -126 -126 -127 -123 -125 -125 -124 -120 -124 -120 -122 -122 -123 -125 -123 -120 -121 -117 -115 -112 -114 -115 -116 -118 -120 -121 -122 -126 -124 -120 -118 -121 -124 -122 -122 -123 -124 -128 -129 -125 -129 -129 -132 -129 -127 -127 -131 -132 -134 -137 -141 -138 -139 -136 -138 -136 -140 -142 -144 -145 -142 -143 -144 -148 -145 -144 -140 -140 -141 -145 -146 -142 -143 -147 -147 -143 -143 -141 -143 -145 -149 -152 -155 -159 -156 -155 -157 -156 -152 -148 -148 -147 -151 -147 -147 -147 -144 -143 -144 -147 -151 -153 -154 -151 -148 -147 -148 -149 -153 -149 -148 -148 -146 -143 -147 -150 -148 -152 -155 -157 -161 -164 -167 -169 -168 -164 -160 -157 -158 -160 -159 -162 -166 -162 -160 -164 -163 -163 -159 -163 -165 -163 -167 -169 -171 -167 -164 -163 -166 -169 -169 -173 -176 -179 -178 -176 -175 -178 -178 -174 -174 -176 -175 -179 -176 -176 -180 -179 -183 -181 -184 -182 -179 -176 -174 -174 -173 -176 -175 -178 -176 -177 -173 -172 -172 -168 -165 -169 -171 -169 -165 -165 -165 -164 -165 -169 -166 -163 -165 -165 -168 -167 -171 -169 -170 -170 -166 -163 -162 -158 -161 -163 -161 -159 -156 -158 -158 -154 -150 -150 -146 -148 -144 -141 -143 -143 -140 -136 -136 -135 -138 -139 -142 -142 -142 -139 -143 -147 -149 -152 -148 -149 -149 -151 -154 -156 -152 -151 -148 -148 -152 -149 -150 -153 -153 -157 -153 -156 -154 -154 -157 -158 -154 -155 -157 -155 -158 -161 -162 -165 -169 -172 -169 -169 -169 -165 -166 -168 -168 -167 -165 -166 -170 -168 -170 -166 -166 -164 -161 -161 -158 -161 -165 -161 -162 -162 -160 -162 -165 -163 -164 -162 -159 -158 -161 -159 -158 -157 -161 -162 -165 -166 -165 -162 -159 -157 -160 -158 -158 -161 -159 -159 -157 -153 -153 -157 -156 -152 -156 -155 -153 -153 -151 -154 -150 -146 -148 -152 -148 -149 -145 -141 -139 -142 -138 -141 -139 -136 -137 -135 -132 -132 -134 -132 -128 -131 -129 -129 -125 -128 -131 -134 -130 -133 -129 -133 -134 -133 -132 -128 -132 -134 -137 -135 -133 -129 -133 -136 -139 -143 -142 -143 -143 -142 -143 -143 -139 -140 -142 -143 -141 -142 -143 -147 -151 -148 -147 -150 -147 -151 -154 -152 -155 -154 -151 -154 -150 -146 -150 -152 -149 -147 -143 -144 -142 -143 -146 -143 -146 -142 -139 -137 -134 -135 -136 -137 -138 -140 -140 -144 -148 -150 -151 -154 -154 -155 -153 -153 -156 -158 -159 -155 -158 -154 -150 -147 -143 -141 -142 -138 -138 -139 -135 -132 -134 -138 -137 -138 -139 -140 -140 -143 -139 -141 -144 -143 -147 -145 -146 -147 -147 -148 -147 -149 -147 -143 -143 -143 -141 -144 -146 -147 -149 -146 -146 -150 -152 -154 -158 -162 -164 -168 -165 -168 -165 -163 -167 -168 -169 -172 -170 -172 -175 -178 -178 -176 -173 -169 -170 -167 -171 -173 -170 -173 -176 -178 -176 -177 -175 -179 -179 -175 -178 -180 -177 -176 -173 -172 -174 -177 -173 -173 -169 -173 -176 -176 -179 -177 -179 -179 -181 -182 -179 -180 -183 -184 -180 -176 -176 -180 -181 -177 -174 -170 -171 -173 -172 -172 -170 -174 -172 -169 -165 -165 -164 -161 -157 -161 -158 -158 -161 -163 -167 -171 -172 -171 -175 -175 -178 -181 -181 -183 -183 -181 -181 -179 -179 -182 -182 -181 -184 -180 -181 -179 -182 -179 -178 -176 -180 -182 -179 -178 -176 -177 -174 -177 -174 -171 -170 -168 -167 -165 -169 -173 -173 -172 -171 -169 -165 -166 -162 -162 -158 -159 -159 -163 -167 -164 -160 -159 -157 -158 -155 -158 -155 -157 -161 -158 -155 -158 -162 -163 -164 -168 -171 -168 -166 -165 -168 -167 -167 -163 -166 -170 -168 -171 -169 -167 -168 -171 -170 -171 -168 -172 -168 -172 -172 -172 -170 -170 -169 -170 -167 -170 -172 -168 -169 -167 -164 -162 -163 -161 -160 -160 -158 -158 -158 -154 -156 -156 -158 -156 -158 -158 -157 -156 -153 -150 -150 -149 -147 -149 -150 -152 -151 -150 -147 -151 -150 -151 -147 -149 -145 -141 -137 -139 -137 -141 -138 -138 -138 -141 -140 -144 -148 -152 -151 -152 -148 -148 -152 -149 -146 -149 -153 -154 -153 -153 -150 -151 -151 -152 -154 -157 -158 -154 -153 -152 -152 -156 -158 -161 -160 -156 -153 -153 -155 -154 -155 -154 -157 -161 -160 -159 -160 -158 -157 -153 -150 -150 -149 -147 -150 -151 -147 -144 -144 -148 -147 -146 -148 -151 -150 -151 -152 -153 -149 -153 -155 -151 -150 -152 -156 -158 -159 -157 -158 -161 -164 -165 -167 -167 -169 -169 -166 -168 -171 -169 -172 -173 -177 -181 -177 -178 -180 -178 -182 -178 -175 -174 -173 -171 -174 -172 -168 -166 -168 -168 -171 -169 -168 -172 -172 -170 -168 -164 -163 -161 -159 -163 -166 -163 -167 -170 -173 -176 -176 -174 -177 -175 -178 -179 -182 -186 -187 -188 -186 -182 -180 -179 -182 -184 -188 -191 -195 -195 -193 -197 -200 -198 -197 -200 -200 -202 -204 -202 -202 -200 -199 -201 -198 -202 -200 -204 -208 -212 -209 -205 -202 -204 -201 -205 -204 -201 -205 -208 -211 -210 -206 -210 -206 -208 -212 -216 -215 -219 -218 -219 -219 -222 -226 -223 -219 -215 -213 -211 -211 -211 -210 -214 -210 -207 -209 -206 -208 -210 -214 -215 -218 -220 -219 -221 -222 -218 -222 -224 -228 -229 -230 -226 -222 -226 -223 -221 -225 -222 -221 -221 -222 -223 -227 -230 -232 -234 -238 -241 -244 -247 -247 -243 -243 -241 -240 -238 -241 -245 -248 -249 -246 -249 -252 -250 -246 -247 -245 -245 -246 -248 -249 -250 -254 -250 -252 -256 -252 -251 -253 -253 -255 -258 -261 -261 -265 -267 -269 -266 -267 -270 -271 -269 -268 -266 -269 -270 -268 -272 -274 -270 -272 -272 -269 -271 -267 -267 -266 -264 -260 -256 -253 -251 -252 -248 -251 -251 -255 -255 -256 -254 -255 -255 -255 -253 -255 -259 -255 -257 -254 -250 -253 -252 -256 -255 -251 -255 -257 -259 -255 -259 -262 -264 -268 -268 -269 -267 -267 -271 -267 -269 -267 -264 -261 -263 -260 -264 -263 -260 -258 -261 -259 -257 -253 -253 -256 -257 -259 -256 -252 -249 -248 -252 -253 -251 -253 -253 -255 -252 -256 -258 -255 -256 -260 -262 -258 -254 -258 -260 -259 -262 -258 -260 -263 -262 -261 -258 -255 -252 -251 -249 -251 -253 -256 -253 -257 -254 -256 -255 -253 -249 -250 -254 -250 -246 -243 -247 -248 -247 -249 -253 -249 -247 -244 -242 -244 -244 -240 -242 -238 -238 -234 -234 -237 -233 -236 -239 -242 -243 -241 -242 -243 -241 -243 -240 -240 -238 -237 -240 -242 -239 -241 -237 -238 -238 -241 -238 -238 -238 -242 -238 -242 -240 -236 -236 -233 -230 -231 -230 -229 -232 -228 -224 -225 -222 -225 -229 -233 -231 -234 -237 -235 -236 -239 -236 -238 -238 -238 -235 -238 -237 -235 -233 -229 -230 -229 -231 -229 -228 -225 -223 -227 -227 -230 -229 -231 -233 -231 -227 -228 -231 -227 -227 -228 -230 -232 -232 -228 -230 -229 -233 -236 -240 -236 -234 -233 -237 -233 -234 -233 -237 -236 -240 -240 -242 -243 -247 -251 -253 -257 -253 -250 -253 -254 -250 -253 -252 -253 -256 -260 -256 -256 -259 -259 -255 -255 -256 -255 -258 -254 -256 -260 -258 -258 -257 -261 -261 -263 -265 -264 -267 -268 -264 -265 -261 -259 -262 -266 -269 -266 -264 -265 -266 -262 -261 -264 -265 -262 -259 -263 -265 -266 -262 -261 -265 -261 -265 -263 -262 -265 -261 -261 -261 -258 -256 -259 -263 -259 -258 -254 -250 -252 -250 -254 -253 -249 -249 -246 -243 -242 -245 -241 -244 -245 -247 -250 -251 -247 -248 -244 -244 -240 -236 -238 -237 -239 -235 -233 -236 -237 -233 -230 -234 -238 -236 -240 -240 -240 -238 -242 -238 -236 -236 -240 -238 -240 -236 -232 -231 -231 -233 -235 -235 -237 -233 -235 -231 -234 -231 -228 -232 -233 -232 -232 -229 -233 -232 -233 -229 -230 -234 -230 -231 -230 -231 -233 -234 -233 -229 -231 -235 -236 -237 -237 -236 -233 -235 -232 -228 -227 -230 -227 -224 -227 -225 -223 -223 -222 -221 -222 -218 -217 -216 -214 -211 -214 -210 -209 -213 -216 -219 -215 -219 -220 -217 -215 -217 -217 -218 -214 -215 -214 -217 -213 -215 -216 -214 -211 -210 -210 -213 -213 -217 -213 -215 -215 -219 -217 -213 -214 -216 -218 -214 -217 -220 -219 -223 -219 -220 -218 -222 -218 -222 -225 -222 -221 -220 -221 -222 -225 -221 -221 -217 -220 -217 -214 -215 -217 -217 -220 -216 -213 -216 -215 -219 -220 -217 -213 -215 -216 -215 -218 -222 -218 -221 -221 -223 -219 -219 -216 -215 -213 -214 -216 -212 -213 -213 -209 -209 -210 -211 -211 -211 -208 -206 -205 -206 -208 -206 -206 -206 -207 -207 -204 -207 -203 -207 -208 -204 -201 -203 -207 -208 -208 -212 -213 -210 -208 -212 -214 -212 -209 -210 -206 -202 -204 -208 -210 -207 -211 -215 -217 -214 -210 -209 -205 -202 -205 -203 -199 -195 -192 -192 -195 -191 -192 -192 -195 -197 -194 -193 -197 -193 -190 -191 -192 -195 -199 -197 -196 -194 -193 -194 -197 -200 -197 -196 -195 -196 -192 -194 -197 -194 -197 -194 -192 -196 -197 -196 -200 -197 -195 -194 -194 -195 -191 -194 -195 -191 -190 -194 -195 -195 -197 -201 -203 -205 -203 -203 -205 -206 -206 -210 -207 -211 -207 -210 -214 -210 -214 -216 -215 -215 -214 -216 -214 -217 -218 -220 -222 -224 -222 -219 -223 -225 -228 -224 -226 -227 -224 -225 -225 -226 -228 -232 -230 -230 -233 -235 -236 -234 -231 -228 -226 -223 -223 -220 -217 -219 -221 -217 -216 -218 -216 -215 -212 -212 -209 -212 -213 -210 -213 -216 -220 -219 -218 -217 -214 -213 -215 -216 -220 -223 -219 -216 -219 -219 -222 -225 -226 -223 -227 -231 -233 -235 -234 -238 -236 -234 -238 -240 -242 -246 -245 -242 -243 -246 -248 -245 -243 -241 -243 -239 -240 -239 -242 -242 -239 -235 -233 -236 -239 -240 -240 -244 -247 -245 -247 -243 -241 -237 -235 -236 -233 -233 -237 -241 -238 -237 -236 -235 -231 -230 -229 -226 -229 -227 -228 -232 -232 -231 -230 -232 -229 -233 -231 -234 -230 -229 -230 -226 -228 -228 -229 -228 -224 -223 -223 -219 -218 -219 -221 -221 -222 -226 -228 -225 -229 -228 -228 -230 -228 -231 -229 -226 -226 -230 -231 -229 -229 -226 -226 -226 -222 -220 -219 -223 -223 -220 -219 -222 -219 -215 -215 -214 -214 -210 -214 -212 -214 -216 -217 -216 -220 -223 -223 -227 -230 -228 -227 -227 -225 -221 -218 -221 -222 -224 -222 -223 -224 -221 -223 -225 -221 -217 -213 -211 -214 -213 -217 -218 -219 -220 -216 -218 -214 -215 -214 -217 -213 -212 -215 -213 -216 -218 -219 -219 -218 -218 -214 -217 -218 -221 -224 -228 -225 -228 -228 -228 -226 -230 -227 -226 -224 -220 -216 -212 -211 -210 -208 -207 -205 -201 -200 -199 -203 -199 -199 -198 -195 -197 -201 -199 -200 -203 -205 -208 -208 -206 -205 -205 -209 -205 -209 -209 -209 -208 -205 -208 -211 -215 -216 -217 -218 -214 -212 -208 -211 -212 -211 -214 -211 -210 -210 -210 -214 -217 -214 -210 -210 -209 -210 -210 -209 -213 -210 -206 -210 -213 -210 -212 -210 -207 -211 -213 -212 -212 -216 -216 -217 -220 -216 -217 -215 -211 -211 -211 -208 -204 -207 -205 -203 -200 -201 -200 -201 -205 -208 -208 -204 -206 -206 -204 -200 -204 -208 -211 -211 -211 -207 -203 -201 -203 -201 -201 -203 -207 -203 -206 -204 -206 -210 -210 -211 -214 -218 -220 -222 -222 -223 -227 -231 -232 -234 -231 -233 -234 -237 -237 -237 -234 -238 -236 -240 -236 -240 -238 -240 -237 -235 -236 -237 -239 -243 -239 -242 -246 -242 -243 -247 -243 -242 -238 -239 -242 -244 -246 -250 -247 -249 -250 -254 -252 -252 -251 -250 -246 -246 -249 -250 -247 -250 -251 -251 -247 -247 -249 -252 -253 -255 -258 -262 -261 -261 -263 -267 -270 -273 -272 -274 -276 -272 -272 -270 -272 -271 -272 -268 -264 -267 -271 -267 -270 -273 -272 -273 -274 -270 -273 -270 -272 -273 -274 -278 -279 -277 -276 -276 -277 -281 -282 -283 -282 -281 -285 -282 -284 -281 -281 -277 -276 -279 -283 -280 -279 -283 -284 -288 -285 -286 -288 -290 -291 -291 -289 -293 -290 -292 -288 -285 -288 -292 -292 -288 -287 -288 -290 -290 -293 -297 -297 -301 -301 -305 -306 -305 -304 -301 -298 -295 -294 -292 -288 -288 -285 -289 -292 -290 -294 -295 -295 -295 -294 -297 -298 -294 -290 -290 -294 -292 -291 -295 -294 -297 -295 -291 -288 -284 -283 -286 -288 -284 -287 -286 -286 -287 -284 -287 -285 -282 -283 -280 -280 -279 -278 -277 -277 -274 -273 -273 -270 -272 -272 -275 -273 -276 -278 -277 -276 -280 -281 -278 -281 -285 -282 -283 -284 -282 -281 -285 -285 -287 -291 -292 -295 -298 -295 -291 -292 -290 -287 -289 -293 -297 -297 -299 -296 -292 -289 -286 -289 -288 -285 -284 -287 -283 -279 -283 -280 -276 -278 -279 -275 -279 -280 -283 -280 -283 -285 -287 -283 -286 -289 -287 -291 -289 -293 -291 -288 -289 -285 -287 -283 -281 -283 -287 -283 -281 -280 -279 -277 -276 -280 -278 -282 -286 -286 -290 -292 -295 -295 -292 -289 -288 -284 -287 -285 -285 -285 -289 -293 -297 -299 -298 -295 -291 -295 -297 -299 -298 -300 -303 -303 -300 -298 -296 -296 -297 -298 -300 -296 -300 -299 -295 -299 -299 -296 -298 -302 -303 -302 -302 -300 -303 -302 -306 -310 -306 -303 -307 -305 -308 -306 -303 -300 -300 -304 -303 -301 -300 -302 -304 -300 -297 -294 -293 -290 -288 -287 -290 -291 -294 -294 -292 -288 -288 -289 -286 -282 -281 -281 -282 -283 -284 -283 -286 -287 -287 -290 -293 -291 -293 -289 -285 -287 -283 -287 -289 -293 -295 -292 -290 -293 -291 -295 -292 -293 -290 -289 -292 -296 -292 -296 -292 -292 -291 -292 -292 -290 -288 -289 -291 -290 -293 -296 -298 -295 -293 -289 -293 -289 -287 -288 -292 -289 -292 -289 -286 -286 -290 -291 -295 -298 -296 -297 -296 -294 -293 -292 -295 -293 -292 -295 -299 -295 -296 -292 -292 -295 -294 -296 -299 -296 -299 -302 -303 -299 -297 -300 -300 -300 -297 -293 -291 -295 -299 -296 -298 -301 -298 -295 -299 -297 -295 -294 -293 -294 -297 -294 -295 -293 -296 -297 -293 -295 -298 -297 -293 -294 -290 -290 -294 -295 -298 -302 -301 -302 -301 -299 -299 -298 -295 -296 -292 -292 -291 -292 -295 -293 -292 -292 -293 -290 -294 -296 -296 -299 -301 -298 -296 -297 -296 -292 -290 -293 -294 -293 -296 -294 -291 -287 -286 -285 -281 -280 -278 -278 -275 -275 -271 -271 -267 -267 -263 -262 -263 -259 -260 -262 -260 -261 -262 -266 -262 -261 -258 -260 -262 -259 -263 -262 -260 -257 -260 -256 -256 -259 -260 -261 -259 -261 -265 -269 -269 -273 -271 -267 -267 -267 -268 -268 -270 -269 -273 -271 -273 -272 -271 -271 -271 -273 -269 -270 -268 -265 -262 -260 -260 -263 -267 -266 -264 -262 -258 -259 -259 -262 -258 -260 -257 -260 -262 -259 -262 -264 -266 -263 -264 -263 -260 -260 -263 -265 -268 -270 -272 -273 -273 -270 -270 -274 -275 -271 -275 -272 -270 -269 -268 -271 -274 -278 -274 -277 -274 -278 -281 -281 -281 -280 -277 -277 -281 -281 -284 -283 -281 -285 -288 -284 -286 -286 -290 -289 -287 -291 -289 -293 -289 -293 -293 -289 -290 -292 -293 -294 -298 -297 -297 -294 -292 -288 -288 -292 -290 -290 -286 -282 -279 -278 -274 -271 -268 -269 -266 -267 -268 -272 -270 -266 -270 -272 -275 -278 -276 -274 -271 -273 -270 -266 -266 -264 -263 -261 -257 -258 -262 -263 -260 -264 -261 -265 -269 -268 -268 -264 -264 -266 -263 -267 -265 -266 -268 -272 -276 -275 -276 -272 -270 -268 -269 -268 -272 -276 -277 -279 -276 -273 -274 -274 -270 -274 -278 -282 -284 -285 -283 -280 -281 -280 -284 -287 -284 -285 -287 -288 -284 -282 -281 -285 -286 -290 -291 -288 -289 -285 -282 -280 -276 -279 -279 -278 -282 -286 -283 -281 -280 -278 -278 -281 -282 -283 -286 -288 -286 -284 -282 -285 -282 -278 -281 -285 -284 -288 -292 -290 -287 -287 -284 -286 -282 -285 -282 -281 -281 -281 -277 -279 -278 -277 -275 -274 -275 -276 -272 -271 -274 -277 -273 -277 -274 -278 -274 -274 -273 -269 -267 -266 -268 -269 -270 -267 -264 -266 -270 -268 -266 -264 -266 -266 -263 -262 -261 -260 -261 -262 -266 -264 -262 -263 -259 -259 -257 -255 -258 -259 -262 -266 -268 -268 -271 -267 -270 -269 -273 -272 -268 -264 -261 -262 -258 -259 -255 -255 -255 -259 -260 -259 -257 -253 -250 -249 -250 -248 -246 -247 -243 -246 -247 -244 -248 -244 -243 -242 -243 -246 -242 -244 -243 -246 -242 -239 -242 -243 -241 -238 -235 -232 -230 -234 -230 -226 -229 -229 -225 -223 -220 -217 -214 -210 -206 -205 -204 -206 -207 -204 -205 -208 -210 -207 -209 -210 -211 -211 -209 -209 -210 -206 -205 -205 -201 -203 -202 -206 -209 -210 -210 -213 -215 -218 -222 -221 -225 -226 -229 -226 -225 -225 -221 -219 -219 -219 -222 -224 -225 -224 -223 -225 -229 -225 -225 -226 -223 -226 -228 -226 -222 -218 -219 -215 -214 -213 -213 -209 -208 -209 -210 -209 -213 -215 -213 -210 -214 -216 -219 -217 -220 -217 -215 -211 -211 -212 -210 -213 -216 -215 -216 -212 -208 -210 -207 -211 -209 -210 -210 -213 -216 -212 -211 -215 -214 -218 -220 -219 -216 -219 -215 -218 -221 -221 -225 -229 -228 -226 -223 -222 -224 -223 -226 -225 -228 -228 -231 -227 -226 -224 -223 -224 -222 -220 -217 -218 -222 -224 -228 -225 -222 -225 -228 -224 -221 -224 -221 -222 -221 -220 -220 -221 -222 -221 -220 -217 -218 -222 -219 -219 -215 -211 -208 -208 -210 -209 -213 -212 -212 -215 -217 -218 -220 -222 -224 -223 -222 -221 -219 -218 -221 -218 -218 -219 -217 -220 -219 -223 -221 -225 -222 -224 -224 -225 -222 -218 -220 -217 -218 -220 -221 -217 -215 -217 -216 -217 -213 -213 -216 -214 -215 -219 -217 -216 -218 -220 -223 -226 -225 -221 -222 -219 -217 -217 -213 -215 -213 -209 -205 -205 -208 -207 -204 -204 -205 -203 -203 -201 -204 -207 -209 -213 -215 -211 -212 -213 -209 -205 -205 -204 -200 -201 -199 -197 -200 -202 -199 -195 -198 -202 -200 -196 -198 -199 -198 -197 -200 -199 -200 -201 -201 -198 -196 -196 -193 -194 -194 -195 -191 -187 -189 -190 -194 -194 -198 -200 -198 -200 -197 -197 -197 -193 -195 -199 -200 -197 -200 -203 -199 -203 -206 -209 -210 -212 -209 -205 -204 -208 -210 -206 -206 -208 -206 -204 -205 -209 -211 -215 -213 -212 -210 -213 -209 -206 -204 -203 -200 -200 -200 -197 -195 -198 -195 -191 -193 -195 -191 -188 -189 -192 -189 -188 -192 -196 -196 -192 -193 -194 -194 -198 -194 -192 -191 -191 -194 -190 -194 -198 -198 -198 -194 -191 -190 -192 -195 -193 -190 -188 -187 -184 -188 -191 -190 -192 -195 -191 -194 -198 -198 -199 -196 -199 -197 -199 -201 -204 -202 -204 -204 -200 -200 -201 -201 -202 -200 -199 -195 -195 -198 -195 -199 -203 -203 -200 -198 -199 -201 -202 -201 -204 -202 -202 -201 -201 -201 -199 -201 -200 -200 -198 -202 -204 -201 -200 -197 -194 -196 -195 -194 -194 -192 -196 -200 -204 -204 -201 -205 -205 -202 -200 -196 -199 -197 -194 -191 -194 -193 -190 -190 -190 -190 -192 -195 -194 -195 -199 -202 -198 -202 -203 -199 -203 -207 -211 -209 -209 -211 -212 -209 -207 -207 -211 -209 -205 -205 -201 -205 -208 -208 -209 -208 -207 -210 -214 -217 -218 -216 -217 -219 -219 -219 -220 -222 -220 -223 -221 -217 -215 -219 -220 -223 -223 -222 -218 -221 -219 -217 -217 -221 -221 -217 -219 -223 -221 -222 -224 -227 -224 -224 -224 -225 -229 -225 -223 -227 -223 -226 -224 -227 -223 -222 -224 -226 -229 -225 -226 -225 -221 -217 -221 -225 -226 -227 -229 -229 -225 -225 -224 -224 -220 -220 -222 -226 -229 -226 -223 -220 -223 -221 -225 -225 -225 -226 -227 -225 -228 -232 -233 -234 -236 -236 -239 -239 -239 -243 -239 -239 -243 -247 -251 -251 -250 -251 -254 -256 -253 -250 -248 -245 -246 -243 -240 -239 -242 -239 -237 -238 -237 -239 -238 -241 -239 -238 -240 -240 -237 -236 -236 -235 -239 -235 -237 -240 -243 -246 -246 -243 -242 -243 -243 -244 -247 -246 -248 -247 -246 -245 -243 -241 -240 -239 -241 -242 -243 -247 -250 -254 -258 -256 -258 -254 -252 -254 -252 -253 -256 -258 -256 -254 -255 -257 -259 -263 -267 -271 -272 -275 -274 -277 -281 -283 -282 -283 -285 -281 -280 -277 -276 -280 -284 -287 -290 -287 -285 -281 -277 -275 -277 -279 -282 -279 -282 -285 -281 -284 -287 -290 -292 -295 -297 -295 -297 -295 -291 -295 -296 -292 -292 -293 -295 -296 -300 -302 -306 -304 -308 -304 -308 -306 -302 -303 -305 -308 -310 -313 -313 -312 -310 -307 -306 -305 -304 -305 -308 -306 -306 -307 -311 -315 -315 -312 -308 -309 -310 -307 -310 -311 -309 -307 -311 -312 -311 -315 -317 -320 -317 -320 -318 -322 -321 -318 -318 -315 -315 -312 -310 -306 -306 -308 -308 -309 -312 -314 -311 -307 -311 -310 -311 -315 -319 -321 -320 -324 -326 -325 -326 -329 -331 -331 -327 -327 -324 -323 -326 -326 -327 -326 -326 -325 -328 -331 -328 -326 -330 -326 -324 -322 -318 -317 -320 -320 -320 -320 -323 -319 -319 -318 -315 -311 -315 -311 -315 -311 -314 -317 -317 -313 -311 -315 -311 -311 -313 -314 -311 -311 -308 -308 -306 -305 -306 -309 -313 -311 -307 -305 -309 -305 -302 -301 -302 -298 -296 -296 -300 -302 -300 -298 -297 -298 -294 -298 -298 -302 -299 -303 -299 -297 -299 -302 -298 -297 -301 -301 -297 -300 -303 -300 -296 -296 -293 -297 -295 -297 -300 -300 -303 -304 -308 -305 -304 -301 -302 -298 -301 -300 -304 -300 -302 -298 -300 -300 -303 -303 -306 -309 -310 -310 -306 -310 -313 -310 -307 -311 -315 -316 -317 -317 -320 -324 -325 -323 -326 -325 -322 -319 -320 -317 -320 -324 -320 -316 -316 -312 -308 -306 -305 -309 -310 -306 -307 -310 -311 -315 -315 -315 -315 -311 -310 -314 -310 -309 -311 -314 -311 -315 -319 -316 -319 -323 -326 -326 -322 -318 -321 -319 -320 -316 -318 -320 -316 -312 -311 -307 -303 -299 -299 -302 -298 -302 -306 -309 -309 -312 -314 -317 -319 -318 -315 -311 -307 -306 -306 -308 -312 -311 -308 -310 -314 -310 -308 -311 -315 -317 -319 -315 -313 -313 -317 -314 -318 -319 -316 -316 -313 -314 -311 -314 -311 -312 -311 -307 -310 -306 -309 -308 -308 -309 -309 -312 -315 -319 -321 -323 -319 -321 -325 -326 -324 -320 -317 -316 -313 -315 -312 -311 -313 -317 -317 -315 -311 -307 -311 -314 -310 -308 -307 -308 -310 -309 -309 -310 -314 -312 -309 -308 -312 -310 -313 -309 -305 -309 -310 -306 -303 -307 -308 -308 -308 -310 -309 -308 -312 -312 -312 -310 -312 -315 -314 -316 -320 -320 -322 -323 -321 -321 -317 -314 -318 -314 -314 -316 -316 -316 -317 -318 -319 -318 -318 -321 -317 -318 -318 -317 -319 -316 -313 -309 -307 -305 -309 -307 -309 -310 -310 -306 -309 -312 -312 -312 -308 -306 -302 -304 -308 -305 -307 -303 -305 -305 -304 -301 -302 -305 -303 -306 -302 -300 -302 -303 -300 -303 -299 -296 -295 -295 -294 -296 -298 -302 -303 -302 -298 -299 -300 -303 -305 -303 -306 -308 -306 -304 -303 -303 -304 -302 -301 -304 -305 -309 -305 -303 -299 -295 -292 -292 -288 -286 -283 -279 -280 -276 -280 -278 -281 -278 -275 -279 -279 -278 -276 -277 -274 -278 -281 -285 -286 -290 -294 -296 -297 -294 -294 -295 -297 -301 -303 -302 -304 -302 -299 -297 -298 -294 -291 -290 -289 -285 -286 -283 -280 -281 -280 -281 -277 -277 -281 -278 -274 -278 -277 -278 -280 -284 -282 -282 -284 -287 -283 -284 -288 -292 -289 -291 -287 -283 -285 -289 -288 -285 -288 -289 -293 -296 -293 -294 -291 -287 -283 -280 -282 -284 -285 -287 -291 -289 -291 -287 -288 -287 -285 -281 -284 -283 -279 -282 -282 -285 -289 -287 -291 -290 -292 -294 -297 -294 -290 -293 -294 -295 -293 -295 -299 -295 -292 -288 -284 -286 -287 -287 -289 -293 -289 -285 -281 -283 -279 -275 -275 -277 -280 -278 -282 -286 -288 -288 -286 -283 -283 -284 -288 -285 -283 -282 -278 -282 -281 -281 -281 -278 -280 -276 -274 -277 -280 -282 -284 -282 -281 -278 -281 -285 -287 -286 -283 -284 -283 -279 -280 -279 -280 -277 -274 -271 -269 -267 -267 -266 -262 -265 -262 -259 -263 -263 -261 -259 -258 -254 -258 -258 -257 -259 -261 -259 -260 -257 -253 -249 -251 -250 -248 -247 -249 -247 -247 -244 -245 -244 -244 -242 -246 -243 -239 -243 -245 -246 -245 -248 -245 -248 -252 -256 -255 -253 -255 -259 -258 -257 -254 -257 -254 -255 -256 -257 -255 -256 -256 -254 -257 -256 -257 -259 -259 -258 -262 -260 -257 -260 -260 -261 -258 -262 -264 -267 -265 -261 -257 -256 -255 -256 -256 -255 -256 -253 -250 -252 -251 -254 -255 -259 -261 -261 -259 -258 -257 -260 -256 -260 -256 -255 -252 -248 -250 -248 -249 -249 -247 -247 -246 -246 -242 -239 -236 -240 -237 -237 -234 -234 -235 -239 -240 -241 -243 -242 -245 -241 -239 -239 -241 -241 -240 -239 -243 -247 -248 -251 -255 -254 -250 -249 -246 -248 -244 -242 -245 -247 -244 -244 -246 -246 -247 -247 -244 -244 -240 -239 -238 -239 -235 -233 -237 -238 -241 -240 -242 -240 -240 -236 -232 -233 -230 -232 -231 -231 -232 -233 -237 -238 -237 -238 -238 -242 -238 -239 -237 -234 -235 -237 -237 -234 -231 -227 -231 -229 -233 -237 -240 -242 -246 -242 -239 -241 -243 -246 -249 -251 -253 -251 -252 -249 -251 -255 -256 -252 -251 -255 -258 -254 -251 -247 -249 -251 -253 -252 -252 -250 -253 -253 -253 -254 -252 -248 -250 -250 -248 -250 -251 -251 -247 -243 -239 -239 -240 -237 -241 -239 -242 -240 -236 -234 -237 -237 -234 -235 -234 -232 -231 -235 -235 -233 -231 -228 -230 -226 -225 -224 -226 -226 -225 -228 -228 -225 -222 -219 -222 -226 -226 -230 -227 -225 -229 -229 -226 -226 -228 -226 -222 -223 -221 -224 -226 -223 -221 -217 -216 -213 -217 -216 -214 -216 -215 -217 -217 -213 -210 -208 -205 -202 -203 -205 -205 -207 -209 -209 -208 -212 -209 -207 -209 -205 -204 -202 -200 -203 -201 -205 -209 -213 -215 -217 -215 -218 -222 -224 -223 -219 -219 -217 -217 -219 -220 -218 -222 -224 -228 -230 -234 -232 -236 -238 -241 -245 -242 -243 -241 -239 -243 -240 -237 -235 -237 -235 -232 -228 -230 -229 -228 -227 -231 -231 -231 -231 -227 -231 -228 -230 -228 -224 -226 -222 -225 -226 -229 -227 -229 -231 -235 -235 -231 -229 -230 -232 -234 -231 -234 -232 -228 -229 -228 -231 -235 -238 -236 -237 -233 -237 -239 -235 -238 -236 -239 -236 -240 -236 -238 -235 -235 -234 -230 -230 -226 -222 -219 -215 -214 -218 -219 -221 -224 -223 -224 -225 -229 -226 -225 -228 -227 -229 -226 -229 -226 -230 -229 -227 -223 -225 -228 -225 -227 -229 -226 -224 -224 -226 -228 -228 -230 -231 -227 -229 -229 -233 -233 -229 -227 -223 -220 -220 -220 -222 -220 -224 -220 -217 -220 -224 -221 -217 -218 -218 -217 -220 -222 -219 -216 -215 -213 -214 -210 -207 -209 -207 -205 -207 -204 -205 -207 -206 -206 -206 -204 -202 -204 -205 -208 -210 -214 -218 -216 -220 -220 -217 -215 -216 -219 -220 -221 -220 -219 -222 -226 -226 -230 -234 -231 -232 -234 -237 -238 -239 -237 -241 -240 -239 -235 -232 -230 -226 -228 -228 -229 -225 -226 -225 -222 -221 -225 -229 -225 -222 -219 -218 -214 -210 -210 -208 -207 -204 -203 -207 -206 -206 -209 -206 -204 -203 -204 -206 -210 -206 -205 -209 -205 -203 -207 -205 -201 -199 -197 -193 -195 -192 -193 -192 -188 -187 -187 -188 -188 -192 -195 -195 -199 -199 -195 -199 -200 -203 -201 -202 -201 -204 -201 -198 -199 -197 -194 -197 -195 -196 -192 -191 -187 -190 -193 -192 -192 -192 -193 -196 -197 -197 -200 -199 -202 -203 -205 -205 -204 -208 -206 -210 -209 -207 -210 -211 -212 -209 -212 -213 -209 -212 -214 -213 -216 -218 -222 -222 -223 -223 -225 -221 -221 -221 -224 -227 -227 -231 -233 -229 -229 -233 -237 -238 -234 -234 -230 -227 -225 -229 -225 -224 -226 -223 -220 -220 -222 -222 -220 -216 -214 -218 -219 -221 -224 -221 -221 -225 -227 -227 -230 -232 -231 -229 -231 -228 -228 -230 -231 -231 -234 -234 -234 -233 -229 -230 -229 -226 -223 -222 -219 -216 -219 -220 -216 -218 -222 -220 -220 -223 -225 -222 -225 -223 -220 -218 -220 -218 -221 -222 -219 -215 -213 -214 -216 -218 -220 -221 -223 -227 -229 -228 -227 -226 -222 -226 -222 -225 -228 -229 -225 -228 -232 -233 -232 -236 -234 -235 -239 -239 -235 -237 -240 -240 -236 -238 -241 -243 -245 -247 -245 -248 -249 -252 -249 -250 -248 -252 -249 -248 -245 -248 -251 -247 -250 -246 -243 -241 -244 -244 -246 -250 -254 -254 -256 -253 -251 -250 -254 -250 -254 -251 -250 -253 -254 -256 -254 -256 -260 -262 -261 -262 -260 -259 -260 -256 -259 -256 -252 -250 -253 -254 -257 -258 -258 -254 -255 -256 -259 -255 -259 -260 -256 -257 -253 -253 -255 -258 -256 -256 -254 -256 -259 -260 -263 -264 -260 -259 -263 -260 -264 -266 -267 -270 -272 -271 -269 -272 -268 -270 -273 -272 -275 -279 -278 -276 -276 -272 -274 -276 -273 -272 -272 -270 -273 -271 -267 -266 -263 -266 -264 -261 -264 -263 -261 -264 -262 -260 -259 -257 -256 -255 -256 -256 -258 -260 -261 -259 -261 -258 -257 -258 -258 -257 -254 -254 -255 -251 -249 -248 -249 -251 -247 -248 -249 -251 -250 -251 -247 -250 -254 -252 -252 -252 -251 -247 -244 -246 -244 -242 -244 -240 -238 -239 -238 -235 -235 -235 -236 -234 -238 -234 -231 -227 -226 -226 -222 -220 -224 -223 -221 -225 -226 -229 -233 -231 -228 -225 -223 -225 -222 -221 -219 -215 -214 -212 -212 -208 -205 -207 -209 -208 -204 -204 -200 -204 -204 -205 -206 -208 -206 -207 -205 -203 -205 -202 -203 -202 -198 -196 -199 -201 -205 -201 -197 -193 -192 -196 -196 -198 -197 -196 -200 -198 -200 -199 -202 -199 -200 -202 -200 -200 -200 -201 -198 -202 -198 -197 -193 -197 -201 -201 -200 -198 -194 -192 -194 -196 -199 -202 -206 -203 -201 -199 -200 -203 -201 -197 -201 -203 -207 -205 -208 -212 -216 -218 -216 -212 -209 -208 -212 -209 -207 -205 -208 -209 -205 -209 -206 -204 -205 -209 -208 -210 -207 -209 -206 -206 -209 -205 -203 -201 -200 -197 -201 -197 -196 -194 -191 -187 -184 -187 -188 -192 -191 -194 -193 -193 -190 -186 -183 -186 -190 -193 -191 -192 -193 -194 -197 -200 -198 -196 -195 -191 -191 -189 -192 -189 -186 -185 -185 -187 -191 -193 -193 -190 -188 -192 -188 -184 -188 -187 -190 -191 -194 -190 -190 -193 -191 -193 -196 -197 -196 -196 -198 -202 -199 -200 -199 -203 -204 -208 -207 -206 -204 -202 -203 -206 -207 -203 -201 -202 -205 -201 -197 -198 -194 -190 -191 -187 -190 -187 -186 -189 -192 -192 -191 -188 -192 -195 -199 -201 -199 -203 -205 -202 -203 -203 -206 -210 -213 -215 -219 -217 -214 -214 -212 -215 -212 -214 -216 -218 -219 -220 -219 -216 -218 -214 -214 -213 -209 -211 -212 -211 -212 -210 -208 -211 -215 -214 -217 -213 -209 -212 -208 -212 -212 -214 -214 -210 -208 -206 -207 -205 -207 -204 -203 -204 -204 -201 -205 -202 -201 -202 -205 -208 -205 -203 -204 -202 -205 -208 -211 -207 -207 -208 -212 -212 -210 -207 -207 -203 -201 -203 -199 -202 -205 -201 -203 -203 -205 -202 -202 -200 -204 -208 -209 -212 -215 -213 -212 -208 -209 -212 -214 -217 -213 -216 -215 -217 -215 -216 -213 -210 -208 -209 -212 -211 -207 -206 -208 -209 -206 -210 -207 -203 -204 -203 -201 -197 -195 -198 -197 -199 -195 -198 -201 -204 -202 -205 -202 -199 -195 -197 -195 -195 -194 -190 -190 -192 -189 -189 -188 -189 -190 -186 -182 -184 -180 -176 -180 -177 -180 -183 -184 -182 -182 -185 -188 -190 -189 -193 -191 -194 -196 -194 -191 -195 -197 -193 -193 -194 -196 -196 -198 -201 -203 -203 -199 -195 -197 -200 -199 -197 -195 -198 -202 -201 -204 -200 -197 -195 -198 -198 -194 -194 -195 -192 -193 -194 -196 -194 -191 -193 -189 -191 -187 -188 -187 -184 -184 -182 -179 -179 -179 -182 -179 -178 -181 -181 -181 -178 -174 -178 -175 -174 -178 -174 -176 -174 -171 -173 -174 -170 -169 -170 -173 -169 -166 -167 -167 -164 -161 -164 -167 -170 -167 -168 -164 -163 -164 -164 -161 -159 -159 -162 -159 -156 -158 -162 -162 -166 -164 -166 -166 -165 -168 -166 -169 -171 -173 -174 -174 -173 -172 -168 -165 -165 -162 -158 -156 -155 -158 -156 -160 -160 -160 -156 -155 -153 -154 -152 -154 -155 -159 -157 -160 -161 -157 -159 -162 -165 -165 -161 -159 -158 -158 -159 -162 -166 -167 -165 -166 -162 -159 -156 -153 -153 -153 -151 -149 -149 -151 -152 -149 -146 -147 -150 -149 -148 -149 -148 -144 -148 -145 -146 -143 -144 -144 -142 -145 -149 -150 -152 -150 -150 -152 -151 -149 -147 -145 -142 -145 -142 -140 -143 -145 -146 -148 -150 -150 -153 -149 -146 -149 -153 -154 -153 -156 -155 -158 -162 -162 -158 -160 -160 -159 -157 -159 -161 -163 -167 -163 -160 -161 -160 -160 -157 -159 -163 -161 -159 -160 -156 -155 -153 -149 -149 -146 -143 -144 -143 -140 -143 -146 -146 -142 -139 -143 -147 -146 -142 -145 -147 -146 -146 -144 -143 -146 -148 -144 -147 -144 -142 -141 -143 -143 -140 -144 -143 -146 -149 -147 -147 -150 -146 -150 -146 -150 -153 -156 -160 -164 -163 -164 -164 -164 -163 -160 -159 -163 -163 -163 -159 -162 -159 -158 -158 -160 -163 -165 -167 -167 -164 -162 -166 -165 -168 -164 -165 -163 -164 -161 -161 -165 -168 -169 -170 -166 -164 -165 -165 -167 -169 -172 -176 -178 -181 -181 -177 -175 -178 -179 -177 -178 -181 -178 -175 -173 -172 -168 -164 -160 -158 -158 -160 -159 -162 -162 -159 -159 -161 -161 -164 -162 -163 -162 -158 -158 -160 -157 -157 -158 -156 -153 -155 -158 -161 -165 -161 -160 -159 -157 -155 -151 -149 -152 -155 -157 -153 -157 -159 -161 -164 -162 -159 -159 -157 -159 -156 -154 -153 -156 -156 -154 -157 -158 -156 -157 -157 -161 -158 -160 -157 -160 -158 -161 -164 -168 -171 -167 -168 -170 -174 -171 -167 -169 -170 -169 -165 -161 -163 -164 -162 -163 -163 -160 -160 -160 -163 -165 -162 -159 -163 -161 -158 -154 -153 -157 -156 -154 -153 -155 -158 -159 -161 -157 -155 -157 -157 -154 -153 -150 -146 -150 -150 -149 -153 -150 -146 -147 -147 -145 -144 -140 -138 -141 -137 -139 -143 -146 -147 -143 -144 -143 -144 -144 -147 -151 -155 -157 -157 -159 -163 -163 -159 -163 -164 -167 -170 -168 -165 -168 -169 -170 -172 -170 -169 -173 -177 -177 -181 -177 -181 -180 -176 -178 -182 -180 -180 -178 -176 -174 -172 -175 -176 -173 -176 -173 -169 -167 -165 -161 -157 -160 -156 -154 -152 -155 -156 -160 -162 -161 -163 -166 -168 -167 -170 -171 -167 -169 -166 -163 -162 -158 -156 -157 -157 -161 -158 -160 -158 -155 -154 -156 -158 -158 -160 -156 -160 -156 -160 -164 -167 -167 -166 -162 -164 -163 -161 -163 -162 -160 -163 -161 -163 -160 -158 -162 -166 -163 -167 -164 -160 -158 -156 -159 -161 -165 -165 -168 -169 -170 -166 -167 -168 -169 -169 -165 -168 -166 -163 -166 -162 -161 -165 -164 -163 -167 -163 -166 -167 -163 -163 -167 -171 -170 -167 -164 -165 -167 -166 -169 -168 -164 -168 -171 -174 -177 -178 -181 -181 -185 -184 -185 -183 -187 -186 -185 -189 -191 -195 -192 -193 -197 -201 -197 -193 -197 -196 -196 -196 -195 -194 -195 -191 -191 -188 -186 -185 -183 -186 -189 -192 -190 -191 -195 -193 -196 -192 -188 -187 -184 -183 -184 -180 -183 -186 -187 -186 -188 -186 -186 -185 -186 -186 -184 -187 -185 -184 -186 -188 -187 -184 -187 -186 -185 -186 -188 -188 -186 -186 -185 -183 -184 -183 -184 -186 -188 -189 -193 -195 -194 -197 -193 -189 -188 -184 -187 -189 -185 -188 -191 -191 -189 -191 -195 -193 -190 -191 -189 -185 -184 -180 -177 -179 -181 -182 -185 -189 -193 -192 -194 -194 -191 -187 -183 -183 -180 -176 -173 -170 -168 -167 -169 -167 -167 -171 -171 -172 -174 -176 -177 -178 -176 -173 -174 -177 -174 -176 -180 -177 -179 -180 -181 -177 -179 -179 -181 -182 -185 -181 -183 -179 -177 -181 -180 -176 -178 -181 -182 -179 -178 -174 -173 -175 -175 -175 -179 -180 -181 -180 -184 -183 -180 -183 -183 -187 -189 -189 -193 -196 -199 -199 -197 -199 -199 -195 -192 -192 -195 -197 -197 -195 -199 -200 -196 -200 -204 -201 -200 -202 -200 -197 -196 -200 -202 -200 -198 -194 -197 -200 -198 -199 -196 -199 -203 -201 -205 -201 -197 -197 -196 -199 -199 -202 -199 -195 -194 -195 -197 -194 -192 -192 -196 -199 -199 -201 -197 -201 -200 -201 -197 -200 -197 -193 -193 -196 -200 -204 -206 -203 -202 -201 -201 -203 -202 -201 -202 -198 -196 -200 -200 -196 -198 -195 -191 -189 -188 -186 -183 -181 -181 -182 -184 -187 -188 -186 -183 -185 -182 -182 -182 -180 -177 -174 -177 -181 -180 -180 -176 -175 -175 -171 -172 -169 -166 -164 -161 -165 -166 -168 -165 -163 -167 -167 -164 -167 -166 -169 -171 -172 -170 -172 -170 -170 -168 -166 -162 -159 -162 -162 -163 -163 -162 -161 -164 -165 -166 -166 -163 -163 -163 -164 -167 -164 -163 -167 -171 -172 -169 -166 -165 -164 -161 -160 -162 -165 -163 -163 -161 -161 -163 -160 -161 -161 -157 -154 -158 -157 -158 -162 -159 -161 -164 -166 -162 -158 -155 -154 -155 -159 -161 -159 -156 -153 -149 -148 -144 -142 -144 -144 -142 -141 -141 -141 -137 -134 -138 -142 -143 -146 -146 -142 -139 -138 -140 -140 -139 -139 -140 -143 -142 -139 -140 -140 -143 -146 -150 -147 -145 -141 -143 -139 -136 -133 -130 -126 -128 -128 -127 -131 -130 -130 -130 -127 -129 -131 -131 -130 -126 -127 -127 -128 -126 -122 -121 -124 -121 -118 -114 -112 -114 -115 -119 -120 -123 -119 -116 -112 -115 -113 -109 -110 -110 -114 -113 -109 -106 -102 -104 -108 -106 -104 -105 -105 -106 -103 -105 -102 -98 -100 -101 -103 -101 -105 -106 -108 -111 -114 -114 -116 -113 -112 -112 -116 -116 -115 -112 -112 -108 -106 -110 -111 -111 -114 -113 -116 -119 -118 -115 -115 -117 -121 -125 -127 -123 -124 -128 -126 -127 -125 -122 -126 -122 -119 -121 -122 -125 -124 -120 -116 -116 -112 -108 -108 -110 -108 -112 -109 -108 -105 -103 -99 -102 -106 -103 -107 -104 -100 -101 -99 -96 -95 -97 -99 -103 -102 -98 -100 -103 -103 -101 -100 -97 -97 -97 -96 -96 -93 -93 -92 -94 -90 -87 -91 -94 -95 -96 -96 -97 -99 -97 -98 -98 -99 -102 -98 -102 -104 -103 -105 -109 -110 -112 -109 -106 -110 -106 -105 -104 -107 -107 -103 -99 -96 -100 -100 -96 -93 -94 -94 -95 -96 -96 -98 -94 -96 -93 -94 -92 -95 -95 -91 -87 -84 -88 -91 -88 -84 -88 -84 -83 -81 -81 -77 -79 -76 -74 -75 -71 -67 -67 -64 -65 -61 -57 -59 -55 -52 -55 -51 -48 -48 -46 -45 -49 -50 -50 -48 -52 -55 -58 -60 -58 -57 -55 -57 -56 -57 -57 -53 -54 -58 -62 -66 -63 -64 -61 -62 -59 -58 -58 -57 -57 -58 -60 -57 -55 -56 -55 -51 -47 -50 -52 -49 -50 -52 -48 -44 -46 -45 -45 -46 -42 -46 -45 -47 -47 -49 -47 -43 -47 -43 -44 -42 -41 -37 -39 -36 -34 -37 -41 -41 -41 -41 -42 -43 -45 -49 -47 -44 -43 -44 -47 -48 -52 -52 -51 -50 -47 -46 -50 -53 -49 -52 -56 -57 -53 -50 -51 -50 -53 -49 -52 -50 -51 -54 -51 -52 -49 -50 -51 -48 -52 -48 -47 -46 -49 -49 -46 -42 -41 -42 -43 -45 -44 -40 -44 -48 -51 -54 -50 -51 -55 -59 -62 -66 -63 -66 -65 -69 -71 -72 -75 -73 -72 -75 -75 -72 -70 -74 -75 -79 -78 -75 -79 -77 -73 -71 -72 -69 -71 -75 -78 -74 -76 -76 -75 -71 -71 -67 -69 -71 -73 -72 -76 -74 -78 -77 -80 -77 -76 -78 -74 -74 -77 -80 -78 -78 -81 -79 -77 -73 -77 -73 -71 -74 -72 -74 -78 -79 -83 -79 -80 -84 -86 -85 -86 -90 -90 -91 -93 -91 -95 -97 -95 -94 -97 -101 -97 -94 -97 -100 -103 -102 -98 -98 -97 -93 -91 -95 -96 -98 -96 -99 -103 -104 -105 -103 -104 -102 -101 -98 -102 -103 -99 -101 -100 -102 -103 -104 -106 -105 -103 -103 -99 -101 -104 -103 -99 -97 -100 -98 -100 -102 -99 -98 -98 -101 -102 -101 -99 -96 -97 -99 -99 -100 -101 -100 -96 -99 -101 -105 -101 -99 -98 -97 -93 -90 -92 -92 -94 -97 -99 -102 -103 -100 -97 -99 -97 -99 -102 -105 -109 -113 -113 -115 -113 -109 -106 -106 -107 -103 -104 -102 -103 -101 -103 -99 -103 -103 -104 -100 -104 -101 -99 -98 -95 -97 -101 -97 -98 -94 -94 -97 -101 -102 -105 -101 -103 -105 -109 -109 -112 -108 -110 -108 -109 -109 -109 -113 -116 -120 -119 -117 -117 -119 -115 -114 -113 -116 -116 -114 -117 -120 -122 -123 -120 -118 -121 -125 -128 -130 -134 -137 -139 -142 -143 -141 -143 -141 -139 -141 -137 -139 -140 -144 -144 -141 -140 -144 -140 -137 -133 -133 -135 -132 -129 -128 -132 -136 -138 -138 -137 -133 -134 -131 -132 -130 -127 -125 -126 -127 -128 -129 -129 -130 -133 -132 -133 -137 -141 -144 -140 -137 -133 -133 -135 -139 -143 -144 -144 -148 -146 -145 -149 -147 -151 -147 -150 -152 -150 -148 -146 -145 -143 -139 -141 -141 -139 -143 -145 -148 -144 -146 -144 -148 -149 -147 -149 -145 -149 -148 -151 -153 -156 -156 -152 -155 -152 -154 -150 -151 -152 -149 -146 -145 -146 -145 -144 -147 -151 -155 -159 -156 -159 -158 -160 -159 -157 -160 -158 -154 -158 -154 -157 -157 -155 -155 -158 -158 -157 -155 -151 -151 -147 -150 -149 -145 -147 -143 -139 -142 -142 -141 -138 -139 -139 -140 -140 -144 -146 -148 -144 -146 -147 -147 -143 -145 -142 -146 -146 -143 -145 -149 -148 -152 -149 -148 -146 -146 -144 -140 -139 -140 -144 -141 -144 -147 -145 -147 -145 -146 -148 -145 -144 -148 -149 -146 -147 -143 -141 -142 -146 -143 -140 -139 -138 -136 -139 -135 -135 -132 -134 -135 -139 -140 -141 -137 -135 -138 -137 -134 -133 -134 -130 -133 -136 -137 -136 -134 -137 -137 -141 -143 -146 -150 -151 -153 -157 -161 -158 -158 -160 -162 -163 -159 -158 -158 -161 -163 -167 -163 -166 -166 -167 -163 -159 -159 -157 -157 -156 -152 -151 -150 -152 -153 -153 -155 -151 -153 -153 -154 -150 -154 -150 -149 -151 -155 -151 -148 -144 -144 -140 -138 -134 -132 -131 -131 -128 -131 -128 -127 -126 -130 -126 -129 -127 -129 -125 -125 -124 -121 -125 -124 -128 -126 -126 -126 -124 -121 -125 -127 -129 -133 -134 -135 -138 -141 -143 -142 -141 -138 -136 -133 -130 -126 -125 -124 -123 -119 -117 -116 -112 -115 -118 -118 -117 -114 -111 -112 -108 -106 -106 -108 -105 -101 -103 -101 -102 -99 -101 -99 -101 -102 -103 -106 -103 -103 -100 -96 -95 -92 -90 -88 -85 -83 -79 -78 -76 -73 -71 -74 -73 -75 -71 -71 -69 -66 -66 -63 -61 -59 -62 -58 -59 -59 -55 -57 -59 -60 -56 -56 -53 -56 -57 -55 -52 -56 -54 -57 -61 -57 -54 -56 -58 -61 -59 -56 -60 -57 -54 -57 -60 -60 -63 -63 -65 -62 -58 -59 -59 -62 -65 -68 -71 -67 -63 -66 -68 -70 -74 -74 -72 -71 -68 -72 -68 -66 -66 -65 -65 -69 -71 -69 -66 -69 -71 -75 -75 -73 -69 -67 -66 -66 -68 -65 -61 -62 -66 -69 -68 -72 -73 -73 -69 -72 -74 -77 -76 -77 -77 -77 -77 -76 -80 -79 -76 -77 -77 -79 -78 -78 -77 -78 -82 -85 -89 -86 -85 -87 -85 -88 -92 -91 -87 -89 -92 -90 -91 -87 -83 -85 -87 -89 -89 -87 -84 -87 -84 -82 -78 -75 -79 -80 -81 -78 -81 -83 -83 -86 -85 -81 -82 -83 -82 -82 -79 -76 -75 -75 -76 -77 -79 -82 -83 -81 -78 -75 -78 -77 -73 -70 -68 -68 -67 -68 -67 -68 -68 -67 -63 -66 -70 -73 -74 -70 -72 -71 -71 -71 -71 -73 -71 -67 -67 -63 -62 -61 -58 -55 -51 -53 -49 -46 -48 -48 -46 -48 -48 -45 -45 -45 -44 -40 -42 -39 -39 -36 -39 -42 -44 -46 -49 -48 -47 -50 -54 -53 -55 -56 -57 -58 -60 -62 -65 -67 -67 -69 -68 -71 -73 -70 -70 -73 -69 -73 -70 -70 -67 -66 -66 -63 -60 -59 -57 -58 -56 -60 -57 -60 -64 -60 -62 -63 -67 -64 -61 -64 -63 -63 -59 -63 -65 -63 -59 -59 -62 -58 -55 -52 -51 -52 -53 -53 -51 -52 -49 -48 -50 -54 -51 -50 -46 -43 -42 -38 -40 -40 -40 -36 -35 -38 -40 -40 -38 -40 -42 -45 -47 -43 -46 -43 -44 -47 -43 -46 -42 -46 -44 -48 -51 -51 -49 -53 -54 -56 -57 -57 -54 -56 -56 -53 -54 -55 -52 -51 -47 -44 -48 -46 -47 -49 -52 -52 -49 -52 -51 -48 -45 -43 -40 -43 -40 -41 -45 -42 -39 -43 -46 -50 -47 -46 -47 -43 -42 -46 -47 -49 -53 -55 -57 -53 -53 -51 -51 -47 -45 -48 -46 -47 -46 -42 -40 -43 -44 -45 -41 -38 -35 -34 -30 -28 -30 -32 -29 -27 -23 -21 -21 -24 -24 -28 -28 -24 -20 -20 -22 -23 -23 -21 -23 -19 -20 -22 -19 -22 -19 -22 -21 -22 -19 -21 -18 -21 -25 -23 -20 -22 -22 -22 -20 -22 -19 -18 -15 -16 -20 -23 -22 -26 -29 -28 -29 -33 -30 -26 -29 -30 -28 -29 -27 -28 -25 -23 -22 -23 -20 -24 -27 -23 -26 -23 -23 -24 -23 -19 -23 -19 -21 -23 -19 -22 -23 -26 -23 -27 -27 -26 -28 -26 -23 -25 -22 -26 -30 -30 -33 -33 -29 -28 -29 -27 -26 -26 -24 -28 -31 -31 -34 -32 -28 -27 -28 -31 -27 -28 -28 -29 -32 -32 -35 -31 -31 -32 -33 -36 -40 -41 -41 -42 -41 -45 -41 -38 -42 -45 -43 -39 -39 -40 -43 -45 -46 -45 -41 -40 -43 -45 -41 -38 -41 -40 -44 -40 -43 -39 -39 -38 -41 -40 -40 -39 -35 -35 -34 -37 -39 -39 -39 -36 -37 -39 -35 -31 -32 -31 -30 -30 -31 -34 -30 -34 -37 -36 -33 -33 -33 -33 -34 -32 -30 -34 -38 -35 -39 -35 -37 -40 -38 -35 -34 -37 -41 -43 -39 -38 -41 -44 -46 -43 -45 -48 -49 -45 -43 -39 -37 -38 -38 -37 -33 -29 -32 -32 -30 -29 -26 -23 -21 -17 -16 -15 -14 -14 -13 -14 -16 -15 -18 -17 -20 -19 -16 -18 -18 -22 -19 -20 -23 -25 -21 -17 -15 -17 -14 -13 -13 -17 -13 -14 -16 -18 -17 -19 -17 -18 -16 -14 -13 -12 -14 -12 -9 -9 -11 -15 -15 -11 -12 -13 -17 -18 -21 -23 -19 -18 -22 -18 -14 -14 -13 -12 -9 -8 -12 -14 -14 -16 -16 -17 -20 -23 -20 -20 -18 -22 -21 -24 -28 -28 -28 -25 -27 -30 -28 -31 -31 -31 -29 -30 -34 -37 -33 -34 -37 -40 -38 -34 -36 -32 -28 -31 -30 -31 -31 -34 -34 -35 -33 -31 -31 -29 -33 -37 -38 -35 -37 -33 -29 -29 -30 -34 -31 -31 -29 -28 -26 -25 -29 -25 -21 -22 -18 -21 -24 -22 -22 -21 -22 -21 -23 -23 -22 -24 -23 -19 -16 -14 -13 -15 -16 -19 -22 -18 -17 -13 -11 -13 -12 -15 -15 -17 -17 -21 -19 -23 -25 -29 -27 -29 -28 -24 -26 -29 -30 -28 -25 -21 -23 -23 -20 -19 -22 -19 -23 -23 -26 -23 -21 -23 -26 -30 -33 -35 -39 -36 -32 -30 -28 -24 -22 -24 -26 -29 -32 -36 -35 -35 -37 -34 -37 -40 -38 -35 -34 -30 -29 -31 -35 -36 -32 -36 -36 -36 -33 -30 -27 -23 -27 -29 -30 -31 -28 -30 -32 -29 -30 -26 -23 -26 diff --git a/hw2/encoding.py b/hw2/encoding.py deleted file mode 100644 index 2a1f834..0000000 --- a/hw2/encoding.py +++ /dev/null @@ -1,59 +0,0 @@ -'''ecoding.py provides utilities for compressing a file of data -using a 'delta' encoding (change over the previous) element. -''' -import struct - -#TODO 1. Write a function that loads the input data -#and returns a list of numbers -def load_orig_file(in_filename): - '''load_orig_file takes an input file and returns a list of - numbers. The file is formatted with a single integer - number on each line - ''' - - raise ValueError('Not implemented') - - -#TODO 2. Write a function that performs the delta encoding -def delta_encoding(data): - '''delta_encoding takes a list of integers and performs - a delta encoding represent each element as a difference - from the previous one. The first element is kept as is. - - delta_encoding encoding returns a list where the first - element is the original value and all the rest of the - elements are deltas from the first value. - ''' - - raise ValueError('Not implemented') - - -#TODO 3. Apply a shift to all the elements so all the deltas are positive -def shift(data, offset): - '''shift adds 'offset' to all of the elements to ensure that - every value in the delta encoding is positive. - ''' - raise ValueError('Not implemented') - -#GIVEN, should be obvious what it does -def unshift(data, offset): - return shift(data,-offset) - -#TODO 4. Convert the encoded data into a byte array and write -#to disk. -def write_encoding(data, out_file): - raise ValueError('Not implemented') - -#GIVEN, read encoded file -def read_encoding(out_file): - f = open(out_file, 'rb') - encoded = f.read() - return struct.unpack("B"*len(encoded), encoded) - - -#TODO 5. Write a function that performs the delta encoding -def delta_decoding(data): - '''delta_decoding takes a delta encoded list and return - the original data. - ''' - raise ValueError('Not implemented') \ No newline at end of file diff --git a/hw3/README.md b/hw3/README.md index 9cd6aea..30c1e9f 100644 --- a/hw3/README.md +++ b/hw3/README.md @@ -1,7 +1,7 @@ -# Homework 2. Bloom Filter -This homework assignment introduces an advanced use of hashing called a Bloom filter. +# Homework 1. Introduction to Python and File I/O +This homework assignment is meant to be an introduction to Python programming and introduces some basic concepts of encoding and decoding. -Due Date: *Friday May 1st, 2020 11:59 pm* +Due Date: *Friday April 17, 2020 11:59 pm* ## Initial Setup These initial setup instructions assume you've done ``hw0``. Before you start an assingment you should sync your cloned repository with the online one: @@ -10,9 +10,9 @@ $ cd cmsc13600-materials $ git pull ``` -Copy the folder ``hw2`` to your newly cloned submission repository. Enter that repository from the command line and enter the copied ``hw2`` folder. In this homework assignment, you will only modify ``bloom.py``. Once you are done, you must add 'bloom.py' to git: +Copy the folder ``hw1`` to your newly cloned submission repository. Enter that repository from the command line and enter the copied ``hw1`` folder. In this homework assignment, you will only modify ``encoding.py``. Once you are done, you must add 'encoding.py' to git: ``` -$ git add bloom.py +$ git add encoding.py ``` After adding your files, to submit your code you must run: ``` @@ -21,44 +21,65 @@ $ git push ``` We will NOT grade any code that is not added, committed, and pushed to your submission repository. You can confirm your submission by visiting the web interface[https://mit.cs.uchicago.edu/cmsc13600-spr-20/skr] -## Bloom filter -A Bloom filter is a space-efficient probabilistic data structure, conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set. False positive matches are possible, but false negatives are not – in other words, a query returns either "possibly in set" or "definitely not in set." Elements can be added to the set, but not removed (though this can be addressed with the counting Bloom filter variant); the more items added, the larger the probability of false positives. All of the necessary parts that you need to write are marked with *TODO*. +## Delta Encoding +Delta encoding is a way of storing or transmitting data in the form of differences (deltas) between sequential data rather than complete files. +In this first assignment, you will implement a delta encoding module in python. +The module will: +* Load a file of integers +* Delta encode them +* Write back a file in binary form -Here's how the basic Bloom filter works: +The instructions in this assignment are purposefully incomplete for you to read Python's API and to understand how the different functions work. All of the necessary parts that you need to write are marked with *TODO*. -### Initialization -* An empty Bloom filter is initialized with an array of *m* elements each with value 0. -* Generate *k* independent hash functions whose output domain are integers {0,...,m}. +## TODO 1. Loading the data file +In `encoding.py`, your first task is to write `load_orig_file`. This function reads from a specified filename and returns a list of integers in the file. You may assume the file is formatted like ``data.txt`` provided with the code, where each line contains a single integer number. The input of this function is a filename and the output is a list of numbers. If the file does not exist you must raise an exception. -### Adding An Item e -* For each hash function calculate the hash value of the item "e" (should be a number from 0 to m). -* Treat those calculated hash values as indices for the array and set each corresponding index in the array to 1 (if it is already 1 from a previous addition keep it as is). +## TODO 2. Compute the basic encoding +In `encoding.py`, your next task is to write `delta_encoding`. This function takes a list of numbers and computes the delta encoding. The delta encoding encodes the list in terms of successive differences from the previous element. The first element is kept as is in the encoding. -### Contains An Item e -* For each hash function calculate the hash value of the item "e" (should be a number from 0 to m). -* Treat those calculated hash values as indices for the array and retrieve the array value for each corresponding index. If any of the values is 0, we know that "e" could not have possibly been inserted in the past. +For example: +``` +> data = [1,3,4,3] +> enc = delta_encoding(data) +1,2,1,-1 +``` -## TODO 1. Generate K independent Hash Functions -Your first task is to write the function `generate_hashes`. This function is a higher-order function that returns a list of *k* random hash functions each with a range from 0 to *m*. Here are some hints that will help you write this function. +Or, +``` +> data = [1,0,6,1] +> enc = delta_encoding(data) +1,-1,6,-5 +``` +Your job is to write a function that computes this encoding. Pay close attention to how python passes around references and where you make copies of lists v.s. modify a list in place. -* Step 1. Review the "linear" hash function described in lecture and write a helper function that generates such a hash function for a pre-defined A and B. How would you restrict the domain of this hash function to be with 0 to m? +## TODO 3. Integer Shifting +When we write this data to a file, we will want to represent each encoded value as an unsigned short integer (1 single byte of data). To do so, we have to "shift" all of the values upwards so there are no negatives. You will write a function `shift` that adds a pre-specified offset to each value. -* Step 2. Generate k of such functions with different random settings of A and B. Pay close attention to how many times you call "random.x" because of how the seeded random variable works. +## TODO 4. Write Encoding +Now, we are ready to write the encoded data to disk. In the function `write_encoding`, you will do the following steps: +* Open the specified filename in the function arguments for writing +* Convert the encoded list of numbers into a bytearray +* Write the bytearray to the file +* Close the file -* Step 3. Return the functions themselves so they can be applied to data. Look at the autograder to understand what inputs these functions should take. +Reading from such a file is a little tricky, so we've provided that function for you. -## TODO 2. Put -Write a function that uses the algorithm listed above to add a string to the bloom filter. In pseudo-code: -* For each of the k hash functions: -* Compute the hash code of the string, and store the code in i -* Set the ith element of the array to 1 +## TODO 5. Delta Decoding +Finally, you will write a function that takes a delta encoded list and recovers the original data. This should do the opposite of what you did before. Don't forget to unshift the data when you are testing! -## TODO 3. Get -Write a function that uses the algorithm listed above to test whether the bloom filter possibly contains the string. In pseudo-code: -* For each of the k hash functions: -* Compute the hash code of the string, and store the code in i -* if the ith element is 0, return false -* if all code-indices are 1, return true +For example: +``` +> enc = [1,2,1,-1] +> data = delta_decoding(enc) +1,3,4,3 +``` + +Or, +``` +> data = [1,-1,6,-5] +> data = delta_decoding(enc) +1,0,6,1 +``` ## Testing -We've provided an autograder script `autograder.py` which runs a bunch of interesting tests. The autograder is not comprehensive but it is a good start. It's up to you to figure out what the test do and why they work. +We've provided a sample dataset ``data.txt`` which can be used to test your code as well as an autograder script `autograder.py` which runs a bunch of interesting tests. The autograder is not comprehensive but it is a good start. It's up to you to figure out what the test do and why they work. diff --git a/hw3/auto_grader.py b/hw3/auto_grader.py index 4715d4e..0b4bebe 100644 --- a/hw3/auto_grader.py +++ b/hw3/auto_grader.py @@ -1,112 +1,82 @@ import random -import string +from encoding import * -from bloom import * - -def generate_random_string(seed=True): - chars = string.ascii_uppercase + string.digits - size = 10 - return ''.join(random.choice(chars) for x in range(size)) - -def test_hash_generation(): - b = Bloom(5,10) - - try: - assert(len(b.hashes) == 10) - except: - print('[#1] Failure the number of generated hashes is wrong') +def test_load(): + data = load_orig_file('data.txt') try: + assert(sum(data) == 1778744) + except AssertionError: + print('TODO 1. Failure check your load_orig_file function') - for h in b.hashes: - h(generate_random_string()) - - except: - print('[#2] The hashes are not properly represented as a lambda') - - - s = generate_random_string() +def test_encoding(): + data = load_orig_file('data.txt') + encoded = delta_encoding(data) try: - for h in b.hashes: - assert(h(s) == h(s)) - except: - print('[#3] Hashes are not deterministic') + assert(sum(encoded) == data[-1]) + assert(sum(encoded) == 26) + assert(len(data) == len(encoded)) + except AssertionError: + print('TODO 2. Failure check your delta_encoding function') +def test_shift(): + data = load_orig_file('data.txt') + encoded = delta_encoding(data) + N = len(data) try: - b = Bloom(100,10) - b1h = b.hashes[0](s) - b = Bloom(100,10) - b2h = b.hashes[0](s) - - assert(b1h == b2h) - - except: - print('[#4] Seeds are not properly set') + assert(sum(shift(data, 10)) == N*10 + sum(data)) + assert(all([d >=0 for d in shift(encoded,4)])) + except AssertionError: + print('TODO 3. Failure check your shift function') +def test_decoding(): + data = load_orig_file('data.txt') + encoded = delta_encoding(data) + sencoded = shift(encoded ,4) + data_p = delta_decoding(unshift(sencoded,4)) try: - b = Bloom(100,10) - - for h in b.hashes: - for i in range(10): - assert( h(generate_random_string())< 100 ) + assert(data == data_p) + except AssertionError: + print('TODO 5. Cannot recover data with delta_decoding') - except: - print('[#5] Hash exceeds range') +def generate_file(size, seed): + FILE_NAME = 'data.gen.txt' + f = open(FILE_NAME,'w') - try: - b = Bloom(1000,2) - s = generate_random_string() - bh1 = b.hashes[0](s) - bh2 = b.hashes[1](s) + initial = seed + for i in range(size): + f.write(str(initial) + '\n') + initial += random.randint(-4, 4) - assert(bh1 != bh2) +def generate_random_tests(): + SIZES = (1,1000,16,99) + SEEDS = (240,-3, 9, 1) - except: - print('[#6] Hashes generated are not independent') + cnt = 0 + for trials in range(10): + generate_file(random.choice(SIZES), random.choice(SEEDS)) -def test_put(): - b = Bloom(100,10,seed=0) - b.put('the') - b.put('university') - b.put('of') - b.put('chicago') + data = load_orig_file('data.gen.txt') + encoded = delta_encoding(data) + sencoded = shift(encoded ,4) + write_encoding(sencoded, 'data_out.txt') - try: - assert(sum(b.array) == 30) - except: - print('[#7] Unexpected Put() Result') - -def test_put_get(): - b = Bloom(100,5,seed=0) - b.put('the') - b.put('quick') - b.put('brown') - b.put('fox') - b.put('jumped') - b.put('over') - b.put('the') - b.put('lazy') - b.put('dog') - - results = [b.contains('the'),\ - b.contains('cow'), \ - b.contains('jumped'), \ - b.contains('over'),\ - b.contains('the'), \ - b.contains('moon')] + loaded = unshift(read_encoding('data_out.txt'),4) + decoded = delta_decoding(loaded) + + cnt += (decoded == data) try: - assert(results == [True, False, True, True, True, False]) - except: - print('[#8] Unexpected contains result') - -test_hash_generation() -test_put() -test_put_get() - - - + assert(cnt == 10) + except AssertionError: + print('Failed Random Tests', str(10-cnt), 'out of 10') + +test_load() +test_encoding() +test_shift() +test_decoding() +generate_random_tests() \ No newline at end of file diff --git a/hw3/bloom.py b/hw3/bloom.py deleted file mode 100644 index f8819e1..0000000 --- a/hw3/bloom.py +++ /dev/null @@ -1,49 +0,0 @@ -'''bloom.py defines a bloom filter which is an -approximate set membership data structure. You -will implement a full bloom filter in this module -''' -import array -import binascii -import random - -class Bloom(object): - - def __init__(self, m,k, seed=0): - '''Creates a bloom filter of size m with k - independent hash functions. - ''' - - self.array = array.array('B', [0] * m) - self.hashes = self.generate_hashes(m,k,seed) - - - #TODO - def generate_hashes(self, m, k, seed): - '''Generate *k* independent linear hash functions - each with the range 0,...,m. - - m: the range of the hash functions - k: the number of hash functions - seed: a random seed that controls which A/B linear - parameters are used. - - The output of this function should be a list of functions - ''' - random.seed(seed) - - #TODO - - raise ValueError('Not Implemented') - - - - def put(self, item): - '''Add a string to the bloom filter, returns void - ''' - #TODO - - def contains(self, item): - '''Test to see if the bloom filter could possibly - contain the string (true (possibly)), false (definitely). - ''' - #TODO \ No newline at end of file diff --git a/hw3/data.txt b/hw3/data.txt new file mode 100644 index 0000000..722754b --- /dev/null +++ b/hw3/data.txt @@ -0,0 +1,10000 @@ +107 +105 +106 +103 +105 +108 +109 +112 +110 +110 +109 +111 +109 +106 +110 +112 +115 +114 +116 +118 +117 +116 +113 +112 +115 +111 +114 +118 +122 +124 +127 +125 +123 +124 +126 +128 +130 +134 +131 +133 +129 +129 +129 +130 +127 +130 +130 +128 +131 +131 +129 +126 +125 +124 +121 +117 +118 +120 +117 +117 +118 +116 +118 +120 +124 +123 +122 +125 +124 +123 +123 +126 +126 +124 +120 +117 +117 +118 +116 +118 +115 +115 +111 +115 +114 +115 +115 +115 +114 +118 +115 +116 +116 +116 +117 +114 +111 +113 +117 +116 +119 +115 +115 +114 +111 +113 +115 +111 +110 +114 +113 +115 +119 +122 +122 +121 +125 +126 +130 +126 +128 +131 +131 +132 +134 +133 +135 +131 +130 +132 +134 +134 +138 +134 +131 +131 +133 +136 +134 +133 +129 +133 +131 +130 +126 +127 +125 +125 +127 +130 +128 +130 +133 +136 +139 +141 +142 +138 +142 +142 +143 +145 +149 +153 +152 +149 +145 +148 +144 +147 +147 +148 +147 +150 +152 +148 +152 +152 +152 +150 +152 +153 +155 +159 +158 +162 +164 +160 +162 +166 +167 +165 +165 +168 +172 +171 +170 +170 +173 +175 +175 +173 +172 +173 +173 +176 +177 +175 +172 +175 +174 +174 +171 +172 +168 +169 +165 +164 +163 +162 +163 +161 +161 +161 +158 +159 +163 +162 +158 +162 +160 +160 +163 +161 +159 +163 +163 +164 +165 +168 +165 +169 +166 +164 +160 +161 +165 +168 +166 +167 +167 +171 +167 +170 +173 +172 +175 +178 +180 +177 +173 +177 +180 +178 +182 +186 +182 +179 +180 +182 +180 +177 +177 +174 +175 +178 +179 +175 +173 +173 +170 +173 +171 +169 +166 +164 +166 +169 +165 +161 +162 +160 +162 +162 +159 +161 +165 +161 +163 +167 +163 +159 +160 +156 +154 +154 +156 +153 +151 +147 +144 +144 +140 +141 +144 +147 +143 +144 +146 +147 +146 +147 +150 +150 +151 +149 +150 +147 +147 +148 +148 +149 +148 +148 +144 +147 +144 +145 +144 +147 +143 +142 +142 +144 +140 +142 +142 +141 +143 +141 +143 +145 +144 +148 +150 +146 +144 +148 +146 +143 +140 +144 +148 +146 +143 +143 +139 +142 +145 +146 +145 +142 +142 +144 +141 +143 +145 +142 +140 +141 +138 +139 +136 +137 +136 +134 +138 +142 +140 +138 +138 +139 +137 +136 +133 +136 +137 +133 +137 +137 +133 +132 +131 +135 +131 +128 +128 +132 +136 +132 +134 +130 +128 +126 +122 +120 +117 +117 +120 +120 +123 +126 +130 +126 +129 +128 +125 +127 +124 +124 +125 +122 +123 +125 +124 +125 +129 +127 +131 +132 +128 +127 +130 +128 +125 +126 +130 +132 +128 +132 +133 +137 +133 +133 +131 +129 +130 +126 +122 +124 +120 +123 +121 +119 +119 +122 +125 +125 +128 +125 +123 +126 +126 +124 +124 +120 +124 +121 +120 +121 +120 +120 +121 +117 +114 +110 +114 +112 +108 +104 +102 +106 +104 +108 +104 +105 +105 +108 +111 +114 +111 +113 +114 +112 +113 +116 +119 +120 +120 +121 +117 +114 +113 +112 +115 +113 +115 +111 +113 +113 +109 +110 +110 +109 +108 +110 +106 +104 +107 +107 +107 +111 +109 +109 +110 +108 +110 +110 +110 +108 +106 +108 +105 +104 +106 +108 +111 +114 +114 +117 +117 +113 +111 +110 +111 +112 +114 +117 +117 +121 +117 +115 +116 +120 +116 +112 +110 +106 +108 +111 +107 +110 +111 +107 +104 +106 +107 +111 +111 +112 +116 +118 +120 +123 +121 +119 +116 +112 +112 +116 +119 +118 +116 +112 +111 +115 +113 +112 +110 +113 +112 +114 +115 +111 +109 +110 +106 +109 +110 +107 +109 +110 +113 +115 +119 +115 +116 +118 +119 +118 +116 +119 +115 +115 +113 +113 +111 +109 +112 +108 +106 +103 +102 +101 +104 +108 +105 +102 +101 +98 +98 +96 +92 +93 +89 +89 +91 +89 +88 +90 +93 +89 +85 +84 +84 +86 +89 +89 +89 +86 +87 +87 +83 +85 +86 +85 +83 +87 +83 +80 +80 +80 +84 +83 +87 +91 +95 +94 +95 +93 +97 +100 +103 +106 +110 +106 +106 +107 +105 +103 +102 +100 +101 +98 +96 +100 +103 +104 +101 +97 +93 +90 +90 +88 +91 +93 +93 +93 +93 +90 +88 +86 +84 +84 +88 +87 +83 +84 +88 +92 +90 +93 +96 +96 +97 +98 +95 +98 +96 +99 +95 +98 +98 +98 +97 +94 +93 +93 +94 +91 +89 +86 +82 +82 +81 +82 +78 +79 +79 +77 +81 +85 +84 +81 +84 +87 +83 +80 +78 +74 +75 +77 +73 +70 +73 +71 +75 +72 +68 +66 +70 +73 +77 +77 +74 +71 +74 +74 +70 +66 +68 +71 +74 +77 +76 +78 +79 +79 +75 +79 +75 +74 +75 +77 +81 +84 +86 +82 +80 +81 +80 +76 +74 +71 +67 +66 +70 +73 +71 +73 +71 +75 +74 +72 +76 +79 +79 +75 +78 +77 +80 +76 +76 +73 +75 +75 +77 +76 +74 +77 +76 +77 +75 +76 +80 +76 +74 +73 +71 +70 +71 +67 +66 +69 +68 +68 +67 +66 +62 +64 +66 +68 +68 +69 +70 +70 +66 +67 +63 +64 +68 +67 +70 +74 +70 +74 +72 +71 +70 +68 +64 +62 +62 +58 +56 +52 +52 +49 +50 +48 +45 +44 +47 +49 +45 +47 +45 +44 +44 +43 +47 +48 +46 +50 +46 +45 +49 +53 +54 +53 +50 +52 +49 +47 +51 +48 +51 +53 +53 +51 +54 +56 +56 +55 +51 +48 +45 +49 +52 +56 +60 +59 +61 +64 +61 +59 +61 +62 +61 +65 +67 +70 +69 +67 +71 +68 +67 +63 +61 +64 +67 +67 +67 +70 +74 +70 +71 +69 +65 +64 +60 +64 +63 +66 +64 +60 +60 +61 +62 +64 +62 +65 +68 +72 +73 +69 +70 +72 +71 +72 +75 +76 +73 +74 +71 +69 +68 +71 +68 +65 +65 +66 +70 +72 +74 +72 +75 +71 +67 +65 +68 +72 +72 +74 +71 +75 +74 +70 +71 +68 +71 +69 +69 +67 +71 +67 +66 +68 +68 +65 +61 +63 +62 +60 +64 +66 +68 +72 +70 +74 +75 +71 +70 +66 +68 +64 +67 +64 +60 +59 +62 +65 +66 +67 +69 +71 +71 +68 +65 +66 +69 +71 +68 +64 +66 +67 +70 +66 +69 +65 +66 +70 +71 +72 +73 +72 +69 +73 +77 +73 +77 +78 +78 +74 +78 +78 +77 +80 +79 +75 +73 +71 +70 +68 +72 +70 +68 +65 +61 +61 +65 +65 +66 +66 +70 +67 +71 +69 +68 +71 +67 +70 +72 +70 +66 +68 +65 +68 +65 +64 +62 +60 +60 +63 +61 +57 +56 +58 +57 +59 +62 +64 +63 +62 +60 +62 +61 +62 +58 +62 +64 +60 +58 +54 +56 +58 +55 +55 +51 +51 +51 +52 +51 +53 +57 +53 +53 +55 +53 +54 +55 +58 +54 +51 +54 +52 +50 +47 +44 +45 +43 +45 +48 +46 +44 +41 +44 +42 +46 +50 +48 +49 +48 +46 +47 +47 +43 +42 +45 +46 +43 +44 +45 +42 +39 +41 +44 +45 +46 +43 +45 +46 +49 +51 +54 +58 +56 +57 +59 +60 +62 +66 +68 +71 +68 +68 +71 +71 +69 +73 +73 +70 +69 +72 +70 +72 +71 +73 +71 +73 +77 +77 +76 +74 +75 +77 +75 +76 +75 +75 +71 +69 +66 +68 +70 +73 +69 +65 +62 +59 +61 +58 +59 +61 +64 +66 +67 +71 +71 +69 +72 +74 +78 +78 +82 +78 +74 +78 +77 +76 +80 +82 +85 +88 +88 +85 +86 +89 +90 +89 +91 +89 +93 +95 +94 +94 +90 +87 +84 +86 +84 +84 +86 +89 +91 +90 +92 +96 +93 +91 +94 +91 +90 +89 +89 +87 +86 +85 +89 +88 +86 +85 +85 +82 +82 +81 +83 +87 +84 +81 +79 +81 +83 +84 +81 +80 +82 +84 +85 +86 +88 +89 +87 +91 +89 +92 +90 +89 +90 +89 +93 +96 +94 +98 +95 +98 +97 +94 +91 +89 +92 +92 +95 +92 +88 +91 +89 +87 +84 +82 +83 +83 +85 +85 +81 +85 +88 +85 +81 +83 +84 +87 +86 +90 +94 +94 +96 +97 +95 +91 +91 +93 +97 +98 +100 +103 +103 +107 +105 +102 +99 +95 +98 +100 +100 +102 +98 +102 +98 +100 +98 +101 +105 +104 +108 +110 +113 +112 +116 +120 +118 +114 +114 +117 +118 +118 +115 +112 +115 +112 +112 +113 +115 +112 +115 +114 +118 +119 +115 +115 +111 +113 +113 +111 +113 +113 +114 +114 +118 +116 +112 +110 +109 +111 +108 +104 +100 +102 +101 +103 +100 +103 +106 +109 +107 +108 +104 +107 +111 +114 +115 +115 +115 +117 +117 +119 +122 +119 +118 +115 +116 +115 +114 +111 +115 +114 +112 +109 +110 +109 +109 +111 +113 +109 +105 +106 +103 +103 +104 +108 +109 +111 +114 +112 +116 +113 +113 +117 +115 +111 +114 +115 +113 +116 +114 +116 +118 +114 +115 +118 +122 +125 +127 +126 +125 +124 +124 +126 +126 +127 +123 +125 +125 +124 +120 +124 +120 +122 +122 +123 +125 +123 +120 +121 +117 +115 +112 +114 +115 +116 +118 +120 +121 +122 +126 +124 +120 +118 +121 +124 +122 +122 +123 +124 +128 +129 +125 +129 +129 +132 +129 +127 +127 +131 +132 +134 +137 +141 +138 +139 +136 +138 +136 +140 +142 +144 +145 +142 +143 +144 +148 +145 +144 +140 +140 +141 +145 +146 +142 +143 +147 +147 +143 +143 +141 +143 +145 +149 +152 +155 +159 +156 +155 +157 +156 +152 +148 +148 +147 +151 +147 +147 +147 +144 +143 +144 +147 +151 +153 +154 +151 +148 +147 +148 +149 +153 +149 +148 +148 +146 +143 +147 +150 +148 +152 +155 +157 +161 +164 +167 +169 +168 +164 +160 +157 +158 +160 +159 +162 +166 +162 +160 +164 +163 +163 +159 +163 +165 +163 +167 +169 +171 +167 +164 +163 +166 +169 +169 +173 +176 +179 +178 +176 +175 +178 +178 +174 +174 +176 +175 +179 +176 +176 +180 +179 +183 +181 +184 +182 +179 +176 +174 +174 +173 +176 +175 +178 +176 +177 +173 +172 +172 +168 +165 +169 +171 +169 +165 +165 +165 +164 +165 +169 +166 +163 +165 +165 +168 +167 +171 +169 +170 +170 +166 +163 +162 +158 +161 +163 +161 +159 +156 +158 +158 +154 +150 +150 +146 +148 +144 +141 +143 +143 +140 +136 +136 +135 +138 +139 +142 +142 +142 +139 +143 +147 +149 +152 +148 +149 +149 +151 +154 +156 +152 +151 +148 +148 +152 +149 +150 +153 +153 +157 +153 +156 +154 +154 +157 +158 +154 +155 +157 +155 +158 +161 +162 +165 +169 +172 +169 +169 +169 +165 +166 +168 +168 +167 +165 +166 +170 +168 +170 +166 +166 +164 +161 +161 +158 +161 +165 +161 +162 +162 +160 +162 +165 +163 +164 +162 +159 +158 +161 +159 +158 +157 +161 +162 +165 +166 +165 +162 +159 +157 +160 +158 +158 +161 +159 +159 +157 +153 +153 +157 +156 +152 +156 +155 +153 +153 +151 +154 +150 +146 +148 +152 +148 +149 +145 +141 +139 +142 +138 +141 +139 +136 +137 +135 +132 +132 +134 +132 +128 +131 +129 +129 +125 +128 +131 +134 +130 +133 +129 +133 +134 +133 +132 +128 +132 +134 +137 +135 +133 +129 +133 +136 +139 +143 +142 +143 +143 +142 +143 +143 +139 +140 +142 +143 +141 +142 +143 +147 +151 +148 +147 +150 +147 +151 +154 +152 +155 +154 +151 +154 +150 +146 +150 +152 +149 +147 +143 +144 +142 +143 +146 +143 +146 +142 +139 +137 +134 +135 +136 +137 +138 +140 +140 +144 +148 +150 +151 +154 +154 +155 +153 +153 +156 +158 +159 +155 +158 +154 +150 +147 +143 +141 +142 +138 +138 +139 +135 +132 +134 +138 +137 +138 +139 +140 +140 +143 +139 +141 +144 +143 +147 +145 +146 +147 +147 +148 +147 +149 +147 +143 +143 +143 +141 +144 +146 +147 +149 +146 +146 +150 +152 +154 +158 +162 +164 +168 +165 +168 +165 +163 +167 +168 +169 +172 +170 +172 +175 +178 +178 +176 +173 +169 +170 +167 +171 +173 +170 +173 +176 +178 +176 +177 +175 +179 +179 +175 +178 +180 +177 +176 +173 +172 +174 +177 +173 +173 +169 +173 +176 +176 +179 +177 +179 +179 +181 +182 +179 +180 +183 +184 +180 +176 +176 +180 +181 +177 +174 +170 +171 +173 +172 +172 +170 +174 +172 +169 +165 +165 +164 +161 +157 +161 +158 +158 +161 +163 +167 +171 +172 +171 +175 +175 +178 +181 +181 +183 +183 +181 +181 +179 +179 +182 +182 +181 +184 +180 +181 +179 +182 +179 +178 +176 +180 +182 +179 +178 +176 +177 +174 +177 +174 +171 +170 +168 +167 +165 +169 +173 +173 +172 +171 +169 +165 +166 +162 +162 +158 +159 +159 +163 +167 +164 +160 +159 +157 +158 +155 +158 +155 +157 +161 +158 +155 +158 +162 +163 +164 +168 +171 +168 +166 +165 +168 +167 +167 +163 +166 +170 +168 +171 +169 +167 +168 +171 +170 +171 +168 +172 +168 +172 +172 +172 +170 +170 +169 +170 +167 +170 +172 +168 +169 +167 +164 +162 +163 +161 +160 +160 +158 +158 +158 +154 +156 +156 +158 +156 +158 +158 +157 +156 +153 +150 +150 +149 +147 +149 +150 +152 +151 +150 +147 +151 +150 +151 +147 +149 +145 +141 +137 +139 +137 +141 +138 +138 +138 +141 +140 +144 +148 +152 +151 +152 +148 +148 +152 +149 +146 +149 +153 +154 +153 +153 +150 +151 +151 +152 +154 +157 +158 +154 +153 +152 +152 +156 +158 +161 +160 +156 +153 +153 +155 +154 +155 +154 +157 +161 +160 +159 +160 +158 +157 +153 +150 +150 +149 +147 +150 +151 +147 +144 +144 +148 +147 +146 +148 +151 +150 +151 +152 +153 +149 +153 +155 +151 +150 +152 +156 +158 +159 +157 +158 +161 +164 +165 +167 +167 +169 +169 +166 +168 +171 +169 +172 +173 +177 +181 +177 +178 +180 +178 +182 +178 +175 +174 +173 +171 +174 +172 +168 +166 +168 +168 +171 +169 +168 +172 +172 +170 +168 +164 +163 +161 +159 +163 +166 +163 +167 +170 +173 +176 +176 +174 +177 +175 +178 +179 +182 +186 +187 +188 +186 +182 +180 +179 +182 +184 +188 +191 +195 +195 +193 +197 +200 +198 +197 +200 +200 +202 +204 +202 +202 +200 +199 +201 +198 +202 +200 +204 +208 +212 +209 +205 +202 +204 +201 +205 +204 +201 +205 +208 +211 +210 +206 +210 +206 +208 +212 +216 +215 +219 +218 +219 +219 +222 +226 +223 +219 +215 +213 +211 +211 +211 +210 +214 +210 +207 +209 +206 +208 +210 +214 +215 +218 +220 +219 +221 +222 +218 +222 +224 +228 +229 +230 +226 +222 +226 +223 +221 +225 +222 +221 +221 +222 +223 +227 +230 +232 +234 +238 +241 +244 +247 +247 +243 +243 +241 +240 +238 +241 +245 +248 +249 +246 +249 +252 +250 +246 +247 +245 +245 +246 +248 +249 +250 +254 +250 +252 +256 +252 +251 +253 +253 +255 +258 +261 +261 +265 +267 +269 +266 +267 +270 +271 +269 +268 +266 +269 +270 +268 +272 +274 +270 +272 +272 +269 +271 +267 +267 +266 +264 +260 +256 +253 +251 +252 +248 +251 +251 +255 +255 +256 +254 +255 +255 +255 +253 +255 +259 +255 +257 +254 +250 +253 +252 +256 +255 +251 +255 +257 +259 +255 +259 +262 +264 +268 +268 +269 +267 +267 +271 +267 +269 +267 +264 +261 +263 +260 +264 +263 +260 +258 +261 +259 +257 +253 +253 +256 +257 +259 +256 +252 +249 +248 +252 +253 +251 +253 +253 +255 +252 +256 +258 +255 +256 +260 +262 +258 +254 +258 +260 +259 +262 +258 +260 +263 +262 +261 +258 +255 +252 +251 +249 +251 +253 +256 +253 +257 +254 +256 +255 +253 +249 +250 +254 +250 +246 +243 +247 +248 +247 +249 +253 +249 +247 +244 +242 +244 +244 +240 +242 +238 +238 +234 +234 +237 +233 +236 +239 +242 +243 +241 +242 +243 +241 +243 +240 +240 +238 +237 +240 +242 +239 +241 +237 +238 +238 +241 +238 +238 +238 +242 +238 +242 +240 +236 +236 +233 +230 +231 +230 +229 +232 +228 +224 +225 +222 +225 +229 +233 +231 +234 +237 +235 +236 +239 +236 +238 +238 +238 +235 +238 +237 +235 +233 +229 +230 +229 +231 +229 +228 +225 +223 +227 +227 +230 +229 +231 +233 +231 +227 +228 +231 +227 +227 +228 +230 +232 +232 +228 +230 +229 +233 +236 +240 +236 +234 +233 +237 +233 +234 +233 +237 +236 +240 +240 +242 +243 +247 +251 +253 +257 +253 +250 +253 +254 +250 +253 +252 +253 +256 +260 +256 +256 +259 +259 +255 +255 +256 +255 +258 +254 +256 +260 +258 +258 +257 +261 +261 +263 +265 +264 +267 +268 +264 +265 +261 +259 +262 +266 +269 +266 +264 +265 +266 +262 +261 +264 +265 +262 +259 +263 +265 +266 +262 +261 +265 +261 +265 +263 +262 +265 +261 +261 +261 +258 +256 +259 +263 +259 +258 +254 +250 +252 +250 +254 +253 +249 +249 +246 +243 +242 +245 +241 +244 +245 +247 +250 +251 +247 +248 +244 +244 +240 +236 +238 +237 +239 +235 +233 +236 +237 +233 +230 +234 +238 +236 +240 +240 +240 +238 +242 +238 +236 +236 +240 +238 +240 +236 +232 +231 +231 +233 +235 +235 +237 +233 +235 +231 +234 +231 +228 +232 +233 +232 +232 +229 +233 +232 +233 +229 +230 +234 +230 +231 +230 +231 +233 +234 +233 +229 +231 +235 +236 +237 +237 +236 +233 +235 +232 +228 +227 +230 +227 +224 +227 +225 +223 +223 +222 +221 +222 +218 +217 +216 +214 +211 +214 +210 +209 +213 +216 +219 +215 +219 +220 +217 +215 +217 +217 +218 +214 +215 +214 +217 +213 +215 +216 +214 +211 +210 +210 +213 +213 +217 +213 +215 +215 +219 +217 +213 +214 +216 +218 +214 +217 +220 +219 +223 +219 +220 +218 +222 +218 +222 +225 +222 +221 +220 +221 +222 +225 +221 +221 +217 +220 +217 +214 +215 +217 +217 +220 +216 +213 +216 +215 +219 +220 +217 +213 +215 +216 +215 +218 +222 +218 +221 +221 +223 +219 +219 +216 +215 +213 +214 +216 +212 +213 +213 +209 +209 +210 +211 +211 +211 +208 +206 +205 +206 +208 +206 +206 +206 +207 +207 +204 +207 +203 +207 +208 +204 +201 +203 +207 +208 +208 +212 +213 +210 +208 +212 +214 +212 +209 +210 +206 +202 +204 +208 +210 +207 +211 +215 +217 +214 +210 +209 +205 +202 +205 +203 +199 +195 +192 +192 +195 +191 +192 +192 +195 +197 +194 +193 +197 +193 +190 +191 +192 +195 +199 +197 +196 +194 +193 +194 +197 +200 +197 +196 +195 +196 +192 +194 +197 +194 +197 +194 +192 +196 +197 +196 +200 +197 +195 +194 +194 +195 +191 +194 +195 +191 +190 +194 +195 +195 +197 +201 +203 +205 +203 +203 +205 +206 +206 +210 +207 +211 +207 +210 +214 +210 +214 +216 +215 +215 +214 +216 +214 +217 +218 +220 +222 +224 +222 +219 +223 +225 +228 +224 +226 +227 +224 +225 +225 +226 +228 +232 +230 +230 +233 +235 +236 +234 +231 +228 +226 +223 +223 +220 +217 +219 +221 +217 +216 +218 +216 +215 +212 +212 +209 +212 +213 +210 +213 +216 +220 +219 +218 +217 +214 +213 +215 +216 +220 +223 +219 +216 +219 +219 +222 +225 +226 +223 +227 +231 +233 +235 +234 +238 +236 +234 +238 +240 +242 +246 +245 +242 +243 +246 +248 +245 +243 +241 +243 +239 +240 +239 +242 +242 +239 +235 +233 +236 +239 +240 +240 +244 +247 +245 +247 +243 +241 +237 +235 +236 +233 +233 +237 +241 +238 +237 +236 +235 +231 +230 +229 +226 +229 +227 +228 +232 +232 +231 +230 +232 +229 +233 +231 +234 +230 +229 +230 +226 +228 +228 +229 +228 +224 +223 +223 +219 +218 +219 +221 +221 +222 +226 +228 +225 +229 +228 +228 +230 +228 +231 +229 +226 +226 +230 +231 +229 +229 +226 +226 +226 +222 +220 +219 +223 +223 +220 +219 +222 +219 +215 +215 +214 +214 +210 +214 +212 +214 +216 +217 +216 +220 +223 +223 +227 +230 +228 +227 +227 +225 +221 +218 +221 +222 +224 +222 +223 +224 +221 +223 +225 +221 +217 +213 +211 +214 +213 +217 +218 +219 +220 +216 +218 +214 +215 +214 +217 +213 +212 +215 +213 +216 +218 +219 +219 +218 +218 +214 +217 +218 +221 +224 +228 +225 +228 +228 +228 +226 +230 +227 +226 +224 +220 +216 +212 +211 +210 +208 +207 +205 +201 +200 +199 +203 +199 +199 +198 +195 +197 +201 +199 +200 +203 +205 +208 +208 +206 +205 +205 +209 +205 +209 +209 +209 +208 +205 +208 +211 +215 +216 +217 +218 +214 +212 +208 +211 +212 +211 +214 +211 +210 +210 +210 +214 +217 +214 +210 +210 +209 +210 +210 +209 +213 +210 +206 +210 +213 +210 +212 +210 +207 +211 +213 +212 +212 +216 +216 +217 +220 +216 +217 +215 +211 +211 +211 +208 +204 +207 +205 +203 +200 +201 +200 +201 +205 +208 +208 +204 +206 +206 +204 +200 +204 +208 +211 +211 +211 +207 +203 +201 +203 +201 +201 +203 +207 +203 +206 +204 +206 +210 +210 +211 +214 +218 +220 +222 +222 +223 +227 +231 +232 +234 +231 +233 +234 +237 +237 +237 +234 +238 +236 +240 +236 +240 +238 +240 +237 +235 +236 +237 +239 +243 +239 +242 +246 +242 +243 +247 +243 +242 +238 +239 +242 +244 +246 +250 +247 +249 +250 +254 +252 +252 +251 +250 +246 +246 +249 +250 +247 +250 +251 +251 +247 +247 +249 +252 +253 +255 +258 +262 +261 +261 +263 +267 +270 +273 +272 +274 +276 +272 +272 +270 +272 +271 +272 +268 +264 +267 +271 +267 +270 +273 +272 +273 +274 +270 +273 +270 +272 +273 +274 +278 +279 +277 +276 +276 +277 +281 +282 +283 +282 +281 +285 +282 +284 +281 +281 +277 +276 +279 +283 +280 +279 +283 +284 +288 +285 +286 +288 +290 +291 +291 +289 +293 +290 +292 +288 +285 +288 +292 +292 +288 +287 +288 +290 +290 +293 +297 +297 +301 +301 +305 +306 +305 +304 +301 +298 +295 +294 +292 +288 +288 +285 +289 +292 +290 +294 +295 +295 +295 +294 +297 +298 +294 +290 +290 +294 +292 +291 +295 +294 +297 +295 +291 +288 +284 +283 +286 +288 +284 +287 +286 +286 +287 +284 +287 +285 +282 +283 +280 +280 +279 +278 +277 +277 +274 +273 +273 +270 +272 +272 +275 +273 +276 +278 +277 +276 +280 +281 +278 +281 +285 +282 +283 +284 +282 +281 +285 +285 +287 +291 +292 +295 +298 +295 +291 +292 +290 +287 +289 +293 +297 +297 +299 +296 +292 +289 +286 +289 +288 +285 +284 +287 +283 +279 +283 +280 +276 +278 +279 +275 +279 +280 +283 +280 +283 +285 +287 +283 +286 +289 +287 +291 +289 +293 +291 +288 +289 +285 +287 +283 +281 +283 +287 +283 +281 +280 +279 +277 +276 +280 +278 +282 +286 +286 +290 +292 +295 +295 +292 +289 +288 +284 +287 +285 +285 +285 +289 +293 +297 +299 +298 +295 +291 +295 +297 +299 +298 +300 +303 +303 +300 +298 +296 +296 +297 +298 +300 +296 +300 +299 +295 +299 +299 +296 +298 +302 +303 +302 +302 +300 +303 +302 +306 +310 +306 +303 +307 +305 +308 +306 +303 +300 +300 +304 +303 +301 +300 +302 +304 +300 +297 +294 +293 +290 +288 +287 +290 +291 +294 +294 +292 +288 +288 +289 +286 +282 +281 +281 +282 +283 +284 +283 +286 +287 +287 +290 +293 +291 +293 +289 +285 +287 +283 +287 +289 +293 +295 +292 +290 +293 +291 +295 +292 +293 +290 +289 +292 +296 +292 +296 +292 +292 +291 +292 +292 +290 +288 +289 +291 +290 +293 +296 +298 +295 +293 +289 +293 +289 +287 +288 +292 +289 +292 +289 +286 +286 +290 +291 +295 +298 +296 +297 +296 +294 +293 +292 +295 +293 +292 +295 +299 +295 +296 +292 +292 +295 +294 +296 +299 +296 +299 +302 +303 +299 +297 +300 +300 +300 +297 +293 +291 +295 +299 +296 +298 +301 +298 +295 +299 +297 +295 +294 +293 +294 +297 +294 +295 +293 +296 +297 +293 +295 +298 +297 +293 +294 +290 +290 +294 +295 +298 +302 +301 +302 +301 +299 +299 +298 +295 +296 +292 +292 +291 +292 +295 +293 +292 +292 +293 +290 +294 +296 +296 +299 +301 +298 +296 +297 +296 +292 +290 +293 +294 +293 +296 +294 +291 +287 +286 +285 +281 +280 +278 +278 +275 +275 +271 +271 +267 +267 +263 +262 +263 +259 +260 +262 +260 +261 +262 +266 +262 +261 +258 +260 +262 +259 +263 +262 +260 +257 +260 +256 +256 +259 +260 +261 +259 +261 +265 +269 +269 +273 +271 +267 +267 +267 +268 +268 +270 +269 +273 +271 +273 +272 +271 +271 +271 +273 +269 +270 +268 +265 +262 +260 +260 +263 +267 +266 +264 +262 +258 +259 +259 +262 +258 +260 +257 +260 +262 +259 +262 +264 +266 +263 +264 +263 +260 +260 +263 +265 +268 +270 +272 +273 +273 +270 +270 +274 +275 +271 +275 +272 +270 +269 +268 +271 +274 +278 +274 +277 +274 +278 +281 +281 +281 +280 +277 +277 +281 +281 +284 +283 +281 +285 +288 +284 +286 +286 +290 +289 +287 +291 +289 +293 +289 +293 +293 +289 +290 +292 +293 +294 +298 +297 +297 +294 +292 +288 +288 +292 +290 +290 +286 +282 +279 +278 +274 +271 +268 +269 +266 +267 +268 +272 +270 +266 +270 +272 +275 +278 +276 +274 +271 +273 +270 +266 +266 +264 +263 +261 +257 +258 +262 +263 +260 +264 +261 +265 +269 +268 +268 +264 +264 +266 +263 +267 +265 +266 +268 +272 +276 +275 +276 +272 +270 +268 +269 +268 +272 +276 +277 +279 +276 +273 +274 +274 +270 +274 +278 +282 +284 +285 +283 +280 +281 +280 +284 +287 +284 +285 +287 +288 +284 +282 +281 +285 +286 +290 +291 +288 +289 +285 +282 +280 +276 +279 +279 +278 +282 +286 +283 +281 +280 +278 +278 +281 +282 +283 +286 +288 +286 +284 +282 +285 +282 +278 +281 +285 +284 +288 +292 +290 +287 +287 +284 +286 +282 +285 +282 +281 +281 +281 +277 +279 +278 +277 +275 +274 +275 +276 +272 +271 +274 +277 +273 +277 +274 +278 +274 +274 +273 +269 +267 +266 +268 +269 +270 +267 +264 +266 +270 +268 +266 +264 +266 +266 +263 +262 +261 +260 +261 +262 +266 +264 +262 +263 +259 +259 +257 +255 +258 +259 +262 +266 +268 +268 +271 +267 +270 +269 +273 +272 +268 +264 +261 +262 +258 +259 +255 +255 +255 +259 +260 +259 +257 +253 +250 +249 +250 +248 +246 +247 +243 +246 +247 +244 +248 +244 +243 +242 +243 +246 +242 +244 +243 +246 +242 +239 +242 +243 +241 +238 +235 +232 +230 +234 +230 +226 +229 +229 +225 +223 +220 +217 +214 +210 +206 +205 +204 +206 +207 +204 +205 +208 +210 +207 +209 +210 +211 +211 +209 +209 +210 +206 +205 +205 +201 +203 +202 +206 +209 +210 +210 +213 +215 +218 +222 +221 +225 +226 +229 +226 +225 +225 +221 +219 +219 +219 +222 +224 +225 +224 +223 +225 +229 +225 +225 +226 +223 +226 +228 +226 +222 +218 +219 +215 +214 +213 +213 +209 +208 +209 +210 +209 +213 +215 +213 +210 +214 +216 +219 +217 +220 +217 +215 +211 +211 +212 +210 +213 +216 +215 +216 +212 +208 +210 +207 +211 +209 +210 +210 +213 +216 +212 +211 +215 +214 +218 +220 +219 +216 +219 +215 +218 +221 +221 +225 +229 +228 +226 +223 +222 +224 +223 +226 +225 +228 +228 +231 +227 +226 +224 +223 +224 +222 +220 +217 +218 +222 +224 +228 +225 +222 +225 +228 +224 +221 +224 +221 +222 +221 +220 +220 +221 +222 +221 +220 +217 +218 +222 +219 +219 +215 +211 +208 +208 +210 +209 +213 +212 +212 +215 +217 +218 +220 +222 +224 +223 +222 +221 +219 +218 +221 +218 +218 +219 +217 +220 +219 +223 +221 +225 +222 +224 +224 +225 +222 +218 +220 +217 +218 +220 +221 +217 +215 +217 +216 +217 +213 +213 +216 +214 +215 +219 +217 +216 +218 +220 +223 +226 +225 +221 +222 +219 +217 +217 +213 +215 +213 +209 +205 +205 +208 +207 +204 +204 +205 +203 +203 +201 +204 +207 +209 +213 +215 +211 +212 +213 +209 +205 +205 +204 +200 +201 +199 +197 +200 +202 +199 +195 +198 +202 +200 +196 +198 +199 +198 +197 +200 +199 +200 +201 +201 +198 +196 +196 +193 +194 +194 +195 +191 +187 +189 +190 +194 +194 +198 +200 +198 +200 +197 +197 +197 +193 +195 +199 +200 +197 +200 +203 +199 +203 +206 +209 +210 +212 +209 +205 +204 +208 +210 +206 +206 +208 +206 +204 +205 +209 +211 +215 +213 +212 +210 +213 +209 +206 +204 +203 +200 +200 +200 +197 +195 +198 +195 +191 +193 +195 +191 +188 +189 +192 +189 +188 +192 +196 +196 +192 +193 +194 +194 +198 +194 +192 +191 +191 +194 +190 +194 +198 +198 +198 +194 +191 +190 +192 +195 +193 +190 +188 +187 +184 +188 +191 +190 +192 +195 +191 +194 +198 +198 +199 +196 +199 +197 +199 +201 +204 +202 +204 +204 +200 +200 +201 +201 +202 +200 +199 +195 +195 +198 +195 +199 +203 +203 +200 +198 +199 +201 +202 +201 +204 +202 +202 +201 +201 +201 +199 +201 +200 +200 +198 +202 +204 +201 +200 +197 +194 +196 +195 +194 +194 +192 +196 +200 +204 +204 +201 +205 +205 +202 +200 +196 +199 +197 +194 +191 +194 +193 +190 +190 +190 +190 +192 +195 +194 +195 +199 +202 +198 +202 +203 +199 +203 +207 +211 +209 +209 +211 +212 +209 +207 +207 +211 +209 +205 +205 +201 +205 +208 +208 +209 +208 +207 +210 +214 +217 +218 +216 +217 +219 +219 +219 +220 +222 +220 +223 +221 +217 +215 +219 +220 +223 +223 +222 +218 +221 +219 +217 +217 +221 +221 +217 +219 +223 +221 +222 +224 +227 +224 +224 +224 +225 +229 +225 +223 +227 +223 +226 +224 +227 +223 +222 +224 +226 +229 +225 +226 +225 +221 +217 +221 +225 +226 +227 +229 +229 +225 +225 +224 +224 +220 +220 +222 +226 +229 +226 +223 +220 +223 +221 +225 +225 +225 +226 +227 +225 +228 +232 +233 +234 +236 +236 +239 +239 +239 +243 +239 +239 +243 +247 +251 +251 +250 +251 +254 +256 +253 +250 +248 +245 +246 +243 +240 +239 +242 +239 +237 +238 +237 +239 +238 +241 +239 +238 +240 +240 +237 +236 +236 +235 +239 +235 +237 +240 +243 +246 +246 +243 +242 +243 +243 +244 +247 +246 +248 +247 +246 +245 +243 +241 +240 +239 +241 +242 +243 +247 +250 +254 +258 +256 +258 +254 +252 +254 +252 +253 +256 +258 +256 +254 +255 +257 +259 +263 +267 +271 +272 +275 +274 +277 +281 +283 +282 +283 +285 +281 +280 +277 +276 +280 +284 +287 +290 +287 +285 +281 +277 +275 +277 +279 +282 +279 +282 +285 +281 +284 +287 +290 +292 +295 +297 +295 +297 +295 +291 +295 +296 +292 +292 +293 +295 +296 +300 +302 +306 +304 +308 +304 +308 +306 +302 +303 +305 +308 +310 +313 +313 +312 +310 +307 +306 +305 +304 +305 +308 +306 +306 +307 +311 +315 +315 +312 +308 +309 +310 +307 +310 +311 +309 +307 +311 +312 +311 +315 +317 +320 +317 +320 +318 +322 +321 +318 +318 +315 +315 +312 +310 +306 +306 +308 +308 +309 +312 +314 +311 +307 +311 +310 +311 +315 +319 +321 +320 +324 +326 +325 +326 +329 +331 +331 +327 +327 +324 +323 +326 +326 +327 +326 +326 +325 +328 +331 +328 +326 +330 +326 +324 +322 +318 +317 +320 +320 +320 +320 +323 +319 +319 +318 +315 +311 +315 +311 +315 +311 +314 +317 +317 +313 +311 +315 +311 +311 +313 +314 +311 +311 +308 +308 +306 +305 +306 +309 +313 +311 +307 +305 +309 +305 +302 +301 +302 +298 +296 +296 +300 +302 +300 +298 +297 +298 +294 +298 +298 +302 +299 +303 +299 +297 +299 +302 +298 +297 +301 +301 +297 +300 +303 +300 +296 +296 +293 +297 +295 +297 +300 +300 +303 +304 +308 +305 +304 +301 +302 +298 +301 +300 +304 +300 +302 +298 +300 +300 +303 +303 +306 +309 +310 +310 +306 +310 +313 +310 +307 +311 +315 +316 +317 +317 +320 +324 +325 +323 +326 +325 +322 +319 +320 +317 +320 +324 +320 +316 +316 +312 +308 +306 +305 +309 +310 +306 +307 +310 +311 +315 +315 +315 +315 +311 +310 +314 +310 +309 +311 +314 +311 +315 +319 +316 +319 +323 +326 +326 +322 +318 +321 +319 +320 +316 +318 +320 +316 +312 +311 +307 +303 +299 +299 +302 +298 +302 +306 +309 +309 +312 +314 +317 +319 +318 +315 +311 +307 +306 +306 +308 +312 +311 +308 +310 +314 +310 +308 +311 +315 +317 +319 +315 +313 +313 +317 +314 +318 +319 +316 +316 +313 +314 +311 +314 +311 +312 +311 +307 +310 +306 +309 +308 +308 +309 +309 +312 +315 +319 +321 +323 +319 +321 +325 +326 +324 +320 +317 +316 +313 +315 +312 +311 +313 +317 +317 +315 +311 +307 +311 +314 +310 +308 +307 +308 +310 +309 +309 +310 +314 +312 +309 +308 +312 +310 +313 +309 +305 +309 +310 +306 +303 +307 +308 +308 +308 +310 +309 +308 +312 +312 +312 +310 +312 +315 +314 +316 +320 +320 +322 +323 +321 +321 +317 +314 +318 +314 +314 +316 +316 +316 +317 +318 +319 +318 +318 +321 +317 +318 +318 +317 +319 +316 +313 +309 +307 +305 +309 +307 +309 +310 +310 +306 +309 +312 +312 +312 +308 +306 +302 +304 +308 +305 +307 +303 +305 +305 +304 +301 +302 +305 +303 +306 +302 +300 +302 +303 +300 +303 +299 +296 +295 +295 +294 +296 +298 +302 +303 +302 +298 +299 +300 +303 +305 +303 +306 +308 +306 +304 +303 +303 +304 +302 +301 +304 +305 +309 +305 +303 +299 +295 +292 +292 +288 +286 +283 +279 +280 +276 +280 +278 +281 +278 +275 +279 +279 +278 +276 +277 +274 +278 +281 +285 +286 +290 +294 +296 +297 +294 +294 +295 +297 +301 +303 +302 +304 +302 +299 +297 +298 +294 +291 +290 +289 +285 +286 +283 +280 +281 +280 +281 +277 +277 +281 +278 +274 +278 +277 +278 +280 +284 +282 +282 +284 +287 +283 +284 +288 +292 +289 +291 +287 +283 +285 +289 +288 +285 +288 +289 +293 +296 +293 +294 +291 +287 +283 +280 +282 +284 +285 +287 +291 +289 +291 +287 +288 +287 +285 +281 +284 +283 +279 +282 +282 +285 +289 +287 +291 +290 +292 +294 +297 +294 +290 +293 +294 +295 +293 +295 +299 +295 +292 +288 +284 +286 +287 +287 +289 +293 +289 +285 +281 +283 +279 +275 +275 +277 +280 +278 +282 +286 +288 +288 +286 +283 +283 +284 +288 +285 +283 +282 +278 +282 +281 +281 +281 +278 +280 +276 +274 +277 +280 +282 +284 +282 +281 +278 +281 +285 +287 +286 +283 +284 +283 +279 +280 +279 +280 +277 +274 +271 +269 +267 +267 +266 +262 +265 +262 +259 +263 +263 +261 +259 +258 +254 +258 +258 +257 +259 +261 +259 +260 +257 +253 +249 +251 +250 +248 +247 +249 +247 +247 +244 +245 +244 +244 +242 +246 +243 +239 +243 +245 +246 +245 +248 +245 +248 +252 +256 +255 +253 +255 +259 +258 +257 +254 +257 +254 +255 +256 +257 +255 +256 +256 +254 +257 +256 +257 +259 +259 +258 +262 +260 +257 +260 +260 +261 +258 +262 +264 +267 +265 +261 +257 +256 +255 +256 +256 +255 +256 +253 +250 +252 +251 +254 +255 +259 +261 +261 +259 +258 +257 +260 +256 +260 +256 +255 +252 +248 +250 +248 +249 +249 +247 +247 +246 +246 +242 +239 +236 +240 +237 +237 +234 +234 +235 +239 +240 +241 +243 +242 +245 +241 +239 +239 +241 +241 +240 +239 +243 +247 +248 +251 +255 +254 +250 +249 +246 +248 +244 +242 +245 +247 +244 +244 +246 +246 +247 +247 +244 +244 +240 +239 +238 +239 +235 +233 +237 +238 +241 +240 +242 +240 +240 +236 +232 +233 +230 +232 +231 +231 +232 +233 +237 +238 +237 +238 +238 +242 +238 +239 +237 +234 +235 +237 +237 +234 +231 +227 +231 +229 +233 +237 +240 +242 +246 +242 +239 +241 +243 +246 +249 +251 +253 +251 +252 +249 +251 +255 +256 +252 +251 +255 +258 +254 +251 +247 +249 +251 +253 +252 +252 +250 +253 +253 +253 +254 +252 +248 +250 +250 +248 +250 +251 +251 +247 +243 +239 +239 +240 +237 +241 +239 +242 +240 +236 +234 +237 +237 +234 +235 +234 +232 +231 +235 +235 +233 +231 +228 +230 +226 +225 +224 +226 +226 +225 +228 +228 +225 +222 +219 +222 +226 +226 +230 +227 +225 +229 +229 +226 +226 +228 +226 +222 +223 +221 +224 +226 +223 +221 +217 +216 +213 +217 +216 +214 +216 +215 +217 +217 +213 +210 +208 +205 +202 +203 +205 +205 +207 +209 +209 +208 +212 +209 +207 +209 +205 +204 +202 +200 +203 +201 +205 +209 +213 +215 +217 +215 +218 +222 +224 +223 +219 +219 +217 +217 +219 +220 +218 +222 +224 +228 +230 +234 +232 +236 +238 +241 +245 +242 +243 +241 +239 +243 +240 +237 +235 +237 +235 +232 +228 +230 +229 +228 +227 +231 +231 +231 +231 +227 +231 +228 +230 +228 +224 +226 +222 +225 +226 +229 +227 +229 +231 +235 +235 +231 +229 +230 +232 +234 +231 +234 +232 +228 +229 +228 +231 +235 +238 +236 +237 +233 +237 +239 +235 +238 +236 +239 +236 +240 +236 +238 +235 +235 +234 +230 +230 +226 +222 +219 +215 +214 +218 +219 +221 +224 +223 +224 +225 +229 +226 +225 +228 +227 +229 +226 +229 +226 +230 +229 +227 +223 +225 +228 +225 +227 +229 +226 +224 +224 +226 +228 +228 +230 +231 +227 +229 +229 +233 +233 +229 +227 +223 +220 +220 +220 +222 +220 +224 +220 +217 +220 +224 +221 +217 +218 +218 +217 +220 +222 +219 +216 +215 +213 +214 +210 +207 +209 +207 +205 +207 +204 +205 +207 +206 +206 +206 +204 +202 +204 +205 +208 +210 +214 +218 +216 +220 +220 +217 +215 +216 +219 +220 +221 +220 +219 +222 +226 +226 +230 +234 +231 +232 +234 +237 +238 +239 +237 +241 +240 +239 +235 +232 +230 +226 +228 +228 +229 +225 +226 +225 +222 +221 +225 +229 +225 +222 +219 +218 +214 +210 +210 +208 +207 +204 +203 +207 +206 +206 +209 +206 +204 +203 +204 +206 +210 +206 +205 +209 +205 +203 +207 +205 +201 +199 +197 +193 +195 +192 +193 +192 +188 +187 +187 +188 +188 +192 +195 +195 +199 +199 +195 +199 +200 +203 +201 +202 +201 +204 +201 +198 +199 +197 +194 +197 +195 +196 +192 +191 +187 +190 +193 +192 +192 +192 +193 +196 +197 +197 +200 +199 +202 +203 +205 +205 +204 +208 +206 +210 +209 +207 +210 +211 +212 +209 +212 +213 +209 +212 +214 +213 +216 +218 +222 +222 +223 +223 +225 +221 +221 +221 +224 +227 +227 +231 +233 +229 +229 +233 +237 +238 +234 +234 +230 +227 +225 +229 +225 +224 +226 +223 +220 +220 +222 +222 +220 +216 +214 +218 +219 +221 +224 +221 +221 +225 +227 +227 +230 +232 +231 +229 +231 +228 +228 +230 +231 +231 +234 +234 +234 +233 +229 +230 +229 +226 +223 +222 +219 +216 +219 +220 +216 +218 +222 +220 +220 +223 +225 +222 +225 +223 +220 +218 +220 +218 +221 +222 +219 +215 +213 +214 +216 +218 +220 +221 +223 +227 +229 +228 +227 +226 +222 +226 +222 +225 +228 +229 +225 +228 +232 +233 +232 +236 +234 +235 +239 +239 +235 +237 +240 +240 +236 +238 +241 +243 +245 +247 +245 +248 +249 +252 +249 +250 +248 +252 +249 +248 +245 +248 +251 +247 +250 +246 +243 +241 +244 +244 +246 +250 +254 +254 +256 +253 +251 +250 +254 +250 +254 +251 +250 +253 +254 +256 +254 +256 +260 +262 +261 +262 +260 +259 +260 +256 +259 +256 +252 +250 +253 +254 +257 +258 +258 +254 +255 +256 +259 +255 +259 +260 +256 +257 +253 +253 +255 +258 +256 +256 +254 +256 +259 +260 +263 +264 +260 +259 +263 +260 +264 +266 +267 +270 +272 +271 +269 +272 +268 +270 +273 +272 +275 +279 +278 +276 +276 +272 +274 +276 +273 +272 +272 +270 +273 +271 +267 +266 +263 +266 +264 +261 +264 +263 +261 +264 +262 +260 +259 +257 +256 +255 +256 +256 +258 +260 +261 +259 +261 +258 +257 +258 +258 +257 +254 +254 +255 +251 +249 +248 +249 +251 +247 +248 +249 +251 +250 +251 +247 +250 +254 +252 +252 +252 +251 +247 +244 +246 +244 +242 +244 +240 +238 +239 +238 +235 +235 +235 +236 +234 +238 +234 +231 +227 +226 +226 +222 +220 +224 +223 +221 +225 +226 +229 +233 +231 +228 +225 +223 +225 +222 +221 +219 +215 +214 +212 +212 +208 +205 +207 +209 +208 +204 +204 +200 +204 +204 +205 +206 +208 +206 +207 +205 +203 +205 +202 +203 +202 +198 +196 +199 +201 +205 +201 +197 +193 +192 +196 +196 +198 +197 +196 +200 +198 +200 +199 +202 +199 +200 +202 +200 +200 +200 +201 +198 +202 +198 +197 +193 +197 +201 +201 +200 +198 +194 +192 +194 +196 +199 +202 +206 +203 +201 +199 +200 +203 +201 +197 +201 +203 +207 +205 +208 +212 +216 +218 +216 +212 +209 +208 +212 +209 +207 +205 +208 +209 +205 +209 +206 +204 +205 +209 +208 +210 +207 +209 +206 +206 +209 +205 +203 +201 +200 +197 +201 +197 +196 +194 +191 +187 +184 +187 +188 +192 +191 +194 +193 +193 +190 +186 +183 +186 +190 +193 +191 +192 +193 +194 +197 +200 +198 +196 +195 +191 +191 +189 +192 +189 +186 +185 +185 +187 +191 +193 +193 +190 +188 +192 +188 +184 +188 +187 +190 +191 +194 +190 +190 +193 +191 +193 +196 +197 +196 +196 +198 +202 +199 +200 +199 +203 +204 +208 +207 +206 +204 +202 +203 +206 +207 +203 +201 +202 +205 +201 +197 +198 +194 +190 +191 +187 +190 +187 +186 +189 +192 +192 +191 +188 +192 +195 +199 +201 +199 +203 +205 +202 +203 +203 +206 +210 +213 +215 +219 +217 +214 +214 +212 +215 +212 +214 +216 +218 +219 +220 +219 +216 +218 +214 +214 +213 +209 +211 +212 +211 +212 +210 +208 +211 +215 +214 +217 +213 +209 +212 +208 +212 +212 +214 +214 +210 +208 +206 +207 +205 +207 +204 +203 +204 +204 +201 +205 +202 +201 +202 +205 +208 +205 +203 +204 +202 +205 +208 +211 +207 +207 +208 +212 +212 +210 +207 +207 +203 +201 +203 +199 +202 +205 +201 +203 +203 +205 +202 +202 +200 +204 +208 +209 +212 +215 +213 +212 +208 +209 +212 +214 +217 +213 +216 +215 +217 +215 +216 +213 +210 +208 +209 +212 +211 +207 +206 +208 +209 +206 +210 +207 +203 +204 +203 +201 +197 +195 +198 +197 +199 +195 +198 +201 +204 +202 +205 +202 +199 +195 +197 +195 +195 +194 +190 +190 +192 +189 +189 +188 +189 +190 +186 +182 +184 +180 +176 +180 +177 +180 +183 +184 +182 +182 +185 +188 +190 +189 +193 +191 +194 +196 +194 +191 +195 +197 +193 +193 +194 +196 +196 +198 +201 +203 +203 +199 +195 +197 +200 +199 +197 +195 +198 +202 +201 +204 +200 +197 +195 +198 +198 +194 +194 +195 +192 +193 +194 +196 +194 +191 +193 +189 +191 +187 +188 +187 +184 +184 +182 +179 +179 +179 +182 +179 +178 +181 +181 +181 +178 +174 +178 +175 +174 +178 +174 +176 +174 +171 +173 +174 +170 +169 +170 +173 +169 +166 +167 +167 +164 +161 +164 +167 +170 +167 +168 +164 +163 +164 +164 +161 +159 +159 +162 +159 +156 +158 +162 +162 +166 +164 +166 +166 +165 +168 +166 +169 +171 +173 +174 +174 +173 +172 +168 +165 +165 +162 +158 +156 +155 +158 +156 +160 +160 +160 +156 +155 +153 +154 +152 +154 +155 +159 +157 +160 +161 +157 +159 +162 +165 +165 +161 +159 +158 +158 +159 +162 +166 +167 +165 +166 +162 +159 +156 +153 +153 +153 +151 +149 +149 +151 +152 +149 +146 +147 +150 +149 +148 +149 +148 +144 +148 +145 +146 +143 +144 +144 +142 +145 +149 +150 +152 +150 +150 +152 +151 +149 +147 +145 +142 +145 +142 +140 +143 +145 +146 +148 +150 +150 +153 +149 +146 +149 +153 +154 +153 +156 +155 +158 +162 +162 +158 +160 +160 +159 +157 +159 +161 +163 +167 +163 +160 +161 +160 +160 +157 +159 +163 +161 +159 +160 +156 +155 +153 +149 +149 +146 +143 +144 +143 +140 +143 +146 +146 +142 +139 +143 +147 +146 +142 +145 +147 +146 +146 +144 +143 +146 +148 +144 +147 +144 +142 +141 +143 +143 +140 +144 +143 +146 +149 +147 +147 +150 +146 +150 +146 +150 +153 +156 +160 +164 +163 +164 +164 +164 +163 +160 +159 +163 +163 +163 +159 +162 +159 +158 +158 +160 +163 +165 +167 +167 +164 +162 +166 +165 +168 +164 +165 +163 +164 +161 +161 +165 +168 +169 +170 +166 +164 +165 +165 +167 +169 +172 +176 +178 +181 +181 +177 +175 +178 +179 +177 +178 +181 +178 +175 +173 +172 +168 +164 +160 +158 +158 +160 +159 +162 +162 +159 +159 +161 +161 +164 +162 +163 +162 +158 +158 +160 +157 +157 +158 +156 +153 +155 +158 +161 +165 +161 +160 +159 +157 +155 +151 +149 +152 +155 +157 +153 +157 +159 +161 +164 +162 +159 +159 +157 +159 +156 +154 +153 +156 +156 +154 +157 +158 +156 +157 +157 +161 +158 +160 +157 +160 +158 +161 +164 +168 +171 +167 +168 +170 +174 +171 +167 +169 +170 +169 +165 +161 +163 +164 +162 +163 +163 +160 +160 +160 +163 +165 +162 +159 +163 +161 +158 +154 +153 +157 +156 +154 +153 +155 +158 +159 +161 +157 +155 +157 +157 +154 +153 +150 +146 +150 +150 +149 +153 +150 +146 +147 +147 +145 +144 +140 +138 +141 +137 +139 +143 +146 +147 +143 +144 +143 +144 +144 +147 +151 +155 +157 +157 +159 +163 +163 +159 +163 +164 +167 +170 +168 +165 +168 +169 +170 +172 +170 +169 +173 +177 +177 +181 +177 +181 +180 +176 +178 +182 +180 +180 +178 +176 +174 +172 +175 +176 +173 +176 +173 +169 +167 +165 +161 +157 +160 +156 +154 +152 +155 +156 +160 +162 +161 +163 +166 +168 +167 +170 +171 +167 +169 +166 +163 +162 +158 +156 +157 +157 +161 +158 +160 +158 +155 +154 +156 +158 +158 +160 +156 +160 +156 +160 +164 +167 +167 +166 +162 +164 +163 +161 +163 +162 +160 +163 +161 +163 +160 +158 +162 +166 +163 +167 +164 +160 +158 +156 +159 +161 +165 +165 +168 +169 +170 +166 +167 +168 +169 +169 +165 +168 +166 +163 +166 +162 +161 +165 +164 +163 +167 +163 +166 +167 +163 +163 +167 +171 +170 +167 +164 +165 +167 +166 +169 +168 +164 +168 +171 +174 +177 +178 +181 +181 +185 +184 +185 +183 +187 +186 +185 +189 +191 +195 +192 +193 +197 +201 +197 +193 +197 +196 +196 +196 +195 +194 +195 +191 +191 +188 +186 +185 +183 +186 +189 +192 +190 +191 +195 +193 +196 +192 +188 +187 +184 +183 +184 +180 +183 +186 +187 +186 +188 +186 +186 +185 +186 +186 +184 +187 +185 +184 +186 +188 +187 +184 +187 +186 +185 +186 +188 +188 +186 +186 +185 +183 +184 +183 +184 +186 +188 +189 +193 +195 +194 +197 +193 +189 +188 +184 +187 +189 +185 +188 +191 +191 +189 +191 +195 +193 +190 +191 +189 +185 +184 +180 +177 +179 +181 +182 +185 +189 +193 +192 +194 +194 +191 +187 +183 +183 +180 +176 +173 +170 +168 +167 +169 +167 +167 +171 +171 +172 +174 +176 +177 +178 +176 +173 +174 +177 +174 +176 +180 +177 +179 +180 +181 +177 +179 +179 +181 +182 +185 +181 +183 +179 +177 +181 +180 +176 +178 +181 +182 +179 +178 +174 +173 +175 +175 +175 +179 +180 +181 +180 +184 +183 +180 +183 +183 +187 +189 +189 +193 +196 +199 +199 +197 +199 +199 +195 +192 +192 +195 +197 +197 +195 +199 +200 +196 +200 +204 +201 +200 +202 +200 +197 +196 +200 +202 +200 +198 +194 +197 +200 +198 +199 +196 +199 +203 +201 +205 +201 +197 +197 +196 +199 +199 +202 +199 +195 +194 +195 +197 +194 +192 +192 +196 +199 +199 +201 +197 +201 +200 +201 +197 +200 +197 +193 +193 +196 +200 +204 +206 +203 +202 +201 +201 +203 +202 +201 +202 +198 +196 +200 +200 +196 +198 +195 +191 +189 +188 +186 +183 +181 +181 +182 +184 +187 +188 +186 +183 +185 +182 +182 +182 +180 +177 +174 +177 +181 +180 +180 +176 +175 +175 +171 +172 +169 +166 +164 +161 +165 +166 +168 +165 +163 +167 +167 +164 +167 +166 +169 +171 +172 +170 +172 +170 +170 +168 +166 +162 +159 +162 +162 +163 +163 +162 +161 +164 +165 +166 +166 +163 +163 +163 +164 +167 +164 +163 +167 +171 +172 +169 +166 +165 +164 +161 +160 +162 +165 +163 +163 +161 +161 +163 +160 +161 +161 +157 +154 +158 +157 +158 +162 +159 +161 +164 +166 +162 +158 +155 +154 +155 +159 +161 +159 +156 +153 +149 +148 +144 +142 +144 +144 +142 +141 +141 +141 +137 +134 +138 +142 +143 +146 +146 +142 +139 +138 +140 +140 +139 +139 +140 +143 +142 +139 +140 +140 +143 +146 +150 +147 +145 +141 +143 +139 +136 +133 +130 +126 +128 +128 +127 +131 +130 +130 +130 +127 +129 +131 +131 +130 +126 +127 +127 +128 +126 +122 +121 +124 +121 +118 +114 +112 +114 +115 +119 +120 +123 +119 +116 +112 +115 +113 +109 +110 +110 +114 +113 +109 +106 +102 +104 +108 +106 +104 +105 +105 +106 +103 +105 +102 +98 +100 +101 +103 +101 +105 +106 +108 +111 +114 +114 +116 +113 +112 +112 +116 +116 +115 +112 +112 +108 +106 +110 +111 +111 +114 +113 +116 +119 +118 +115 +115 +117 +121 +125 +127 +123 +124 +128 +126 +127 +125 +122 +126 +122 +119 +121 +122 +125 +124 +120 +116 +116 +112 +108 +108 +110 +108 +112 +109 +108 +105 +103 +99 +102 +106 +103 +107 +104 +100 +101 +99 +96 +95 +97 +99 +103 +102 +98 +100 +103 +103 +101 +100 +97 +97 +97 +96 +96 +93 +93 +92 +94 +90 +87 +91 +94 +95 +96 +96 +97 +99 +97 +98 +98 +99 +102 +98 +102 +104 +103 +105 +109 +110 +112 +109 +106 +110 +106 +105 +104 +107 +107 +103 +99 +96 +100 +100 +96 +93 +94 +94 +95 +96 +96 +98 +94 +96 +93 +94 +92 +95 +95 +91 +87 +84 +88 +91 +88 +84 +88 +84 +83 +81 +81 +77 +79 +76 +74 +75 +71 +67 +67 +64 +65 +61 +57 +59 +55 +52 +55 +51 +48 +48 +46 +45 +49 +50 +50 +48 +52 +55 +58 +60 +58 +57 +55 +57 +56 +57 +57 +53 +54 +58 +62 +66 +63 +64 +61 +62 +59 +58 +58 +57 +57 +58 +60 +57 +55 +56 +55 +51 +47 +50 +52 +49 +50 +52 +48 +44 +46 +45 +45 +46 +42 +46 +45 +47 +47 +49 +47 +43 +47 +43 +44 +42 +41 +37 +39 +36 +34 +37 +41 +41 +41 +41 +42 +43 +45 +49 +47 +44 +43 +44 +47 +48 +52 +52 +51 +50 +47 +46 +50 +53 +49 +52 +56 +57 +53 +50 +51 +50 +53 +49 +52 +50 +51 +54 +51 +52 +49 +50 +51 +48 +52 +48 +47 +46 +49 +49 +46 +42 +41 +42 +43 +45 +44 +40 +44 +48 +51 +54 +50 +51 +55 +59 +62 +66 +63 +66 +65 +69 +71 +72 +75 +73 +72 +75 +75 +72 +70 +74 +75 +79 +78 +75 +79 +77 +73 +71 +72 +69 +71 +75 +78 +74 +76 +76 +75 +71 +71 +67 +69 +71 +73 +72 +76 +74 +78 +77 +80 +77 +76 +78 +74 +74 +77 +80 +78 +78 +81 +79 +77 +73 +77 +73 +71 +74 +72 +74 +78 +79 +83 +79 +80 +84 +86 +85 +86 +90 +90 +91 +93 +91 +95 +97 +95 +94 +97 +101 +97 +94 +97 +100 +103 +102 +98 +98 +97 +93 +91 +95 +96 +98 +96 +99 +103 +104 +105 +103 +104 +102 +101 +98 +102 +103 +99 +101 +100 +102 +103 +104 +106 +105 +103 +103 +99 +101 +104 +103 +99 +97 +100 +98 +100 +102 +99 +98 +98 +101 +102 +101 +99 +96 +97 +99 +99 +100 +101 +100 +96 +99 +101 +105 +101 +99 +98 +97 +93 +90 +92 +92 +94 +97 +99 +102 +103 +100 +97 +99 +97 +99 +102 +105 +109 +113 +113 +115 +113 +109 +106 +106 +107 +103 +104 +102 +103 +101 +103 +99 +103 +103 +104 +100 +104 +101 +99 +98 +95 +97 +101 +97 +98 +94 +94 +97 +101 +102 +105 +101 +103 +105 +109 +109 +112 +108 +110 +108 +109 +109 +109 +113 +116 +120 +119 +117 +117 +119 +115 +114 +113 +116 +116 +114 +117 +120 +122 +123 +120 +118 +121 +125 +128 +130 +134 +137 +139 +142 +143 +141 +143 +141 +139 +141 +137 +139 +140 +144 +144 +141 +140 +144 +140 +137 +133 +133 +135 +132 +129 +128 +132 +136 +138 +138 +137 +133 +134 +131 +132 +130 +127 +125 +126 +127 +128 +129 +129 +130 +133 +132 +133 +137 +141 +144 +140 +137 +133 +133 +135 +139 +143 +144 +144 +148 +146 +145 +149 +147 +151 +147 +150 +152 +150 +148 +146 +145 +143 +139 +141 +141 +139 +143 +145 +148 +144 +146 +144 +148 +149 +147 +149 +145 +149 +148 +151 +153 +156 +156 +152 +155 +152 +154 +150 +151 +152 +149 +146 +145 +146 +145 +144 +147 +151 +155 +159 +156 +159 +158 +160 +159 +157 +160 +158 +154 +158 +154 +157 +157 +155 +155 +158 +158 +157 +155 +151 +151 +147 +150 +149 +145 +147 +143 +139 +142 +142 +141 +138 +139 +139 +140 +140 +144 +146 +148 +144 +146 +147 +147 +143 +145 +142 +146 +146 +143 +145 +149 +148 +152 +149 +148 +146 +146 +144 +140 +139 +140 +144 +141 +144 +147 +145 +147 +145 +146 +148 +145 +144 +148 +149 +146 +147 +143 +141 +142 +146 +143 +140 +139 +138 +136 +139 +135 +135 +132 +134 +135 +139 +140 +141 +137 +135 +138 +137 +134 +133 +134 +130 +133 +136 +137 +136 +134 +137 +137 +141 +143 +146 +150 +151 +153 +157 +161 +158 +158 +160 +162 +163 +159 +158 +158 +161 +163 +167 +163 +166 +166 +167 +163 +159 +159 +157 +157 +156 +152 +151 +150 +152 +153 +153 +155 +151 +153 +153 +154 +150 +154 +150 +149 +151 +155 +151 +148 +144 +144 +140 +138 +134 +132 +131 +131 +128 +131 +128 +127 +126 +130 +126 +129 +127 +129 +125 +125 +124 +121 +125 +124 +128 +126 +126 +126 +124 +121 +125 +127 +129 +133 +134 +135 +138 +141 +143 +142 +141 +138 +136 +133 +130 +126 +125 +124 +123 +119 +117 +116 +112 +115 +118 +118 +117 +114 +111 +112 +108 +106 +106 +108 +105 +101 +103 +101 +102 +99 +101 +99 +101 +102 +103 +106 +103 +103 +100 +96 +95 +92 +90 +88 +85 +83 +79 +78 +76 +73 +71 +74 +73 +75 +71 +71 +69 +66 +66 +63 +61 +59 +62 +58 +59 +59 +55 +57 +59 +60 +56 +56 +53 +56 +57 +55 +52 +56 +54 +57 +61 +57 +54 +56 +58 +61 +59 +56 +60 +57 +54 +57 +60 +60 +63 +63 +65 +62 +58 +59 +59 +62 +65 +68 +71 +67 +63 +66 +68 +70 +74 +74 +72 +71 +68 +72 +68 +66 +66 +65 +65 +69 +71 +69 +66 +69 +71 +75 +75 +73 +69 +67 +66 +66 +68 +65 +61 +62 +66 +69 +68 +72 +73 +73 +69 +72 +74 +77 +76 +77 +77 +77 +77 +76 +80 +79 +76 +77 +77 +79 +78 +78 +77 +78 +82 +85 +89 +86 +85 +87 +85 +88 +92 +91 +87 +89 +92 +90 +91 +87 +83 +85 +87 +89 +89 +87 +84 +87 +84 +82 +78 +75 +79 +80 +81 +78 +81 +83 +83 +86 +85 +81 +82 +83 +82 +82 +79 +76 +75 +75 +76 +77 +79 +82 +83 +81 +78 +75 +78 +77 +73 +70 +68 +68 +67 +68 +67 +68 +68 +67 +63 +66 +70 +73 +74 +70 +72 +71 +71 +71 +71 +73 +71 +67 +67 +63 +62 +61 +58 +55 +51 +53 +49 +46 +48 +48 +46 +48 +48 +45 +45 +45 +44 +40 +42 +39 +39 +36 +39 +42 +44 +46 +49 +48 +47 +50 +54 +53 +55 +56 +57 +58 +60 +62 +65 +67 +67 +69 +68 +71 +73 +70 +70 +73 +69 +73 +70 +70 +67 +66 +66 +63 +60 +59 +57 +58 +56 +60 +57 +60 +64 +60 +62 +63 +67 +64 +61 +64 +63 +63 +59 +63 +65 +63 +59 +59 +62 +58 +55 +52 +51 +52 +53 +53 +51 +52 +49 +48 +50 +54 +51 +50 +46 +43 +42 +38 +40 +40 +40 +36 +35 +38 +40 +40 +38 +40 +42 +45 +47 +43 +46 +43 +44 +47 +43 +46 +42 +46 +44 +48 +51 +51 +49 +53 +54 +56 +57 +57 +54 +56 +56 +53 +54 +55 +52 +51 +47 +44 +48 +46 +47 +49 +52 +52 +49 +52 +51 +48 +45 +43 +40 +43 +40 +41 +45 +42 +39 +43 +46 +50 +47 +46 +47 +43 +42 +46 +47 +49 +53 +55 +57 +53 +53 +51 +51 +47 +45 +48 +46 +47 +46 +42 +40 +43 +44 +45 +41 +38 +35 +34 +30 +28 +30 +32 +29 +27 +23 +21 +21 +24 +24 +28 +28 +24 +20 +20 +22 +23 +23 +21 +23 +19 +20 +22 +19 +22 +19 +22 +21 +22 +19 +21 +18 +21 +25 +23 +20 +22 +22 +22 +20 +22 +19 +18 +15 +16 +20 +23 +22 +26 +29 +28 +29 +33 +30 +26 +29 +30 +28 +29 +27 +28 +25 +23 +22 +23 +20 +24 +27 +23 +26 +23 +23 +24 +23 +19 +23 +19 +21 +23 +19 +22 +23 +26 +23 +27 +27 +26 +28 +26 +23 +25 +22 +26 +30 +30 +33 +33 +29 +28 +29 +27 +26 +26 +24 +28 +31 +31 +34 +32 +28 +27 +28 +31 +27 +28 +28 +29 +32 +32 +35 +31 +31 +32 +33 +36 +40 +41 +41 +42 +41 +45 +41 +38 +42 +45 +43 +39 +39 +40 +43 +45 +46 +45 +41 +40 +43 +45 +41 +38 +41 +40 +44 +40 +43 +39 +39 +38 +41 +40 +40 +39 +35 +35 +34 +37 +39 +39 +39 +36 +37 +39 +35 +31 +32 +31 +30 +30 +31 +34 +30 +34 +37 +36 +33 +33 +33 +33 +34 +32 +30 +34 +38 +35 +39 +35 +37 +40 +38 +35 +34 +37 +41 +43 +39 +38 +41 +44 +46 +43 +45 +48 +49 +45 +43 +39 +37 +38 +38 +37 +33 +29 +32 +32 +30 +29 +26 +23 +21 +17 +16 +15 +14 +14 +13 +14 +16 +15 +18 +17 +20 +19 +16 +18 +18 +22 +19 +20 +23 +25 +21 +17 +15 +17 +14 +13 +13 +17 +13 +14 +16 +18 +17 +19 +17 +18 +16 +14 +13 +12 +14 +12 +9 +9 +11 +15 +15 +11 +12 +13 +17 +18 +21 +23 +19 +18 +22 +18 +14 +14 +13 +12 +9 +8 +12 +14 +14 +16 +16 +17 +20 +23 +20 +20 +18 +22 +21 +24 +28 +28 +28 +25 +27 +30 +28 +31 +31 +31 +29 +30 +34 +37 +33 +34 +37 +40 +38 +34 +36 +32 +28 +31 +30 +31 +31 +34 +34 +35 +33 +31 +31 +29 +33 +37 +38 +35 +37 +33 +29 +29 +30 +34 +31 +31 +29 +28 +26 +25 +29 +25 +21 +22 +18 +21 +24 +22 +22 +21 +22 +21 +23 +23 +22 +24 +23 +19 +16 +14 +13 +15 +16 +19 +22 +18 +17 +13 +11 +13 +12 +15 +15 +17 +17 +21 +19 +23 +25 +29 +27 +29 +28 +24 +26 +29 +30 +28 +25 +21 +23 +23 +20 +19 +22 +19 +23 +23 +26 +23 +21 +23 +26 +30 +33 +35 +39 +36 +32 +30 +28 +24 +22 +24 +26 +29 +32 +36 +35 +35 +37 +34 +37 +40 +38 +35 +34 +30 +29 +31 +35 +36 +32 +36 +36 +36 +33 +30 +27 +23 +27 +29 +30 +31 +28 +30 +32 +29 +30 +26 +23 +26 diff --git a/hw3/encoding.py b/hw3/encoding.py new file mode 100644 index 0000000..2a1f834 --- /dev/null +++ b/hw3/encoding.py @@ -0,0 +1,59 @@ +'''ecoding.py provides utilities for compressing a file of data +using a 'delta' encoding (change over the previous) element. +''' +import struct + +#TODO 1. Write a function that loads the input data +#and returns a list of numbers +def load_orig_file(in_filename): + '''load_orig_file takes an input file and returns a list of + numbers. The file is formatted with a single integer + number on each line + ''' + + raise ValueError('Not implemented') + + +#TODO 2. Write a function that performs the delta encoding +def delta_encoding(data): + '''delta_encoding takes a list of integers and performs + a delta encoding represent each element as a difference + from the previous one. The first element is kept as is. + + delta_encoding encoding returns a list where the first + element is the original value and all the rest of the + elements are deltas from the first value. + ''' + + raise ValueError('Not implemented') + + +#TODO 3. Apply a shift to all the elements so all the deltas are positive +def shift(data, offset): + '''shift adds 'offset' to all of the elements to ensure that + every value in the delta encoding is positive. + ''' + raise ValueError('Not implemented') + +#GIVEN, should be obvious what it does +def unshift(data, offset): + return shift(data,-offset) + +#TODO 4. Convert the encoded data into a byte array and write +#to disk. +def write_encoding(data, out_file): + raise ValueError('Not implemented') + +#GIVEN, read encoded file +def read_encoding(out_file): + f = open(out_file, 'rb') + encoded = f.read() + return struct.unpack("B"*len(encoded), encoded) + + +#TODO 5. Write a function that performs the delta encoding +def delta_decoding(data): + '''delta_decoding takes a delta encoded list and return + the original data. + ''' + raise ValueError('Not implemented') \ No newline at end of file diff --git a/hw4/README.md b/hw4/README.md index 860fb9d..9cd6aea 100644 --- a/hw4/README.md +++ b/hw4/README.md @@ -1,74 +1,64 @@ -# HW3 String Matching +# Homework 2. Bloom Filter +This homework assignment introduces an advanced use of hashing called a Bloom filter. -*Due 5/14/20 11:59 PM* -Entity Resolution is the task of disambiguating manifestations of real world entities in various records or mentions by linking and grouping. For example, there could be different ways of addressing the same person in text, different addresses for businesses, or photos of a particular object. In this assignment, you will link two product catalogs. +Due Date: *Friday May 1st, 2020 11:59 pm* -## Getting Started -First, pull the most recent changes from the cmsc13600-public repository: +## Initial Setup +These initial setup instructions assume you've done ``hw0``. Before you start an assingment you should sync your cloned repository with the online one: ``` +$ cd cmsc13600-materials $ git pull ``` -Then, copy the `hw3` folder to your submission repository. Change directories to enter your submission repository. Your code will go into `analzey.py`. You can the files to the repository using `git add`: + +Copy the folder ``hw2`` to your newly cloned submission repository. Enter that repository from the command line and enter the copied ``hw2`` folder. In this homework assignment, you will only modify ``bloom.py``. Once you are done, you must add 'bloom.py' to git: ``` -$ git add analyze.py -$ git commit -m'initialized homework' +$ git add bloom.py ``` -You will also need to fetch the datasets used in this homework assignment: +After adding your files, to submit your code you must run: ``` -https://www.dropbox.com/s/vq5dyl5hwfhbw98/Amazon.csv?dl=0 -https://www.dropbox.com/s/fbys7cqnbl3ch1s/Amzon_GoogleProducts_perfectMapping.csv?dl=0 -https://www.dropbox.com/s/o6rqmscmv38rn1v/GoogleProducts.csv?dl=0 +$ git commit -m"My submission" +$ git push ``` -Download each of the files and put it into your `hw3` folder. +We will NOT grade any code that is not added, committed, and pushed to your submission repository. You can confirm your submission by visiting the web interface[https://mit.cs.uchicago.edu/cmsc13600-spr-20/skr] -Before we can get started, let us understand the main APIs in this project. We have provided a file named `core.py` for you. This file loads and processes the data that you've just downloaded. For example, you can load the Amazon catalog with the `amazon_catalog()` function. This returns an iterator over data tuples in the Amazon catalog. The fields are id, title, description, mfg (manufacturer), and price if any: -``` ->>>for a in amazon_catalog(): -... print(a) -... break +## Bloom filter +A Bloom filter is a space-efficient probabilistic data structure, conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set. False positive matches are possible, but false negatives are not – in other words, a query returns either "possibly in set" or "definitely not in set." Elements can be added to the set, but not removed (though this can be addressed with the counting Bloom filter variant); the more items added, the larger the probability of false positives. All of the necessary parts that you need to write are marked with *TODO*. -{'id': 'b000jz4hqo', 'title': 'clickart 950 000 - premier image pack (dvd-rom)', 'description': '', 'mfg': 'broderbund', 'price': '0'} -``` -You can similarly, do the same for the Google catalog: -``` ->>>for a in google_catalog(): -... print(a) -... break +Here's how the basic Bloom filter works: -{'id': 'http://www.google.com/base/feeds/snippets/11125907881740407428', 'title': 'learning quickbooks 2007', 'description': 'learning quickbooks 2007', 'mfg': 'intuit', 'price': '38.99'} -``` -A matching is a pairing between id's in the Google catalog and the Amazon catalog that refer to the same product. The ground truth is listed in the file `Amzon_GoogleProducts_perfectMapping.csv`. Your job is to construct a list of pairs (or iterator of pairs) of `(amazon.id, google.id)`. These matchings can be evaluated for accuracy using the `eval_matching` function: -``` ->>> my_matching = [('b000jz4hqo', http://www.google.com/base/feeds/snippets/11125907881740407428'),...] ->>> {'false positive': 0.9768566493955095, 'false negative': 0.43351268255188313, 'accuracy': 0.04446992095577143} -``` -False positive refers to the false positive rate, false negative refers to the false negative rate, and accuracy refers to the overall accuracy. +### Initialization +* An empty Bloom filter is initialized with an array of *m* elements each with value 0. +* Generate *k* independent hash functions whose output domain are integers {0,...,m}. -## Assignment -Your job is write the `match` function in `analzye.py`. You can run your code by running: -``` -python3 auto_grader.py -``` -Running the code will print out a result report as follows (accuracy, precision, and recall): -``` -----Accuracy---- -0.5088062622309197 0.6998654104979811 0.3996925441967717 ----- Timing ---- -168.670348 seconds +### Adding An Item e +* For each hash function calculate the hash value of the item "e" (should be a number from 0 to m). +* Treat those calculated hash values as indices for the array and set each corresponding index in the array to 1 (if it is already 1 from a previous addition keep it as is). -``` -*For full credit, you must write a program that achieves at least 50% accuracy in less than 5 mins on a standard laptop.* +### Contains An Item e +* For each hash function calculate the hash value of the item "e" (should be a number from 0 to m). +* Treat those calculated hash values as indices for the array and retrieve the array value for each corresponding index. If any of the values is 0, we know that "e" could not have possibly been inserted in the past. -The project is complete unstructured and it is up to you to figure out how to make this happen. Here are some hints: +## TODO 1. Generate K independent Hash Functions +Your first task is to write the function `generate_hashes`. This function is a higher-order function that returns a list of *k* random hash functions each with a range from 0 to *m*. Here are some hints that will help you write this function. -* The amazon product database is redundant (multiple same products), the google database is essentially unique. +* Step 1. Review the "linear" hash function described in lecture and write a helper function that generates such a hash function for a pre-defined A and B. How would you restrict the domain of this hash function to be with 0 to m? -* Jaccard similarity will be useful but you may have to consider "n-grams" of words (look at the lecture notes!) and "cleaning" up the strings to strip formatting and punctuation. +* Step 2. Generate k of such functions with different random settings of A and B. Pay close attention to how many times you call "random.x" because of how the seeded random variable works. -* Price and manufacturer will also be important attributes to use. +* Step 3. Return the functions themselves so they can be applied to data. Look at the autograder to understand what inputs these functions should take. -## Submission -After you finish the assignment you can submit your code with: -``` -$ git push -``` +## TODO 2. Put +Write a function that uses the algorithm listed above to add a string to the bloom filter. In pseudo-code: +* For each of the k hash functions: +* Compute the hash code of the string, and store the code in i +* Set the ith element of the array to 1 + +## TODO 3. Get +Write a function that uses the algorithm listed above to test whether the bloom filter possibly contains the string. In pseudo-code: +* For each of the k hash functions: +* Compute the hash code of the string, and store the code in i +* if the ith element is 0, return false +* if all code-indices are 1, return true + +## Testing +We've provided an autograder script `autograder.py` which runs a bunch of interesting tests. The autograder is not comprehensive but it is a good start. It's up to you to figure out what the test do and why they work. diff --git a/hw4/analyze.py b/hw4/analyze.py deleted file mode 100644 index ee71842..0000000 --- a/hw4/analyze.py +++ /dev/null @@ -1,14 +0,0 @@ -from core import * -import datetime - -def match(): - ''' - Match must return a list of tuples of amazon ids and google ids. - For example: - [('b000jz4hqo', http://www.google.com/base/feeds/snippets/11125907881740407428'),....] - - ''' - - #YOUR CODE GOES HERE - - return [] \ No newline at end of file diff --git a/hw4/auto_grader.py b/hw4/auto_grader.py index 0606d63..4715d4e 100644 --- a/hw4/auto_grader.py +++ b/hw4/auto_grader.py @@ -1,50 +1,112 @@ -import datetime -import csv -from analyze import match - -def eval_matching(your_matching): - f = open('Amzon_GoogleProducts_perfectMapping.csv', 'r', encoding = "ISO-8859-1") - reader = csv.reader(f, delimiter=',', quotechar='"') - matches = set() - proposed_matches = set() - - tp = set() - fp = set() - fn = set() - tn = set() - - for row in reader: - matches.add((row[0],row[1])) - #print((row[0],row[1])) - - for m in your_matching: - proposed_matches.add(m) - - if m in matches: - tp.add(m) - else: - fp.add(m) - - for m in matches: - if m not in proposed_matches: - fn.add(m) - - if len(your_matching) == 0: - prec = 1.0 - else: - prec = len(tp)/(len(tp) + len(fp)) - - rec = len(tp)/(len(tp) + len(fn)) - - return {'precision': prec, - 'recall': rec, - 'accuracy': 2*(prec*rec)/(prec+rec) } - -#prints out the accuracy -now = datetime.datetime.now() -out = eval_matching(match()) -timing = (datetime.datetime.now()-now).total_seconds() -print("----Accuracy----") -print(out['accuracy'], out['precision'] ,out['recall']) -print("---- Timing ----") -print(timing,"seconds") +import random +import string + +from bloom import * + +def generate_random_string(seed=True): + chars = string.ascii_uppercase + string.digits + size = 10 + return ''.join(random.choice(chars) for x in range(size)) + +def test_hash_generation(): + b = Bloom(5,10) + + try: + assert(len(b.hashes) == 10) + except: + print('[#1] Failure the number of generated hashes is wrong') + + try: + + for h in b.hashes: + h(generate_random_string()) + + except: + print('[#2] The hashes are not properly represented as a lambda') + + + s = generate_random_string() + + try: + for h in b.hashes: + assert(h(s) == h(s)) + except: + print('[#3] Hashes are not deterministic') + + + try: + b = Bloom(100,10) + b1h = b.hashes[0](s) + b = Bloom(100,10) + b2h = b.hashes[0](s) + + assert(b1h == b2h) + + except: + print('[#4] Seeds are not properly set') + + + try: + b = Bloom(100,10) + + for h in b.hashes: + for i in range(10): + assert( h(generate_random_string())< 100 ) + + except: + print('[#5] Hash exceeds range') + + + try: + b = Bloom(1000,2) + s = generate_random_string() + bh1 = b.hashes[0](s) + bh2 = b.hashes[1](s) + + assert(bh1 != bh2) + + except: + print('[#6] Hashes generated are not independent') + +def test_put(): + b = Bloom(100,10,seed=0) + b.put('the') + b.put('university') + b.put('of') + b.put('chicago') + + try: + assert(sum(b.array) == 30) + except: + print('[#7] Unexpected Put() Result') + +def test_put_get(): + b = Bloom(100,5,seed=0) + b.put('the') + b.put('quick') + b.put('brown') + b.put('fox') + b.put('jumped') + b.put('over') + b.put('the') + b.put('lazy') + b.put('dog') + + results = [b.contains('the'),\ + b.contains('cow'), \ + b.contains('jumped'), \ + b.contains('over'),\ + b.contains('the'), \ + b.contains('moon')] + + try: + assert(results == [True, False, True, True, True, False]) + except: + print('[#8] Unexpected contains result') + +test_hash_generation() +test_put() +test_put_get() + + + diff --git a/hw4/bloom.py b/hw4/bloom.py new file mode 100644 index 0000000..f8819e1 --- /dev/null +++ b/hw4/bloom.py @@ -0,0 +1,49 @@ +'''bloom.py defines a bloom filter which is an +approximate set membership data structure. You +will implement a full bloom filter in this module +''' +import array +import binascii +import random + +class Bloom(object): + + def __init__(self, m,k, seed=0): + '''Creates a bloom filter of size m with k + independent hash functions. + ''' + + self.array = array.array('B', [0] * m) + self.hashes = self.generate_hashes(m,k,seed) + + + #TODO + def generate_hashes(self, m, k, seed): + '''Generate *k* independent linear hash functions + each with the range 0,...,m. + + m: the range of the hash functions + k: the number of hash functions + seed: a random seed that controls which A/B linear + parameters are used. + + The output of this function should be a list of functions + ''' + random.seed(seed) + + #TODO + + raise ValueError('Not Implemented') + + + + def put(self, item): + '''Add a string to the bloom filter, returns void + ''' + #TODO + + def contains(self, item): + '''Test to see if the bloom filter could possibly + contain the string (true (possibly)), false (definitely). + ''' + #TODO \ No newline at end of file diff --git a/hw4/core.py b/hw4/core.py deleted file mode 100644 index 890c78a..0000000 --- a/hw4/core.py +++ /dev/null @@ -1,41 +0,0 @@ -''' -The core module sets up the data structures and -and references for this programming assignment. - -2010 -''' - -import platform -import csv - -if platform.system() == 'Windows': - print("This assignment will not work on a windows computer") - exit() - - -#defines an iterator over the google catalog -class Catalog(): - - def __init__(self, filename): - self.filename = filename - - def __iter__(self): - f = open(self.filename, 'r', encoding = "ISO-8859-1") - self.reader = csv.reader(f, delimiter=',', quotechar='"') - next(self.reader) - return self - - def __next__(self): - row = next(self.reader) - return {'id': row[0], - 'title': row[1], - 'description': row[2], - 'mfg': row[3], - 'price': row[4] - } - -def google_catalog(): - return Catalog('GoogleProducts.csv') - -def amazon_catalog(): - return Catalog('Amazon.csv') -- libgit2 0.25.0