ANLP_WS24_CA1/structual_pattern.ipynb

568 lines
41 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tokenization adn Normalization"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"import os\n",
"from collections import Counter\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import nltk\n",
"\n",
"from nltk.corpus import stopwords\n",
"from nltk.tokenize import word_tokenize, sent_tokenize\n",
"from nltk.stem import WordNetLemmatizer\n"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[nltk_data] Downloading package punkt to\n",
"[nltk_data] C:\\Users\\felix\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package punkt is already up-to-date!\n",
"[nltk_data] Downloading package stopwords to\n",
"[nltk_data] C:\\Users\\felix\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package stopwords is already up-to-date!\n",
"[nltk_data] Downloading package wordnet to\n",
"[nltk_data] C:\\Users\\felix\\AppData\\Roaming\\nltk_data...\n",
"[nltk_data] Package wordnet is already up-to-date!\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# nltk count words\n",
"nltk.download('punkt')\n",
"nltk.download('stopwords')\n",
"nltk.download('wordnet')"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
"# Load the data\n",
"# Load the data from the JSON file\n",
"data_path = './data/reddit_jokes.json'\n",
"with open(data_path) as f:\n",
" data = json.load(f)"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>body</th>\n",
" <th>id</th>\n",
" <th>score</th>\n",
" <th>title</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Now I have to say \"Leroy can you please paint ...</td>\n",
" <td>5tz52q</td>\n",
" <td>1</td>\n",
" <td>I hate how you cant even say black paint anymore</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Pizza doesn't scream when you put it in the ov...</td>\n",
" <td>5tz4dd</td>\n",
" <td>0</td>\n",
" <td>What's the difference between a Jew in Nazi Ge...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>...and being there really helped me learn abou...</td>\n",
" <td>5tz319</td>\n",
" <td>0</td>\n",
" <td>I recently went to America....</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>A Sunday school teacher is concerned that his ...</td>\n",
" <td>5tz2wj</td>\n",
" <td>1</td>\n",
" <td>Brian raises his hand and says, “Hes in Heaven.”</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>He got caught trying to sell the two books to ...</td>\n",
" <td>5tz1pc</td>\n",
" <td>0</td>\n",
" <td>You hear about the University book store worke...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" body id score \\\n",
"0 Now I have to say \"Leroy can you please paint ... 5tz52q 1 \n",
"1 Pizza doesn't scream when you put it in the ov... 5tz4dd 0 \n",
"2 ...and being there really helped me learn abou... 5tz319 0 \n",
"3 A Sunday school teacher is concerned that his ... 5tz2wj 1 \n",
"4 He got caught trying to sell the two books to ... 5tz1pc 0 \n",
"\n",
" title \n",
"0 I hate how you cant even say black paint anymore \n",
"1 What's the difference between a Jew in Nazi Ge... \n",
"2 I recently went to America.... \n",
"3 Brian raises his hand and says, “Hes in Heaven.” \n",
"4 You hear about the University book store worke... "
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# create pandas dataframe of the data\n",
"df = pd.DataFrame(data)\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [],
"source": [
"# NOTE: bit more than 1000 jokes for removing duplicates and empty jokes\n",
"num_good = 1046\n",
"num_bad = 1033\n",
"min_score = 50\n",
"\n",
"\n",
"df_sroted = df.sort_values(by='score', ascending=False)\n",
"df_sroted = df_sroted.reset_index(drop=True)\n",
"\n",
"df_good = df_sroted.head(num_good)\n",
"df_good = df_good.reset_index(drop=True)\n",
"\n",
"df_bad = df_sroted[df_sroted['score'] > min_score].tail(num_bad)\n",
"df_bad = df_bad.reset_index(drop=True)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"avg score good jokes: 10731.98 shape: (1046, 4)\n",
"avg score bad jokes: 52.32 shape: (1033, 4)\n"
]
}
],
"source": [
"# avg score and shape\n",
"print('avg score good jokes:', df_good['score'].mean().round(2), 'shape:', df_good.shape)\n",
"print('avg score bad jokes:', df_bad['score'].mean().round(2), 'shape:', df_bad.shape)"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"####################################################################################################\n",
"5 random good jokes:\n",
"####################################################################################################\n",
"I told my wife we can have sex or go see Star Wars, she said, I'm on my period and Star Wars is sold out.\n",
"....what happens next will shock you.\"\n",
"----------------------------------------------------------------------------------------------------\n",
"Two men from Texas were sitting at a bar\n",
"\"No way. That's impossible!\" she said.\n",
"\n",
"\"Trust me,\" I said, \"I have no idea where our baby is.\"\n",
"----------------------------------------------------------------------------------------------------\n",
"My wife always accuses me of having a favorite child.\n",
"...hands down.\n",
"----------------------------------------------------------------------------------------------------\n",
"If i got 50 cents for every failed math exam,\n",
"Two fleas had an arrangement to meet every winter in Miami for a vacation. Last year, when one flea gets to Miami he is shivering and shaking.\n",
"\n",
"The other flea asked him, \"Why are shaking so badly?\"\n",
"\n",
"The first flea says, \"I rode down here from New Jersey in the moustache of a guy on a Harley.\"\n",
"\n",
"The other flea says, \"That's the worst way to travel. Do what I do. Go to the New Jersey airport bar. Have a few drinks. While there, look for a nice stewardess, crawl up her leg and nestle in where it's warm and cozy. It's the best way to travel that I can think of.\"\n",
"\n",
"The first flea thanks the second flea and says he will give it a try next winter. A year goes by... When the first flea shows up in Miami he shivering and shaking again.\n",
"\n",
"The second flea says, \"Didn't you try what I told you?\"\n",
"\n",
"\"Yes,\" says the first flea. \"I did exactly what you said. I went to the New Jersey airport bar. I had a few drinks. Finally, this nice young stewardess came in. I crawled right up to her warm cozy spot. It was so nice and warm that I fell asleep. When I woke up, I was back in the moustache of a guy on a Harley.\"\n",
"\n",
"\n",
" Edit: Front page already!!! Gr8 Guys.\n",
"----------------------------------------------------------------------------------------------------\n",
"I told god a Holocaust joke. He didn't laugh.\n",
"Whoops, wrong sub.\n",
"----------------------------------------------------------------------------------------------------\n"
]
}
],
"source": [
"# print random 5 good jokes\n",
"print('#' * 100)\n",
"print('5 random good jokes:')\n",
"print('#' * 100)\n",
"for i in range(5):\n",
" print(df_good['title'][np.random.randint(0, num_good)])\n",
" print(df_good['body'][np.random.randint(0, num_good)])\n",
" print('-' * 100)"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"####################################################################################################\n",
"5 random bad jokes:\n",
"####################################################################################################\n",
"why dont they have drivers ed and sex ed on the same day in mexico?\n",
"As he was praying a black guy was walking nearby with groceries when he dropped his cheese wheel and it rolled to the Mexican. The Mexican grabbed it, praised god, and ran home. \n",
"\n",
"When he gets home he instructs his wife to make nachos with the cheese. \n",
"\n",
"\"Why nachos\" asks his wife \"we can make so many better meals with this cheese\"\n",
"\n",
"\"No\" said the Mexican \"god instructs me to make nachos.\"\n",
"\n",
"\"What do you mean\" asked the wife \n",
"\n",
"\"As I was praying God sent me the cheese wheel and as I was running home with it I heard him yelling That's Nacho cheese, that's nacho cheese!\"\n",
"----------------------------------------------------------------------------------------------------\n",
"2 Priests go to the beach...\n",
"a navel..\n",
"----------------------------------------------------------------------------------------------------\n",
"Two parrots were sitting on a perch...\n",
"Okay I'm donesn't born yesterday..\n",
"----------------------------------------------------------------------------------------------------\n",
"I recently had sex with a biologist at her laboratory.\n",
"MAN: Id like to buy some dog food.\n",
"CHECKOUT LADY: Do you have a dog?\n",
"MAN: Yes.\n",
"CHECKOUT LADY: Where is he?\n",
"MAN: Hes at home.\n",
"CHECKOUT LADY: Im sorry; I cant sell this dog food to you unless Isee the dog. Store policy.\n",
"The next day, the man returns.\n",
"MAN: Id like to buy some cat food.\n",
"CHECKOUT LADY: Do you have a cat?\n",
"MAN: Yes.\n",
"CHECKOUT LADY: Well...where is he?\n",
"MAN: Hes at home!\n",
"CHECKOUT LADY: Sorry, I cant sell this cat food to you unless I see\n",
"your cat.\n",
"The next day the man returns.\n",
"CHECKOUT LADY: Whats in the sack?\n",
"MAN: Put your hand inside.\n",
"CHECKOUT LADY: Hmmm... Its warm and moist! What is it?\n",
"MAN: I would like to buy some toilet paper.\n",
"----------------------------------------------------------------------------------------------------\n",
"Farmer Dan\n",
"He hit me until I was 21. \n",
"----------------------------------------------------------------------------------------------------\n"
]
}
],
"source": [
"# print random 5 bad jokes\n",
"print('#' * 100)\n",
"print('5 random bad jokes:')\n",
"print('#' * 100)\n",
"for i in range(5):\n",
" print(df_bad['title'][np.random.randint(0, num_bad)])\n",
" print(df_bad['body'][np.random.randint(0, num_bad)])\n",
" print('-' * 100)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"shape after tokenizing: (1046, 6) (1033, 6)\n"
]
}
],
"source": [
"# tokenize the jokes\n",
"stop_words = set(stopwords.words('english'))\n",
"\n",
"def sentinize(joke):\n",
" tokens = sent_tokenize(joke)\n",
" tokens = [word for word in tokens if word not in stop_words]\n",
" return tokens\n",
"\n",
"# Tokenize and lemmatize the jokes\n",
"df_good['tok_body'] = df_good['body'].apply(sentinize)\n",
"df_bad['tok_body'] = df_bad['body'].apply(sentinize)\n",
"\n",
"df_good['tok_title'] = df_good['title'].apply(sentinize)\n",
"df_bad['tok_title'] = df_bad['title'].apply(sentinize)\n",
"\n",
"\n",
"\n",
"print('shape after tokenizing:', df_good.shape, df_bad.shape)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def rem_null_dubl(df):\n",
" # Remove rows where 'tok_body' or 'tok_title' is empty\n",
" df = df[df['tok_body'].map(len) > 0]\n",
" df = df[df['tok_title'].map(len) > 0]\n",
" \n",
" # Convert list-type columns to strings for deduplication\n",
" df['tok_body_str'] = df['tok_body'].apply(lambda x: ' '.join(x))\n",
" df['tok_title_str'] = df['tok_title'].apply(lambda x: ' '.join(x))\n",
" \n",
" # Remove rows where both 'tok_body' and 'tok_title' are duplicates\n",
" df = df.drop_duplicates(subset=['tok_body_str', 'tok_title_str'], keep=False)\n",
" \n",
" # Drop the temporary string columns\n",
" df = df.drop(columns=['tok_body_str', 'tok_title_str'])\n",
" \n",
" return df\n",
"\n",
"df_good = rem_null_dubl(df_good)\n",
"df_bad = rem_null_dubl(df_bad)\n",
"print('shape after removing duplicates:', df_good.shape, df_bad.shape)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_good['tokens'] = df_good['tok_body'] + df_good['tok_title']\n",
"df_bad['tokens'] = df_bad['tok_body'] + df_bad['tok_title']"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"good jokes with more than 1 sentence: 576 total: 1008\n",
"bad jokes with more than 1 sentence: 477 total: 1016\n"
]
},
{
"data": {
"image/png": "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aWkaPXq07r//fp0/f16dOnXS559/Lk9PT0k/nzH5xz/+oYkTJ2rq1KmqXbu2pkyZYn0S69IYQ4cO1d13363Q0FC99NJL1huay2vUqFEqLCzU2LFjVVBQoJiYGH3yySeXPYl1SXJyssrKytSjRw+lp6erW7duWrlypaZMmaLp06fL09NTTZo00dChQyVJQUFBmjZtmlJSUlRaWqrY2Fh9+umnTn3Xj8UwDMNpo1cRRUVFCgwMVGFhocPv3+HRcwBwnHPnzunQoUOqX7++TVCoas6cOaNbb71Vr7/+uoYMGeLSWiZMmKCvv/5a33zzjUvruJprHfPy/v12+aPnAACY3b///W/t2bNH7dq1U2FhofUKxKVLVK5gGIYOHjyojIyMq76Xziwq3Q3KAACY0WuvvaYWLVooPj5eZ86c0ddff62aNWu6rJ7CwkLFxMTIy8tLf/rTn1xWx43AmR0AAJysVatWNk9JVQZBQUE2XxMwM87sAAAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAADgZJ07d1ZycrLDx127dq0sFss1v39Vr149zZ49u9xjTp48WS1btrzu2ioTHj0HAFR9a1Jv7PbumXBjt3cdtmzZourVq7u6DJci7AAAYGK1atVydQkux2UsAABugIsXL2rkyJEKDAxUzZo19cILL+iXn6f8+9//rjZt2sjf319hYWF69NFHVVBQYDPG559/rqioKPn4+Oiee+7R999//5vb/fVlrLy8PPXu3Vt+fn4KCAjQww8/rGPHjl11/QMHDqhBgwYaOXKkDMNQSUmJnn76ad16662qXr262rdvr7Vr11r7//DDD+rVq5duueUWVa9eXU2bNtXnn39e7t/JGQg7AADcAO+++648PDy0efNmvfHGG5o5c6beeust6/ILFy5o6tSp2rZtm1asWKHvv//e5ovmhw8fVt++fdWrVy9lZ2dr6NChevbZZ+2qoaysTL1799aJEye0bt06rV69WgcPHlT//v2v2H/79u2688479eijj+rPf/6zLBaLRo4cqczMTC1dulTbt2/XQw89pO7du2vfvn2SpKSkJJWUlGj9+vXasWOHpk+fLj8/P/t/MAfiMhYAADdARESEZs2aJYvFosaNG2vHjh2aNWuWhg0bJkl64oknrH0bNGigOXPmqG3btiouLpafn58WLFighg0b6vXXX5ck6xjTp08vdw0ZGRnasWOHDh06pIiICEnS3/72NzVt2lRbtmxR27ZtrX2//fZb3X///Xruuec0duxYST+fFUpLS1NeXp7Cw8MlSU8//bTS09OVlpamV155RXl5eerXr59iY2Ot++JqnNkBAOAG6NChgywWi3U+Li5O+/btU2lpqSQpKytLvXr1UmRkpPz9/XX33XdL+jlgSFJOTo7at29vM2ZcXJxdNeTk5CgiIsIadCQpJiZGQUFBysnJsbbl5eXpvvvu08SJE61BR5J27Nih0tJSRUVFyc/PzzqtW7dOBw4ckCSNGjVKL730kjp27KhJkyZp+/btdtXoDIQdAABc7MyZM+rWrZsCAgK0ePFibdmyRcuXL5cknT9//obXU6tWLbVr107vv/++ioqKrO3FxcVyd3dXVlaWsrOzrVNOTo7eeOMNSdLQoUN18OBBPfbYY9qxY4fatGmjuXPn3vB9+CXCDgAAN8CmTZts5jdu3KhGjRrJ3d1de/bs0fHjxzVt2jTdddddatKkyWU3J0dHR2vz5s2XjWGP6OhoHT58WIcPH7a27d69W6dOnVJMTIy1zcfHRytXrlS1atXUrVs3nT59WtLPX28vLS1VQUGBbrvtNpspLCzMun5ERIRGjBihZcuWaezYsXrzzTftqtPRCDsAANwAeXl5SklJUW5urt5//33NnTtXo0ePliRFRkbKy8tLc+fO1cGDB/XJJ59o6tSpNuuPGDFC+/bt07hx45Sbm6slS5Zo0aJFdtUQHx+v2NhYJSYm6rvvvtPmzZs1cOBA3X333WrTpo1N3+rVq+uzzz6Th4eHEhISVFxcrKioKCUmJmrgwIFatmyZDh06pM2bNys1NVWfffaZJCk5OVmrVq3SoUOH9N1332nNmjWKjo6u+A/nAIQdAABugIEDB+qnn35Su3btlJSUpNGjR2v48OGSfr5stGjRIn344YeKiYnRtGnT9Nprr9msHxkZqY8++kgrVqxQixYttHDhQr3yyit21WCxWPTxxx/rlltuUadOnRQfH68GDRrogw8+uGJ/Pz8/ffHFFzIMQz179tSZM2eUlpamgQMHauzYsWrcuLH69OmjLVu2KDIyUpJUWlqqpKQkRUdHq3v37oqKitL8+fMr8Is5jsX45UP+N6mioiIFBgaqsLBQAQEBDh171uq9Dh3vl8bcF+W0sQGgMjp37pwOHTqk+vXrq1q1aq4up0qoXbu2pk6dqqFDh7q6lAq51jEv799vHj0HAMCEzp49qw0bNujYsWNq2rSpq8txKS5jAQBgQn/96181YMAAJScn2/2IutlwZgcAABNKTk52ypfWqyLO7AAAAFMj7AAAqhyerbl5OOJYE3YAAFWGp6enpJ9vvsXN4dKxvnTsK4J7dgAAVYa7u7uCgoKsbxf29fW1+d4UzMMwDJ09e1YFBQUKCgqSu7t7hcci7AAAqpRLnyX49ecUYE5BQUE2n6KoCMIOAKBKsVgsql27tkJCQnThwgVXlwMn8vT0vK4zOpcQdgAAVZK7u7tD/hDC/LhBGQAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmBphBwAAmJpLw05qaqratm0rf39/hYSEqE+fPsrNzbXp07lzZ1ksFptpxIgRNn3y8vLUs2dP+fr6KiQkROPGjdPFixdv5K4AAIBKysOVG1+3bp2SkpLUtm1bXbx4UX/605/UtWtX7d69W9WrV7f2GzZsmKZMmWKd9/X1tf67tLRUPXv2VFhYmL799lsdPXpUAwcOlKenp1555ZUbuj8AAKDycWnYSU9Pt5lftGiRQkJClJWVpU6dOlnbfX19FRYWdsUxvvzyS+3evVv/+te/FBoaqpYtW2rq1Kl65plnNHnyZHl5eV22TklJiUpKSqzzRUVFDtojAABQ2VSqe3YKCwslSTVq1LBpX7x4sWrWrKlmzZppwoQJOnv2rHVZZmamYmNjFRoaam3r1q2bioqKtGvXrituJzU1VYGBgdYpIiLCCXsDAAAqA5ee2fmlsrIyJScnq2PHjmrWrJm1/dFHH1XdunUVHh6u7du365lnnlFubq6WLVsmScrPz7cJOpKs8/n5+Vfc1oQJE5SSkmKdLyoqIvAAAGBSlSbsJCUlaefOnfrmm29s2ocPH279d2xsrGrXrq0uXbrowIEDatiwYYW25e3tLW9v7+uqFwAAVA2V4jLWyJEjtXLlSq1Zs0Z16tS5Zt/27dtLkvbv3y9JCgsL07Fjx2z6XJq/2n0+AADg5uHSsGMYhkaOHKnly5frq6++Uv369X9znezsbElS7dq1JUlxcXHasWOHCgoKrH1Wr16tgIAAxcTEOKVuAABQdbj0MlZSUpKWLFmijz/+WP7+/tZ7bAIDA+Xj46MDBw5oyZIl6tGjh4KDg7V9+3aNGTNGnTp1UvPmzSVJXbt2VUxMjB577DHNmDFD+fn5ev7555WUlMSlKgAA4NozOwsWLFBhYaE6d+6s2rVrW6cPPvhAkuTl5aV//etf6tq1q5o0aaKxY8eqX79++vTTT61juLu7a+XKlXJ3d1dcXJx+//vfa+DAgTbv5QEAADcvl57ZMQzjmssjIiK0bt263xynbt26+vzzzx1VFgAAMJFKcYMyAACAsxB2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqRF2AACAqTkk7Jw6dcoRwwAAADic3WFn+vTp+uCDD6zzDz/8sIKDg3Xrrbdq27ZtDi0OAADgetkddhYuXKiIiAhJ0urVq7V69Wp98cUXSkhI0Lhx4+waKzU1VW3btpW/v79CQkLUp08f5ebm2vQ5d+6ckpKSFBwcLD8/P/Xr10/Hjh2z6ZOXl6eePXvK19dXISEhGjdunC5evGjvrgEAABOyO+zk5+dbw87KlSv18MMPq2vXrho/fry2bNli11jr1q1TUlKSNm7cqNWrV+vChQvq2rWrzpw5Y+0zZswYffrpp/rwww+1bt06HTlyRH379rUuLy0tVc+ePXX+/Hl9++23evfdd7Vo0SJNnDjR3l0DAAAm5GHvCrfccosOHz6siIgIpaen66WXXpIkGYah0tJSu8ZKT0+3mV+0aJFCQkKUlZWlTp06qbCwUG+//baWLFmie++9V5KUlpam6Ohobdy4UR06dNCXX36p3bt361//+pdCQ0PVsmVLTZ06Vc8884wmT54sLy8ve3cRAACYiN1ndvr27atHH31U9913n44fP66EhARJ0r///W/ddttt11VMYWGhJKlGjRqSpKysLF24cEHx8fHWPk2aNFFkZKQyMzMlSZmZmYqNjVVoaKi1T7du3VRUVKRdu3ZdcTslJSUqKiqymQAAgDnZHXZmzZqlkSNHKiYmRqtXr5afn58k6ejRo3rqqacqXEhZWZmSk5PVsWNHNWvWTNLPl8y8vLwUFBRk0zc0NFT5+fnWPr8MOpeWX1p2JampqQoMDLROly7LAQAA87H7Mpanp6eefvrpy9rHjBlzXYUkJSVp586d+uabb65rnPKYMGGCUlJSrPNFRUUEHgAATKpC79n5+9//rjvvvFPh4eH64YcfJEmzZ8/Wxx9/XKEiRo4cqZUrV2rNmjWqU6eOtT0sLEznz5+/7D0+x44dU1hYmLXPr5/OujR/qc+veXt7KyAgwGYCAADmZHfYWbBggVJSUpSQkKBTp05Zb0oOCgrS7Nmz7RrLMAyNHDlSy5cv11dffaX69evbLG/durU8PT2VkZFhbcvNzVVeXp7i4uIkSXFxcdqxY4cKCgqsfVavXq2AgADFxMTYu3sAAMBk7A47c+fO1ZtvvqnnnntO7u7u1vY2bdpox44ddo2VlJSk9957T0uWLJG/v7/y8/OVn5+vn376SZIUGBioIUOGKCUlRWvWrFFWVpYef/xxxcXFqUOHDpKkrl27KiYmRo899pi2bdumVatW6fnnn1dSUpK8vb3t3T0AAGAydt+zc+jQIbVq1eqydm9vb5v345THggULJEmdO3e2aU9LS9PgwYMl/XxDtJubm/r166eSkhJ169ZN8+fPt/Z1d3fXypUr9eSTTyouLk7Vq1fXoEGDNGXKFPt2DAAAmJLdYad+/frKzs5W3bp1bdrT09MVHR1t11iGYfxmn2rVqmnevHmaN2/eVfvUrVtXn3/+uV3bBgAANwe7w05KSoqSkpJ07tw5GYahzZs36/3331dqaqreeustZ9QIAABQYXaHnaFDh8rHx0fPP/+8zp49q0cffVTh4eF64403NGDAAGfUCAAAUGF2h52ioiIlJiYqMTFRZ8+eVXFxsUJCQiRJ+/fvv+63KAMAADiS3U9j9ezZUyUlJZJk/cq49PMj4b++0RgAAMDV7A47fn5++t3vfqeLFy9a23JyctS5c2f169fPocUBAABcL7vDzrJly1RYWKjExEQZhqGdO3eqc+fOeuSRR/TGG284o0YAAIAKszvs+Pj46LPPPlNubq4efvhhdenSRQMHDtTMmTOdUR8AAMB1KdcNykVFRTbzbm5u+uCDD3TfffepX79+euGFF6x9+M4UAACoTMoVdoKCgmSxWC5rNwxDCxcu1F/+8hcZhiGLxWL9VhYAAEBlUK6ws2bNGmfXAQAA4BTlCjt33323s+sAAABwCrtfKihJp06d0ttvv62cnBxJUtOmTfXEE08oMDDQocUBAABcL7ufxtq6dasaNmyoWbNm6cSJEzpx4oRmzpyphg0b6rvvvnNGjQAAABVm95mdMWPG6IEHHtCbb74pD4+fV7948aKGDh2q5ORkrV+/3uFFVmUd8v5aofU2Rg53cCUAANyc7A47W7dutQk6kuTh4aHx48erTZs2Di0OAADgetl9GSsgIEB5eXmXtR8+fFj+/v4OKQoAAMBR7A47/fv315AhQ/TBBx/o8OHDOnz4sJYuXaqhQ4fqkUcecUaNAAAAFWb3ZazXXntNFotFAwcOtH4M1NPTU08++aSmTZvm8AIBAACuh91hx8vLS2+88YZSU1N14MABSVLDhg3l6+vr8OIAAACuV4XesyNJvr6+io2NdWQtAAAADleusNO3b18tWrRIAQEB6tu37zX7+vn5qWnTphoxYgQvGQQAAC5XrrATGBho/RDobwWYkpISLVy4UBs2bNAnn3xy/RUCAABch3KFnbS0tCv++2p2796ttm3bVrwqAAAAB7H70fPyaNy4sb799ltnDA0AAGAXp4Qdd3d3tWjRwhlDAwAA2MUpYQcAAKCyIOwAAABTK1fYuf3223Xy5ElJ0pQpU3T27FmnFgUAAOAo5Qo7OTk5OnPmjCTpxRdfVHFxsVOLAgAAcJRyPXresmVLPf7447rzzjtlGIZee+01+fn5XbHvxIkTHVogAADA9ShX2Fm0aJEmTZqklStXymKx6IsvvpCHx+WrWiwWwg4AAKhUyhV2GjdurKVLl0qS3NzclJGRoZCQEKcWBgAA4Ah2fwi0rKzMGXUAAAA4RYW+en7gwAHNnj1bOTk5kqSYmBiNHj1aDRs2dGhxAAAA18vu9+ysWrVKMTEx2rx5s5o3b67mzZtr06ZNatq0qVavXu2MGgEAACrM7jM7zz77rMaMGaNp06Zd1v7MM8/ovvvuc1hxAAAA18vuMzs5OTkaMmTIZe1PPPGEdu/e7ZCiAAAAHMXusFOrVi1lZ2df1p6dnc0TWgAAoNKx+zLWsGHDNHz4cB08eFB33HGHJGnDhg2aPn26UlJSHF4gAADA9bA77Lzwwgvy9/fX66+/rgkTJkiSwsPDNXnyZI0aNcrhBQIAAFwPu8OOxWLRmDFjNGbMGJ0+fVqS5O/v7/DCAAAAHKFC79m5hJADAAAqO7tvUAYAAKhKCDsAAMDUCDsAAMDU7Ao7Fy5cUJcuXbRv3z5n1QMAAOBQdoUdT09Pbd++3Vm1AAAAOJzdl7F+//vf6+2333ZGLQAAAA5nd9i5ePGiFixYoDZt2ugPf/iDUlJSbCZ7rF+/Xr169VJ4eLgsFotWrFhhs3zw4MGyWCw2U/fu3W36nDhxQomJiQoICFBQUJCGDBmi4uJie3cLAACYlN3v2dm5c6duv/12SdLevXttllksFrvGOnPmjFq0aKEnnnhCffv2vWKf7t27Ky0tzTrv7e1tszwxMVFHjx7V6tWrdeHCBT3++OMaPny4lixZYlctAADAnOwOO2vWrHHYxhMSEpSQkHDNPt7e3goLC7vispycHKWnp2vLli1q06aNJGnu3Lnq0aOHXnvtNYWHh19xvZKSEpWUlFjni4qKKrgHAACgsqvwo+f79+/XqlWr9NNPP0mSDMNwWFG/tHbtWoWEhKhx48Z68skndfz4ceuyzMxMBQUFWYOOJMXHx8vNzU2bNm266pipqakKDAy0ThEREU6pHQAAuJ7dYef48ePq0qWLoqKi1KNHDx09elSSNGTIEI0dO9ahxXXv3l1/+9vflJGRoenTp2vdunVKSEhQaWmpJCk/P18hISE263h4eKhGjRrKz8+/6rgTJkxQYWGhdTp8+LBD6wYAAJWH3WFnzJgx8vT0VF5ennx9fa3t/fv3V3p6ukOLGzBggB544AHFxsaqT58+WrlypbZs2aK1a9de17je3t4KCAiwmQAAgDnZHXa+/PJLTZ8+XXXq1LFpb9SokX744QeHFXYlDRo0UM2aNbV//35JUlhYmAoKCmz6XLx4USdOnLjqfT4AAODmYnfYOXPmjM0ZnUtOnDhx2ZNSjvaf//xHx48fV+3atSVJcXFxOnXqlLKysqx9vvrqK5WVlal9+/ZOrQUAAFQNdoedu+66S3/729+s8xaLRWVlZZoxY4buueceu8YqLi5Wdna2srOzJUmHDh1Sdna28vLyVFxcrHHjxmnjxo36/vvvlZGRod69e+u2225Tt27dJEnR0dHq3r27hg0bps2bN2vDhg0aOXKkBgwYcNUnsQAAwM3F7kfPZ8yYoS5dumjr1q06f/68xo8fr127dunEiRPasGGDXWNt3brVJiBdeinhoEGDtGDBAm3fvl3vvvuuTp06pfDwcHXt2lVTp061OYO0ePFijRw5Ul26dJGbm5v69eunOXPm2LtbAADApOwOO82aNdPevXv15z//Wf7+/iouLlbfvn2VlJRkvbxUXp07d77mI+urVq36zTFq1KjBCwQBAMBV2R12JCkwMFDPPfeco2sBAABwuAqFnZMnT+rtt99WTk6OJCkmJkaPP/64atSo4dDiAAAArpfdNyivX79e9erV05w5c3Ty5EmdPHlSc+bMUf369bV+/Xpn1AgAAFBhdp/ZSUpKUv/+/bVgwQK5u7tLkkpLS/XUU08pKSlJO3bscHiRAAAAFWX3mZ39+/dr7Nix1qAjSe7u7kpJSbG+7A8AAKCysDvs3H777dZ7dX4pJydHLVq0cEhRAAAAjlKuy1jbt2+3/nvUqFEaPXq09u/frw4dOkiSNm7cqHnz5mnatGnOqRIAAKCCyhV2WrZsKYvFYvNOnPHjx1/W79FHH1X//v0dVx0AAMB1KlfYOXTokLPrAAAAcIpyhZ26des6uw4AAACnqNBLBY8cOaJvvvlGBQUFKisrs1k2atQohxQGAADgCHaHnUWLFukPf/iDvLy8FBwcLIvFYl1msVgIOwAAoFKxO+y88MILmjhxoiZMmCA3N7ufXAcAALih7E4rZ8+e1YABAwg6AACgSrA7sQwZMkQffvihM2oBAABwOLsvY6Wmpur+++9Xenq6YmNj5enpabN85syZDisOAADgelUo7KxatUqNGzeWpMtuUAYAAKhM7A47r7/+ut555x0NHjzYCeUAAAA4lt337Hh7e6tjx47OqAUAAMDh7A47o0eP1ty5c51RCwAAgMPZfRlr8+bN+uqrr7Ry5Uo1bdr0shuUly1b5rDiAAAArpfdYScoKEh9+/Z1Ri0AAAAOZ3fYSUtLc0YdAAAATsFrkAEAgKnZfWanfv3613yfzsGDB6+rIAAAAEeyO+wkJyfbzF+4cEH//ve/lZ6ernHjxjmqLgAAAIewO+yMHj36iu3z5s3T1q1br7sgAAAAR3LYPTsJCQn66KOPHDUcAACAQzgs7Pzzn/9UjRo1HDUcAACAQ9h9GatVq1Y2NygbhqH8/Hz9+OOPmj9/vkOLAwAAuF52h50+ffrYzLu5ualWrVrq3LmzmjRp4qi6AAAAHMLusDNp0iRn1AEAAOAUvFQQAACYWrnP7Li5uV3zZYKSZLFYdPHixesuCgAAwFHKHXaWL19+1WWZmZmaM2eOysrKHFIUAACAo5Q77PTu3fuyttzcXD377LP69NNPlZiYqClTpji0OAAAgOtVoXt2jhw5omHDhik2NlYXL15Udna23n33XdWtW9fR9QEAAFwXu8JOYWGhnnnmGd12223atWuXMjIy9Omnn6pZs2bOqg8AAOC6lPsy1owZMzR9+nSFhYXp/fffv+JlLQAAgMqm3GHn2WeflY+Pj2677Ta9++67evfdd6/Yb9myZQ4rDgAA4HqVO+wMHDjwNx89BwAAqGzKHXYWLVrkxDIAAACcgzcoAwAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAAAAU3Np2Fm/fr169eql8PBwWSwWrVixwma5YRiaOHGiateuLR8fH8XHx2vfvn02fU6cOKHExEQFBAQoKChIQ4YMUXFx8Q3cCwAAUJm5NOycOXNGLVq00Lx58664fMaMGZozZ44WLlyoTZs2qXr16urWrZvOnTtn7ZOYmKhdu3Zp9erVWrlypdavX6/hw4ffqF0AAACVXLnfs+MMCQkJSkhIuOIywzA0e/ZsPf/889ZPU/ztb39TaGioVqxYoQEDBignJ0fp6enasmWL2rRpI0maO3euevTooddee03h4eE3bF8AAEDlVGnv2Tl06JDy8/MVHx9vbQsMDFT79u2VmZkpScrMzFRQUJA16EhSfHy83NzctGnTpquOXVJSoqKiIpsJAACYU6UNO/n5+ZKk0NBQm/bQ0FDrsvz8fIWEhNgs9/DwUI0aNax9riQ1NVWBgYHWKSIiwsHVAwCAyqLShh1nmjBhggoLC63T4cOHXV0SAABwkkobdsLCwiRJx44ds2k/duyYdVlYWJgKCgpsll+8eFEnTpyw9rkSb29vBQQE2EwAAMCcKm3YqV+/vsLCwpSRkWFtKyoq0qZNmxQXFydJiouL06lTp5SVlWXt89VXX6msrEzt27e/4TUDAIDKx6VPYxUXF2v//v3W+UOHDik7O1s1atRQZGSkkpOT9dJLL6lRo0aqX7++XnjhBYWHh6tPnz6SpOjoaHXv3l3Dhg3TwoULdeHCBY0cOVIDBgzgSSwAACDJxWFn69atuueee6zzKSkpkqRBgwZp0aJFGj9+vM6cOaPhw4fr1KlTuvPOO5Wenq5q1apZ11m8eLFGjhypLl26yM3NTf369dOcOXNu+L4AAIDKyWIYhuHqIlytqKhIgYGBKiwsdPj9O5lvP12h9TZG/vaLEcfcF1WhsQEAMIPy/v126ZkdXJ9Zq/c6ZVxCFADATAg7uIyzQpREkAIA3HiV9mksAAAARyDsAAAAUyPsAAAAUyPsAAAAU+MG5UqqQ95f7V6nPI+rAwBws+HMDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMDXCDgAAMLVKHXYmT54si8ViMzVp0sS6/Ny5c0pKSlJwcLD8/PzUr18/HTt2zIUVAwCAyqZShx1Jatq0qY4ePWqdvvnmG+uyMWPG6NNPP9WHH36odevW6ciRI+rbt68LqwUAAJWNh6sL+C0eHh4KCwu7rL2wsFBvv/22lixZonvvvVeSlJaWpujoaG3cuFEdOnS46pglJSUqKSmxzhcVFTm+cAAAUClU+jM7+/btU3h4uBo0aKDExETl5eVJkrKysnThwgXFx8db+zZp0kSRkZHKzMy85pipqakKDAy0ThEREU7dBwAA4DqVOuy0b99eixYtUnp6uhYsWKBDhw7prrvu0unTp5Wfny8vLy8FBQXZrBMaGqr8/PxrjjthwgQVFhZap8OHDztxLwAAgCtV6stYCQkJ1n83b95c7du3V926dfWPf/xDPj4+FR7X29tb3t7ejigRAABUcpX6zM6vBQUFKSoqSvv371dYWJjOnz+vU6dO2fQ5duzYFe/xAQAAN6cqFXaKi4t14MAB1a5dW61bt5anp6cyMjKsy3Nzc5WXl6e4uDgXVgkAACqTSn0Z6+mnn1avXr1Ut25dHTlyRJMmTZK7u7seeeQRBQYGasiQIUpJSVGNGjUUEBCgP/7xj4qLi7vmk1gAAODmUqnDzn/+8x898sgjOn78uGrVqqU777xTGzduVK1atSRJs2bNkpubm/r166eSkhJ169ZN8+fPd3HVrtMh7683dHsbI4ff0O0BAFARlTrsLF269JrLq1Wrpnnz5mnevHk3qCIAAFDVVKl7dgAAAOxF2AEAAKZWqS9joXKr2D1Crzm8DgAAroUzOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNQIOwAAwNT46jluqFmr9zpl3DH3RTllXABA1ceZHQAAYGqEHQAAYGqEHQAAYGqEHQAAYGqEHQAAYGqEHQAAYGo8eg5TcNYj7RKPtQNAVceZHQAAYGqEHQAAYGqEHQAAYGqEHQAAYGqEHQAAYGo8jYUqoUPeX+1eZ2PkcCdUAgCoajizAwAATI0zO7ihKnKGBgCA68GZHQAAYGqEHQAAYGqEHQAAYGqEHQAAYGrcoAzTqujN0L9+ZN1ZHxnlA6MAcGNwZgcAAJgaYQcAAJgal7EAE3LWpTeJy28Aqh7CDvArfJoCAMyFy1gAAMDUCDsAAMDUuIwFOECFHnNfEyzdM8HxxQAAbHBmBwAAmBpndgAXyTx4XBsvOu+pKQDAzzizAwAATM00Z3bmzZunV199Vfn5+WrRooXmzp2rdu3aubos4Joc9UkLAMDVmSLsfPDBB0pJSdHChQvVvn17zZ49W926dVNubq5CQkJcXR5gKnwrrALWpFZsPW5gBxzCFJexZs6cqWHDhunxxx9XTEyMFi5cKF9fX73zzjuuLg0AALhYlT+zc/78eWVlZWnChP/7/4Dc3NwUHx+vzMzMK65TUlKikpIS63xhYaEkqaioyOH1nfmp5Lc7AXaKzZ3r6hKuaUudx+1exxn/+6s0zpyr2HpV7DeZ99V+p4ybdO9tThlXcl7NzlQVfw9n1XzpvxuGYVyzX5UPO//73/9UWlqq0NBQm/bQ0FDt2bPniuukpqbqxRdfvKw9IiLCKTUCN58/273Gn5xQRdU3xdUFVAr834atqvh7OLvm06dPKzAw8KrLq3zYqYgJEyYoJSXFOl9WVqYTJ04oODhYFovFpm9RUZEiIiJ0+PBhBQQE3OhScRUcl8qLY1M5cVwqL45NxRmGodOnTys8PPya/ap82KlZs6bc3d117Ngxm/Zjx44pLCzsiut4e3vL29vbpi0oKOia2wkICOD/CCshjkvlxbGpnDgulRfHpmKudUbnkip/g7KXl5dat26tjIwMa1tZWZkyMjIUFxfnwsoAAEBlUOXP7EhSSkqKBg0apDZt2qhdu3aaPXu2zpw5o8cft/8mSQAAYC6mCDv9+/fXjz/+qIkTJyo/P18tW7ZUenr6ZTctV4S3t7cmTZp02WUvuBbHpfLi2FROHJfKi2PjfBbjt57XAgAAqMKq/D07AAAA10LYAQAApkbYAQAApkbYAQAApkbYuYZ58+apXr16qlatmtq3b6/Nmze7uqSbTmpqqtq2bSt/f3+FhISoT58+ys3Ntelz7tw5JSUlKTg4WH5+furXr99lL5mEc02bNk0Wi0XJycnWNo6La/z3v//V73//ewUHB8vHx0exsbHaunWrdblhGJo4caJq164tHx8fxcfHa9++fS6s+OZQWlqqF154QfXr15ePj48aNmyoqVOn2nzTiWPjRAauaOnSpYaXl5fxzjvvGLt27TKGDRtmBAUFGceOHXN1aTeVbt26GWlpacbOnTuN7Oxso0ePHkZkZKRRXFxs7TNixAgjIiLCyMjIMLZu3Wp06NDBuOOOO1xY9c1l8+bNRr169YzmzZsbo0ePtrZzXG68EydOGHXr1jUGDx5sbNq0yTh48KCxatUqY//+/dY+06ZNMwIDA40VK1YY27ZtMx544AGjfv36xk8//eTCys3v5ZdfNoKDg42VK1cahw4dMj788EPDz8/PeOONN6x9ODbOQ9i5inbt2hlJSUnW+dLSUiM8PNxITU11YVUoKCgwJBnr1q0zDMMwTp06ZXh6ehoffvihtU9OTo4hycjMzHRVmTeN06dPG40aNTJWr15t3H333daww3FxjWeeeca48847r7q8rKzMCAsLM1599VVr26lTpwxvb2/j/fffvxEl3rR69uxpPPHEEzZtffv2NRITEw3D4Ng4G5exruD8+fPKyspSfHy8tc3NzU3x8fHKzMx0YWUoLCyUJNWoUUOSlJWVpQsXLtgcqyZNmigyMpJjdQMkJSWpZ8+eNr+/xHFxlU8++URt2rTRQw89pJCQELVq1UpvvvmmdfmhQ4eUn59vc1wCAwPVvn17jouT3XHHHcrIyNDevXslSdu2bdM333yjhIQESRwbZzPFG5Qd7X//+59KS0svewNzaGio9uzZ46KqUFZWpuTkZHXs2FHNmjWTJOXn58vLy+uyD7mGhoYqPz/fBVXePJYuXarvvvtOW7ZsuWwZx8U1Dh48qAULFiglJUV/+tOftGXLFo0aNUpeXl4aNGiQ9be/0n/bOC7O9eyzz6qoqEhNmjSRu7u7SktL9fLLLysxMVGSODZORthBlZGUlKSdO3fqm2++cXUpN73Dhw9r9OjRWr16tapVq+bqcvD/lZWVqU2bNnrllVckSa1atdLOnTu1cOFCDRo0yMXV3dz+8Y9/aPHixVqyZImaNm2q7OxsJScnKzw8nGNzA3AZ6wpq1qwpd3f3y54cOXbsmMLCwlxU1c1t5MiRWrlypdasWaM6depY28PCwnT+/HmdOnXKpj/HyrmysrJUUFCg22+/XR4eHvLw8NC6des0Z84ceXh4KDQ0lOPiArVr11ZMTIxNW3R0tPLy8iTJ+tvz37Ybb9y4cXr22Wc1YMAAxcbG6rHHHtOYMWOUmpoqiWPjbISdK/Dy8lLr1q2VkZFhbSsrK1NGRobi4uJcWNnNxzAMjRw5UsuXL9dXX32l+vXr2yxv3bq1PD09bY5Vbm6u8vLyOFZO1KVLF+3YsUPZ2dnWqU2bNkpMTLT+m+Ny43Xs2PGyVzPs3btXdevWlSTVr19fYWFhNselqKhImzZt4rg42dmzZ+XmZvsn193dXWVlZZI4Nk7n6jukK6ulS5ca3t7exqJFi4zdu3cbw4cPN4KCgoz8/HxXl3ZTefLJJ43AwEBj7dq1xtGjR63T2bNnrX1GjBhhREZGGl999ZWxdetWIy4uzoiLi3Nh1TenXz6NZRgcF1fYvHmz4eHhYbz88svGvn37jMWLFxu+vr7Ge++9Z+0zbdo0IygoyPj444+N7du3G7179+bx5htg0KBBxq233mp99HzZsmVGzZo1jfHjx1v7cGych7BzDXPnzjUiIyMNLy8vo127dsbGjRtdXdJNR9IVp7S0NGufn376yXjqqaeMW265xfD19TV+97vfGUePHnVd0TepX4cdjotrfPrpp0azZs0Mb29vo0mTJsZf//pXm+VlZWXGCy+8YISGhhre3t5Gly5djNzcXBdVe/MoKioyRo8ebURGRhrVqlUzGjRoYDz33HNGSUmJtQ/HxnkshvGL1zcCAACYDPfsAAAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAAAAUyPsAKiw77//XhaLRdnZ2a4uxWrPnj3q0KGDqlWrppYtW7q6HACVAGEHqMIGDx4si8WiadOm2bSvWLFCFovFRVW51qRJk1S9enXl5ubafFTxRlq0aJGCgoJcsm0AlyPsAFVctWrVNH36dJ08edLVpTjM+fPnK7zugQMHdOedd6pu3boKDg52YFUAqirCDlDFxcfHKywsTKmpqVftM3ny5Msu6cyePVv16tWzzg8ePFh9+vTRK6+8otDQUAUFBWnKlCm6ePGixo0bpxo1aqhOnTpKS0u7bPw9e/bojjvuULVq1dSsWTOtW7fOZvnOnTuVkJAgPz8/hYaG6rHHHtP//vc/6/LOnTtr5MiRSk5OVs2aNdWtW7cr7kdZWZmmTJmiOnXqyNvbWy1btlR6erp1ucViUVZWlqZMmSKLxaLJkydfcZx//vOfio2NlY+Pj4KDgxUfH68zZ85Yl7/11luKjo5WtWrV1KRJE82fP9+67NKlu2XLlumee+6Rr6+vWrRooczMTEnS2rVr9fjjj6uwsFAWi8WmjpKSEj399NO69dZbVb16dbVv315r1661jn3pjNCqVasUHR0tPz8/de/eXUePHrWp/5133lHTpk3l7e2t2rVra+TIkdZlp06d0tChQ1WrVi0FBATo3nvv1bZt26zLt23bpnvuuUf+/v4KCAhQ69attXXr1iv+ToBpuPpLpAAqbtCgQUbv3r2NZcuWGdWqVTMOHz5sGIZhLF++3Pjl/7wnTZpktGjRwmbdWbNmGXXr1rUZy9/f30hKSjL27NljvP3224Yko1u3bsbLL79s7N2715g6darh6elp3c6hQ4cMSUadOnWMf/7zn8bu3buNoUOHGv7+/sb//vc/wzAM4+TJk0atWrWMCRMmGDk5OcZ3331n3HfffcY999xj3fbdd99t+Pn5GePGjTP27Nlj7Nmz54r7O3PmTCMgIMB4//33jT179hjjx483PD09jb179xqGYRhHjx41mjZtaowdO9Y4evSocfr06cvGOHLkiOHh4WHMnDnTOHTokLF9+3Zj3rx51r7vvfeeUbt2beOjjz4yDh48aHz00UdGjRo1jEWLFtnsc5MmTYyVK1caubm5xoMPPmjUrVvXuHDhglFSUmLMnj3bCAgIMI4ePWpTx9ChQ4077rjDWL9+vbF//37j1VdfNby9va31p6WlGZ6enkZ8fLyxZcsWIysry4iOjjYeffRRa/3z5883qlWrZsyePdvIzc01Nm/ebMyaNcu6PD4+3ujVq5exZcsWY+/evcbYsWON4OBg4/jx44ZhGEbTpk2N3//+90ZOTo6xd+9e4x//+IeRnZ19xd8bMAvCDlCFXQo7hmEYHTp0MJ544gnDMCoedurWrWuUlpZa2xo3bmzcdddd1vmLFy8a1atXN95//33DMP7vD/+0adOsfS5cuGDUqVPHmD59umEYhjF16lSja9euNts+fPiwIcnIzc01DOPnsNOqVavf3N/w8HDj5Zdftmlr27at8dRTT1nnW7RoYUyaNOmqY2RlZRmSjO+///6Kyxs2bGgsWbLEpm3q1KlGXFycYRj/t89vvfWWdfmuXbsMSUZOTo5hGD+HlsDAQJsxfvjhB8Pd3d3473//a9PepUsXY8KECdb1JBn79++3Lp83b54RGhpq8xs899xzV6z966+/NgICAoxz585dtk9/+ctfDMMwDH9/f2twA24WHi46oQTAwaZPn657771XTz/9dIXHaNq0qdzc/u/qdmhoqJo1a2add3d3V3BwsAoKCmzWi4uLs/7bw8NDbdq0UU5OjqSfL5usWbNGfn5+l23vwIEDioqKkiS1bt36mrUVFRXpyJEj6tixo017x44dbS7T/JYWLVqoS5cuio2NVbdu3dS1a1c9+OCDuuWWW3TmzBkdOHBAQ4YM0bBhw6zrXLx4UYGBgTbjNG/e3Prv2rVrS5IKCgrUpEmTK253x44dKi0tte7vJSUlJTb3Fvn6+qphw4Y2Y1/6vQsKCnTkyBF16dLlitvYtm2biouLL7tX6aefftKBAwckSSkpKRo6dKj+/ve/Kz4+Xg899JDN9gAzIuwAJtGpUyd169ZNEyZM0ODBg22Wubm5yTAMm7YLFy5cNoanp6fNvMViuWJbWVlZuesqLi5Wr169NH369MuWXQoJklS9evVyj3k93N3dtXr1an377bf68ssvNXfuXD333HPatGmTfH19JUlvvvmm2rdvf9l6v/TL3+XSk2/X+l2Ki4vl7u6urKysy8b6ZRC80u996dj5+Phcc9+Ki4tVu3Ztm/uALrn0dNjkyZP16KOP6rPPPtMXX3yhSZMmaenSpfrd7353zbGBqoywA5jItGnT1LJlSzVu3NimvVatWsrPz5dhGNY/zI58N87GjRvVqVMnST+fBcnKyrLeNHv77bfro48+Ur169eThUfH/5AQEBCg8PFwbNmzQ3XffbW3fsGGD2rVrZ9dYFotFHTt2VMeOHTVx4kTVrVtXy5cvV0pKisLDw3Xw4EElJiZWuFYvLy+VlpbatLVq1UqlpaUqKCjQXXfdVaFx/f39Va9ePWVkZOiee+65bPntt9+u/Px8eXh42Nx8/mtRUVGKiorSmDFj9MgjjygtLY2wA1Mj7AAmEhsbq8TERM2ZM8emvXPnzvrxxx81Y8YMPfjgg0pPT9cXX3yhgIAAh2x33rx5atSokaKjozVr1iydPHlSTzzxhCQpKSlJb775ph555BGNHz9eNWrU0P79+7V06VK99dZbl53luJZx48Zp0qRJatiwoVq2bKm0tDRlZ2dr8eLF5R5j06ZNysjIUNeuXRUSEqJNmzbpxx9/VHR0tCTpxRdf1KhRoxQYGKju3burpKREW7du1cmTJ5WSklKubdSrV0/FxcXKyMhQixYt5Ovrq6ioKCUmJmrgwIF6/fXX1apVK/3444/KyMhQ8+bN1bNnz3KNPXnyZI0YMUIhISFKSEjQ6dOntWHDBv3xj39UfHy84uLi1KdPH82YMUNRUVE6cuSIPvvsM/3ud79T06ZNNW7cOD344IOqX7++/vOf/2jLli3q169fuX8/oCri0XPAZKZMmXLZ5ZTo6GjNnz9f8+bNU4sWLbR58+brurfn16ZNm6Zp06apRYsW+uabb/TJJ5+oZs2akmQ9G1NaWqquXbsqNjZWycnJCgoKsrk/qDxGjRqllJQUjR07VrGxsUpPT9cnn3yiRo0alXuMgIAArV+/Xj169FBUVJSef/55vf7660pISJAkDR06VG+99ZbS0tIUGxuru+++W4sWLVL9+vXLvY077rhDI0aMUP/+/VWrVi3NmDFDkpSWlqaBAwdq7Nixaty4sfr06aMtW7YoMjKy3GMPGjRIs2fP1vz589W0aVPdf//92rdvn6Sfz1h9/vnn6tSpkx5//HFFRUVpwIAB+uGHHxQaGip3d3cdP35cAwcOVFRUlB5++GElJCToxRdfLPf2garIYvz6Qj4AAICJcGYHAACYGmEHAACYGmEHAACYGmEHAACYGmEHAACYGmEHAACYGmEHAACYGmEHAACYGmEHAACYGmEHAACYGmEHAACY2v8D2+UKdWiDjq0AAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# plot avarage number of sentences in jokes\n",
"good_sent = df_good['tokens'].apply(len)\n",
"bad_sent = df_bad['tokens'].apply(len)\n",
"\n",
"# bigger than 1\n",
"good_sent = good_sent[good_sent > 2]\n",
"bad_sent = bad_sent[bad_sent > 2]\n",
"\n",
"# print how many jokes have more than 1 sentence relative to the total number of jokes\n",
"print('good jokes with more than 1 sentence:', good_sent.shape[0], 'total:', df_good.shape[0])\n",
"print('bad jokes with more than 1 sentence:', bad_sent.shape[0], 'total:', df_bad.shape[0])\n",
"\n",
"plt.hist(good_sent, bins=20, alpha=0.5, label='good jokes')\n",
"plt.hist(bad_sent, bins=20, alpha=0.5, label='bad jokes')\n",
"plt.xlabel('Number of sentences')\n",
"plt.ylabel('Number of jokes')\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Find Patterns\n",
"use tok_title and tok_body for it"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Oneliner"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Questions -> Answer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Wordplay "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Dialog\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Knock-Knock Jokes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}