{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import yaml\n",
    "import json\n",
    "import collections\n",
    "import random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "Match = collections.namedtuple('Match', 'text, rule, bindings')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "# def read_rules_y(rules_file):\n",
    "#     with open(rules_file) as f:\n",
    "#         rules = [{'pattern': r['pattern'].split(),\n",
    "#                  'responses': [t.split() for t in r['responses']]}\n",
    "#             for r in yaml.safe_load(f)]\n",
    "#     return rules\n",
    "\n",
    "# all_rules_y = read_rules_y('rules.yaml')\n",
    "# all_rules_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'pattern': ['?X', 'hello', '?Y'],\n",
       "  'responses': [['how',\n",
       "    'do',\n",
       "    'you',\n",
       "    'do.',\n",
       "    'please',\n",
       "    'state',\n",
       "    'your',\n",
       "    'problem']]},\n",
       " {'pattern': ['?X', 'computer', '?Y'],\n",
       "  'responses': [['do', 'computers', 'worry', 'you'],\n",
       "   ['what', 'do', 'you', 'think', 'about', 'machines'],\n",
       "   ['why', 'do', 'you', 'mention', 'computers'],\n",
       "   ['what',\n",
       "    'do',\n",
       "    'you',\n",
       "    'think',\n",
       "    'machines',\n",
       "    'have',\n",
       "    'to',\n",
       "    'do',\n",
       "    'with',\n",
       "    'your',\n",
       "    'problem']]},\n",
       " {'pattern': ['?X', 'name', '?Y'],\n",
       "  'responses': [['i', 'am', 'not', 'interested', 'in', 'names']]},\n",
       " {'pattern': ['?X', 'sorry', '?Y'],\n",
       "  'responses': [['please', \"don't\", 'apologize'],\n",
       "   ['apologies', 'are', 'not', 'necessary'],\n",
       "   ['what', 'feelings', 'do', 'you', 'have', 'when', 'you', 'apologize']]},\n",
       " {'pattern': ['?X', 'i', 'remember', '?Y'],\n",
       "  'responses': [['do', 'you', 'often', 'think', 'of', '?Y'],\n",
       "   ['does', 'thinking', 'of', '?Y', 'bring', 'anything', 'else', 'to', 'mind'],\n",
       "   ['what', 'else', 'do', 'you', 'remember?'],\n",
       "   ['why', 'do', 'you', 'recall', '?Y', 'right', 'now'],\n",
       "   ['what',\n",
       "    'in',\n",
       "    'this',\n",
       "    'present',\n",
       "    'situation',\n",
       "    'reminds',\n",
       "    'you',\n",
       "    'of',\n",
       "    '?Y'],\n",
       "   ['what', 'is', 'the', 'connection', 'between', 'me', 'and', '?Y']]},\n",
       " {'pattern': ['?X', 'do', 'you', 'remember', '?Y'],\n",
       "  'responses': [['did', 'you', 'think', 'i', 'would', 'forget', '?Y'],\n",
       "   ['why', 'do', 'you', 'think', 'i', 'should', 'recall', '?Y'],\n",
       "   ['what', 'about', '?Y'],\n",
       "   ['you', 'mentioned', '?Y']]},\n",
       " {'pattern': ['?X', 'if', '?Y'],\n",
       "  'responses': [['do',\n",
       "    'you',\n",
       "    'really',\n",
       "    'think',\n",
       "    'it',\n",
       "    'is',\n",
       "    'likely',\n",
       "    'that',\n",
       "    '?Y'],\n",
       "   ['do', 'you', 'wish', 'that', '?Y'],\n",
       "   ['what', 'do', 'you', 'think', 'about', '?Y'],\n",
       "   ['really', '--', 'if', '?Y']]},\n",
       " {'pattern': ['?X', 'i', 'dreamt', '?Y'],\n",
       "  'responses': [['really', '--', '?Y'],\n",
       "   ['have',\n",
       "    'you',\n",
       "    'ever',\n",
       "    'fantasized',\n",
       "    '?Y',\n",
       "    'while',\n",
       "    'you',\n",
       "    'were',\n",
       "    'awake'],\n",
       "   ['have', 'you', 'dreamt', '?Y', 'before']]},\n",
       " {'pattern': ['?X', 'i', 'dreamed', '?Y'],\n",
       "  'responses': [['really', '--', '?Y'],\n",
       "   ['have',\n",
       "    'you',\n",
       "    'ever',\n",
       "    'fantasized',\n",
       "    '?Y',\n",
       "    'while',\n",
       "    'you',\n",
       "    'were',\n",
       "    'awake'],\n",
       "   ['have', 'you', 'dreamed', '?Y', 'before']]},\n",
       " {'pattern': ['?X', 'dream', '?Y'],\n",
       "  'responses': [['what', 'does', 'this', 'dream', 'suggest', 'to', 'you'],\n",
       "   ['do', 'you', 'dream', 'often'],\n",
       "   ['what', 'persons', 'appear', 'in', 'your', 'dreams'],\n",
       "   [\"don't\",\n",
       "    'you',\n",
       "    'believe',\n",
       "    'that',\n",
       "    'dream',\n",
       "    'has',\n",
       "    'to',\n",
       "    'do',\n",
       "    'with',\n",
       "    'your',\n",
       "    'problem']]},\n",
       " {'pattern': ['?X', 'my', 'mother', '?Y'],\n",
       "  'responses': [['who', 'else', 'is', 'in', 'your', 'family', '?Y'],\n",
       "   ['tell', 'me', 'more', 'about', 'your', 'family']]},\n",
       " {'pattern': ['?X', 'my', 'father', '?Y'],\n",
       "  'responses': [['your', 'father'],\n",
       "   ['does', 'he', 'influence', 'you', 'strongly'],\n",
       "   ['what',\n",
       "    'else',\n",
       "    'comes',\n",
       "    'to',\n",
       "    'mind',\n",
       "    'when',\n",
       "    'you',\n",
       "    'think',\n",
       "    'of',\n",
       "    'your',\n",
       "    'father']]},\n",
       " {'pattern': ['?X', 'i', 'want', '?Y'],\n",
       "  'responses': [['what', 'would', 'it', 'mean', 'if', 'you', 'got', '?Y'],\n",
       "   ['why', 'do', 'you', 'want', '?Y'],\n",
       "   ['suppose', 'you', 'got', '?Y', 'soon']]},\n",
       " {'pattern': ['?X', 'i', 'am', 'glad', '?Y'],\n",
       "  'responses': [['how', 'have', 'i', 'helped', 'you', 'to', 'be', '?Y'],\n",
       "   ['what', 'makes', 'you', 'happy', 'just', 'now'],\n",
       "   ['can', 'you', 'explain', 'why', 'you', 'are', 'suddenly', '?Y']]},\n",
       " {'pattern': ['?X', 'i', 'am', 'happy', '?Y'],\n",
       "  'responses': [['how', 'have', 'i', 'helped', 'you', 'to', 'be', '?Y'],\n",
       "   ['what', 'makes', 'you', 'glad', 'just', 'now'],\n",
       "   ['can', 'you', 'explain', 'why', 'you', 'are', 'suddenly', '?Y']]},\n",
       " {'pattern': ['?X', 'i', 'am', 'sad', '?Y'],\n",
       "  'responses': [['i', 'am', 'sorry', 'to', 'hear', 'you', 'are', 'depressed'],\n",
       "   [\"i'm\", 'sure', \"it's\", 'not', 'pleasant', 'to', 'be', 'sad']]},\n",
       " {'pattern': ['?X', 'i', 'am', 'unhappy', '?Y'],\n",
       "  'responses': [['i', 'am', 'sorry', 'to', 'hear', 'you', 'are', 'depressed'],\n",
       "   [\"i'm\", 'sure', \"it's\", 'not', 'pleasant', 'to', 'be', 'unhappy']]},\n",
       " {'pattern': ['?X', 'are', 'like', '?Y'],\n",
       "  'responses': [['what',\n",
       "    'resemblance',\n",
       "    'do',\n",
       "    'you',\n",
       "    'see',\n",
       "    'between',\n",
       "    '?X',\n",
       "    'and',\n",
       "    '?Y']]},\n",
       " {'pattern': ['?X', 'is', 'like', '?Y'],\n",
       "  'responses': [['in',\n",
       "    'what',\n",
       "    'way',\n",
       "    'is',\n",
       "    'it',\n",
       "    'that',\n",
       "    '?X',\n",
       "    'is',\n",
       "    'like',\n",
       "    '?Y'],\n",
       "   ['what', 'resemblence', 'do', 'you', 'see'],\n",
       "   ['could', 'there', 'really', 'be', 'some', 'connection'],\n",
       "   ['how']]},\n",
       " {'pattern': ['?X', 'alike', '?Y'],\n",
       "  'responses': [['in', 'what', 'way'],\n",
       "   ['what', 'similarities', 'are', 'there']]},\n",
       " {'pattern': ['?X', 'same', '?Y'],\n",
       "  'responses': [['what', 'other', 'connections', 'do', 'you', 'see']]},\n",
       " {'pattern': ['?X', 'i', 'was', '?Y'],\n",
       "  'responses': [['were', 'you', 'really'],\n",
       "   ['perhaps', 'i', 'already', 'knew', 'you', 'were', '?Y'],\n",
       "   ['why', 'do', 'you', 'tell', 'me', 'you', 'were', '?Y', 'now']]},\n",
       " {'pattern': ['?X', 'was', 'i', '?Y'],\n",
       "  'responses': [['what', 'if', 'you', 'were', '?Y'],\n",
       "   ['do', 'you', 'think', 'you', 'were', '?Y'],\n",
       "   ['what', 'would', 'it', 'mean', 'if', 'you', 'were', '?Y']]},\n",
       " {'pattern': ['?X', 'i', 'am', '?Y'],\n",
       "  'responses': [['in', 'what', 'way', 'are', 'you', '?Y'],\n",
       "   ['do', 'you', 'want', 'to', 'be', '?Y']]},\n",
       " {'pattern': ['?X', 'am', 'i', '?Y'],\n",
       "  'responses': [['do', 'you', 'believe', 'you', 'are', '?Y'],\n",
       "   ['would', 'you', 'want', 'to', 'be', '?Y'],\n",
       "   ['you', 'wish', 'i', 'would', 'tell', 'you', 'you', 'are', '?Y'],\n",
       "   ['what', 'would', 'it', 'mean', 'if', 'you', 'were', '?Y']]},\n",
       " {'pattern': ['?X', 'am', '?Y'],\n",
       "  'responses': [['why', 'do', 'you', 'say', '\"am\"'],\n",
       "   ['i', \"don't\", 'understand', 'that']]},\n",
       " {'pattern': ['?X', 'are', 'you', '?Y'],\n",
       "  'responses': [['why',\n",
       "    'are',\n",
       "    'you',\n",
       "    'interested',\n",
       "    'in',\n",
       "    'whether',\n",
       "    'i',\n",
       "    'am',\n",
       "    '?Y',\n",
       "    'or',\n",
       "    'not'],\n",
       "   ['would', 'you', 'prefer', 'it', 'if', 'i', \"weren't\", '?Y'],\n",
       "   ['perhaps', 'i', 'am', '?Y', 'in', 'your', 'fantasies']]},\n",
       " {'pattern': ['?X', 'you', 'are', '?Y'],\n",
       "  'responses': [['what', 'makes', 'you', 'think', 'i', 'am', '?Y']]},\n",
       " {'pattern': ['?X', 'because', '?Y'],\n",
       "  'responses': [['is', 'that', 'the', 'real', 'reason'],\n",
       "   ['what', 'other', 'reason', 'might', 'there', 'be'],\n",
       "   ['does', 'that', 'reason', 'seem', 'to', 'explain', 'anything', 'else']]},\n",
       " {'pattern': ['?X', 'were', 'you', '?Y'],\n",
       "  'responses': [['perhaps', 'i', 'was', '?Y'],\n",
       "   ['what', 'do', 'you', 'think'],\n",
       "   ['what', 'if', 'i', 'had', 'been', '?Y']]},\n",
       " {'pattern': ['?X', 'i', \"can't\", '?Y'],\n",
       "  'responses': [['maybe', 'you', 'could', '?Y', 'now'],\n",
       "   ['what', 'if', 'you', 'could', '?Y']]},\n",
       " {'pattern': ['?X', 'i', 'feel', '?Y'],\n",
       "  'responses': [['do', 'you', 'often', 'feel', '?Y']]},\n",
       " {'pattern': ['?X', 'i', 'felt', '?Y'],\n",
       "  'responses': [['what', 'other', 'feelings', 'do', 'you', 'have']]},\n",
       " {'pattern': ['?X', 'i', '?Y', 'you', '?Z'],\n",
       "  'responses': [['perhaps',\n",
       "    'in',\n",
       "    'your',\n",
       "    'fantasies',\n",
       "    'we',\n",
       "    '?Y',\n",
       "    'each',\n",
       "    'other']]},\n",
       " {'pattern': ['?X', 'why', \"don't\", 'you', '?Y'],\n",
       "  'responses': [['should', 'you', '?Y', 'yourself'],\n",
       "   ['do', 'you', 'believe', 'i', \"don't\", '?Y'],\n",
       "   ['perhaps', 'i', 'will', '?Y', 'in', 'good', 'time']]},\n",
       " {'pattern': ['?X', 'yes', '?Y'],\n",
       "  'responses': [['you', 'seem', 'quite', 'positive'],\n",
       "   ['you', 'are', 'sure'],\n",
       "   ['i', 'understand']]},\n",
       " {'pattern': ['?X', 'no', '?Y'],\n",
       "  'responses': [['why', 'not'],\n",
       "   ['you', 'are', 'being', 'a', 'bit', 'negative'],\n",
       "   ['are', 'you', 'saying', '\"no\"', 'just', 'to', 'be', 'negative']]},\n",
       " {'pattern': ['?X', 'someone', '?Y'],\n",
       "  'responses': [['can', 'you', 'be', 'more', 'specific']]},\n",
       " {'pattern': ['?X', 'everyone', '?Y'],\n",
       "  'responses': [['surely', 'not', 'everyone'],\n",
       "   ['can', 'you', 'think', 'of', 'anyone', 'in', 'particular'],\n",
       "   ['who', 'for', 'example'],\n",
       "   ['you', 'are', 'thinking', 'of', 'a', 'special', 'person']]},\n",
       " {'pattern': ['?X', 'always', '?Y'],\n",
       "  'responses': [['can', 'you', 'think', 'of', 'a', 'specific', 'example'],\n",
       "   ['when'],\n",
       "   ['what', 'incident', 'are', 'you', 'thinking', 'of'],\n",
       "   ['really', '--', 'always']]},\n",
       " {'pattern': ['?X', 'what', '?Y'],\n",
       "  'responses': [['why', 'do', 'you', 'ask'],\n",
       "   ['does', 'that', 'question', 'interest', 'you'],\n",
       "   ['what', 'is', 'it', 'you', 'really', 'want', 'to', 'know'],\n",
       "   ['what', 'do', 'you', 'think'],\n",
       "   ['what', 'comes', 'to', 'your', 'mind', 'when', 'you', 'ask', 'that']]},\n",
       " {'pattern': ['?X', 'perhaps', '?Y'],\n",
       "  'responses': [['you', 'do', 'not', 'seem', 'quite', 'certain']]},\n",
       " {'pattern': ['?X', 'are', '?Y'],\n",
       "  'responses': [['do', 'you', 'think', 'they', 'might', 'not', 'be', '?Y'],\n",
       "   ['possibly', 'they', 'are', '?Y']]},\n",
       " {'pattern': ['?X'],\n",
       "  'responses': [['very', 'interesting'],\n",
       "   ['i', 'am', 'not', 'sure', 'i', 'understand', 'you', 'fully'],\n",
       "   ['what', 'does', 'that', 'suggest', 'to', 'you'],\n",
       "   ['please', 'continue'],\n",
       "   ['go', 'on'],\n",
       "   ['do',\n",
       "    'you',\n",
       "    'feel',\n",
       "    'strongly',\n",
       "    'about',\n",
       "    'discussing',\n",
       "    'such',\n",
       "    'things']]}]"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def read_rules(rules_file):\n",
    "    with open(rules_file) as f:\n",
    "        rules = [{'pattern': r['pattern'].split(),\n",
    "                 'responses': [t.split() for t in r['responses']]}\n",
    "            for r in json.load(f)]\n",
    "    return rules\n",
    "\n",
    "all_rules = read_rules('rules.json')\n",
    "all_rules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> hello there\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "['hello', 'there']"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "i = input(\"> \")\n",
    "i.split()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "def match(text, rule):\n",
    "    return all_matches([Match(text, rule, {})])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "def all_matches(matches):\n",
    "    successes = []\n",
    "    while matches:\n",
    "        # print(matches, successes)\n",
    "        current = matches[0]\n",
    "        new_matches = []\n",
    "        if successful_match(current):\n",
    "            successes += [current.bindings]\n",
    "        elif current.rule:\n",
    "            new_matches = match_item(current.text, current.rule, current.bindings)\n",
    "        matches = matches[1:] + new_matches\n",
    "    return successes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_var(word):\n",
    "    return word[0] == '?'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "def successful_match(match):\n",
    "    return match.text == [] and match.rule == []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "def splits(item):\n",
    "    return [(item[:i], item[i:]) for i in range(len(item)+1)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('', 'harry'),\n",
       " ('h', 'arry'),\n",
       " ('ha', 'rry'),\n",
       " ('har', 'ry'),\n",
       " ('harr', 'y'),\n",
       " ('harry', '')]"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "splits(\"harry\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "def match_item(text, rule, bindings):\n",
    "    r0 = rule[0]\n",
    "    if is_var(r0):\n",
    "        if r0 in bindings:\n",
    "            # already seen this variable\n",
    "            if text[:len(bindings[r0])] == bindings[r0]:\n",
    "                return [Match(text[(len(bindings[r0])):], rule[1:], bindings)]\n",
    "            else:\n",
    "                return []\n",
    "        else:\n",
    "            # not seen this variable yet\n",
    "            matches = []\n",
    "            for pre, suf in splits(text):\n",
    "                new_bindings = bindings.copy()\n",
    "                new_bindings[r0] = pre\n",
    "                matches += [Match(suf, rule[1:], new_bindings)]\n",
    "            return matches\n",
    "    elif text and text[0] == r0:\n",
    "        return [Match(text[1:], rule[1:], bindings)]\n",
    "    else:\n",
    "        return []\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': ['fred'], '?Y': ['jane']}]"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('fred hello jane'.split(), '?X hello ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': [], '?Y': ['jane']}]"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('hello jane'.split(), '?X hello ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': ['fred'], '?Y': []}]"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('fred hello'.split(), '?X hello ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': [], '?Y': []}]"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('hello'.split(), '?X hello ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('fred jane'.split(), '?X hello ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': ['fred']}]"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('fred hello'.split(), '?X hello'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('hello fred'.split(), '?X hello'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': ['yes'], '?Y': ['rain']}]"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('yes i remember rain'.split(), '?X i remember ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': ['no'], '?Y': ['rain']}]"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match('no i remember rain'.split(), '?X i remember ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match(\"no remember rain\".split(), '?X i remember ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': [], '?Y': ['rain']}]"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match(\"i remember rain\".split(), '?X i remember ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': [], '?Y': ['hello', 'there', 'hello']},\n",
       " {'?X': ['hello'], '?Y': ['there']}]"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match(\"hello there hello\".split(), '?X ?Y ?X'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': ['hello']}]"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match(\"hello there hello\".split(), '?X there ?X'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': [], '?Y': ['hello', 'hello', 'hello']},\n",
       " {'?X': ['hello'], '?Y': ['hello', 'hello']},\n",
       " {'?X': ['hello', 'hello'], '?Y': ['hello']},\n",
       " {'?X': ['hello', 'hello', 'hello'], '?Y': []}]"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match(\"hello hello hello\".split(), '?X ?Y'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'?X': [], '?Y': ['hello', 'hello', 'hello']},\n",
       " {'?X': ['hello'], '?Y': ['hello']}]"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match(\"hello hello hello\".split(), '?X ?Y ?X'.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "def candidate_rules(rules, comment):\n",
    "    return [(rule, bindings) \n",
    "            for rule in rules \n",
    "            for bindings in match(comment, rule['pattern'])]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[({'pattern': ['?X', 'i', 'remember', '?Y'],\n",
       "   'responses': [['do', 'you', 'often', 'think', 'of', '?Y'],\n",
       "    ['does',\n",
       "     'thinking',\n",
       "     'of',\n",
       "     '?Y',\n",
       "     'bring',\n",
       "     'anything',\n",
       "     'else',\n",
       "     'to',\n",
       "     'mind'],\n",
       "    ['what', 'else', 'do', 'you', 'remember?'],\n",
       "    ['why', 'do', 'you', 'recall', '?Y', 'right', 'now'],\n",
       "    ['what',\n",
       "     'in',\n",
       "     'this',\n",
       "     'present',\n",
       "     'situation',\n",
       "     'reminds',\n",
       "     'you',\n",
       "     'of',\n",
       "     '?Y'],\n",
       "    ['what', 'is', 'the', 'connection', 'between', 'me', 'and', '?Y']]},\n",
       "  {'?X': [], '?Y': ['rain']}),\n",
       " ({'pattern': ['?X'],\n",
       "   'responses': [['very', 'interesting'],\n",
       "    ['i', 'am', 'not', 'sure', 'i', 'understand', 'you', 'fully'],\n",
       "    ['what', 'does', 'that', 'suggest', 'to', 'you'],\n",
       "    ['please', 'continue'],\n",
       "    ['go', 'on'],\n",
       "    ['do',\n",
       "     'you',\n",
       "     'feel',\n",
       "     'strongly',\n",
       "     'about',\n",
       "     'discussing',\n",
       "     'such',\n",
       "     'things']]},\n",
       "  {'?X': ['i', 'remember', 'rain']})]"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "candidate_rules(all_rules, \"i remember rain\".split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fill(response, bindings):\n",
    "    filled_response = []\n",
    "    for w in response:\n",
    "        if is_var(w):\n",
    "            if w in bindings:\n",
    "                filled_response += bindings[w]\n",
    "            else:\n",
    "                filled_response += ['MISSING']\n",
    "        else:\n",
    "            filled_response += [w]\n",
    "    return filled_response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'do you often think of rain'"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bs = match('yes i remember rain'.split(), '?X i remember ?Y'.split())[0]\n",
    "fr = fill(['do', 'you', 'often', 'think', 'of', '?Y'], bs)\n",
    "' '.join(fr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [],
   "source": [
    "pronoun_swaps = {\n",
    "    'i': 'you',\n",
    "    'me': 'you',\n",
    "    'my': 'your',\n",
    "    'mine': 'yours',\n",
    "    'am': 'are'\n",
    "}\n",
    "\n",
    "def pronoun_person_swap(bindings):\n",
    "    def swapped(words):\n",
    "        sw = []\n",
    "        for w in words:\n",
    "            if w in pronoun_swaps:\n",
    "                sw += [pronoun_swaps[w]]\n",
    "            else:\n",
    "                sw += [w]\n",
    "        return sw\n",
    "    \n",
    "    return {var: swapped(bindings[var]) for var in bindings}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'?X': ['your', 'father'], '?Y': ['you', 'are', 'your', 'brother', 'keeper']}"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pronoun_person_swap({'?X': ['my', 'father'], '?Y': 'i am my brother keeper'.split()})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [],
   "source": [
    "def respond(rule, bindings):\n",
    "    return fill(random.choice(rule['responses']), bindings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['what', 'is', 'the', 'connection', 'between', 'me', 'and', 'rain']"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r0, b0 = candidate_rules(all_rules, \"i remember rain\".split())[0]\n",
    "respond(r0, b0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [],
   "source": [
    "def eliza_loop():\n",
    "    print(\"Hello. I'm Eliza. What seems to be the problem?\")\n",
    "    while True:\n",
    "        c = input(\"> \")\n",
    "        if c.strip() in 'quit halt exit stop'.split(): break\n",
    "        comment = c.split()\n",
    "        rule, bindings = candidate_rules(all_rules, comment)[0]\n",
    "        swapped_bindings = pronoun_person_swap(bindings)\n",
    "        print(' '.join(respond(rule, swapped_bindings)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello. I'm Eliza. What seems to be the problem?\n",
      "> hello\n",
      "how do you do. please state your problem\n",
      "> i am sad about life\n",
      "i'm sure it's not pleasant to be sad\n",
      "> it isn't\n",
      "very interesting\n",
      "> are you happy\n",
      "perhaps i am happy in your fantasies\n",
      "> quit\n"
     ]
    }
   ],
   "source": [
    "eliza_loop()"
   ]
  },
  {
   "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.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}