{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "D = {(a, b) for a in range(2, 100) for b in range(a + 1, 100)}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = lambda tup: tup[0] + tup[1]\n",
    "p = lambda tup: tup[0] * tup[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# image(fun, dom) will generate the image of a function as a dictionary \n",
    "# and record the information of preimage at the same time: a key is an\n",
    "# element in the image, and its value is the preimage set of this key\n",
    "\n",
    "def image(fun, dom):\n",
    "    ima = dict([])\n",
    "    for d in dom:\n",
    "        f = fun(d)\n",
    "        if f in ima:\n",
    "            ima[f] = ima[f].union({d})\n",
    "        else:\n",
    "            ima[f] = {d}\n",
    "    return ima"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = image(s, D)\n",
    "Y = image(p, D)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "X1 = {m : X[m] for m in X if len(X[m]) > 1}\n",
    "Y1 = {n : Y[n] for n in Y if len(Y[n]) > 1}\n",
    "D1 = {d for n in Y1 for d in Y1[n]}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "X2 = {m : X1[m] for m in X1 if X1[m].issubset(D1)}\n",
    "D2 = {d for m in X2 for d in X2[m]}\n",
    "Y2 = image(p, D2)\n",
    "print(sorted(X2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "Y3 = {n : Y2[n] for n in Y2 if len(Y2[n]) == 1}\n",
    "D3 = {d for n in Y3 for d in Y3[n]}\n",
    "X3 = image(s, D3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "X4 = {m : X3[m] for m in X3 if len(X3[m]) == 1}\n",
    "D4 = {d for m in X4 for d in X4[m]}\n",
    "Y4 = image(p, D4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "({17: {(4, 13)}}, {52: {(4, 13)}})"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(X4, Y4)"
   ]
  }
 ],
 "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": 2
}