{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f7006041",
   "metadata": {},
   "source": [
    "## Εισαγωγή στα αντικείμενα"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "596dc977",
   "metadata": {},
   "outputs": [],
   "source": [
    "class person:\n",
    "    def __init__(self, name, phone):\n",
    "        self.name = name\n",
    "        self.phone = phone\n",
    "    \n",
    "p = person(\"Nikos\", \"123\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "db747dbb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<__main__.person at 0x236da3686e0>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cbd43f6b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<__main__.person object at 0x00000236da3686e0>\n"
     ]
    }
   ],
   "source": [
    "print(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1dc3b1b2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Nikos'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4bc67074",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'123'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.phone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b5303dc9",
   "metadata": {},
   "outputs": [],
   "source": [
    "p.name = \"John\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ccf791ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<__main__.person at 0x236da3686e0>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "ed0f2986",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'John'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "91c579e2",
   "metadata": {},
   "outputs": [],
   "source": [
    "p.foo = \"bar\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "01fcad1f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'bar'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.foo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "0c3db58d",
   "metadata": {},
   "outputs": [],
   "source": [
    "class person:\n",
    "    def __init__(self, name, phone):\n",
    "        self.name = name\n",
    "        self.phone = phone\n",
    "    def set_phone(self, phone):\n",
    "        self.phone = phone\n",
    "    \n",
    "p = person(\"Nikos\", \"123\")\n",
    "p.set_phone(\"456\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "7c644274",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'456'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.phone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "3520d208",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calling 456\n",
      "driiinnnn\n",
      "hello?\n",
      "hi Nikos\n",
      "it's a nice day outside!\n",
      "ok, bye\n"
     ]
    }
   ],
   "source": [
    "class person:\n",
    "    def __init__(self, name, phone):\n",
    "        self.name = name\n",
    "        self.phone = phone\n",
    "    def set_phone(self, phone):\n",
    "        self.phone = phone\n",
    "    def call(self, msg):\n",
    "        print(\"calling\", self.phone)\n",
    "        print(\"driiinnnn\")\n",
    "        print(\"hello?\")\n",
    "        print(\"hi\", self.name)\n",
    "        print(msg)\n",
    "        print(\"ok, bye\")\n",
    "\n",
    "p = person(\"Nikos\", \"123\")\n",
    "p.set_phone(\"456\")\n",
    "p.call(\"it's a nice day outside!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b5952c68",
   "metadata": {},
   "outputs": [],
   "source": [
    "class person:\n",
    "    def __init__(self, name, phone):\n",
    "        self.name = name\n",
    "        self.phone = phone\n",
    "    def set_phone(self, phone):\n",
    "        self.phone = phone\n",
    "    def call(self, msg):\n",
    "        print(\"calling\", self.phone)\n",
    "        print(\"driiinnnn\")\n",
    "        print(\"hello?\")\n",
    "        print(\"hi\", self.name)\n",
    "        print(msg)\n",
    "        print(\"ok, bye\")\n",
    "    def __str__(self):\n",
    "        return self.name + \" with phone \" + str(self.phone)\n",
    "    def __repr__(self):\n",
    "        return self.__str__()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "3916383d",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = person(\"Nikos\", 123)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "8eade60c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Nikos with phone 123"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "1b9f041c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Nikos with phone 123'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "667f67b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "class person:\n",
    "    def __init__(self, name, phone):\n",
    "        self.name = name\n",
    "        self.phone = phone\n",
    "    def set_phone(self, phone):\n",
    "        self.phone = phone\n",
    "    def call(self, msg):\n",
    "        print(\"calling\", self.phone)\n",
    "        print(\"driiinnnn\")\n",
    "        print(\"hello?\")\n",
    "        print(\"hi\", self.name)\n",
    "        print(msg)\n",
    "        print(\"ok, bye\")\n",
    "    def __str__(self):\n",
    "        return f\"{self.name} with phone {self.phone}\"\n",
    "    def __repr__(self):\n",
    "        return self.__str__()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "f9a4fa84",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = person(\"Nikos\", \"123\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "4dcb64c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Nikos with phone 123"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "6b95e012",
   "metadata": {},
   "outputs": [],
   "source": [
    "q = person(\"Nikos\", \"123\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "d2c70b55",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p == q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "dcac2aa0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2434612495760"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "acbe9f53",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2434608616176"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(\"hello\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "45ead048",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "140719889188792"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "6e9c2498",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2434608616176"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(\"hello\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "b72e3429",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p is q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "1a7a39a1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(p) == id(q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "3c2fc47d",
   "metadata": {},
   "outputs": [],
   "source": [
    "class person:\n",
    "    def __init__(self, name, phone):\n",
    "        self.name = name\n",
    "        self.phone = phone\n",
    "    def set_phone(self, phone):\n",
    "        self.phone = phone\n",
    "    def call(self, msg):\n",
    "        print(\"calling\", self.phone)\n",
    "        print(\"driiinnnn\")\n",
    "        print(\"hello?\")\n",
    "        print(\"hi\", self.name)\n",
    "        print(msg)\n",
    "        print(\"ok, bye\")\n",
    "    def __str__(self):\n",
    "        return f\"{self.name} with phone {self.phone}\"\n",
    "    def __repr__(self):\n",
    "        return self.__str__()\n",
    "    def __eq__(self, other):\n",
    "        return self.name == other.name and self.phone == other.phone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "72007986",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = person(\"Nikos\", \"123\")\n",
    "q = person(\"Nikos\", \"123\")\n",
    "r = person(\"Anna\", \"123\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "f3694a0c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p == r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "518407fc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q == r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "7bd338b8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p == q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "27ef8477",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p is q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "70321697",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(42) == id(\"hello\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "13b3eb41",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "42 == \"hello\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "3009ffff",
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'str' object has no attribute 'name'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mAttributeError\u001b[39m                            Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[37]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[33;43m\"\u001b[39;49m\u001b[33;43mhello\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m \u001b[49m\u001b[43m==\u001b[49m\u001b[43m \u001b[49m\u001b[43mp\u001b[49m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[29]\u001b[39m\u001b[32m, line 19\u001b[39m, in \u001b[36mperson.__eq__\u001b[39m\u001b[34m(self, other)\u001b[39m\n\u001b[32m     18\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m__eq__\u001b[39m(\u001b[38;5;28mself\u001b[39m, other):\n\u001b[32m---> \u001b[39m\u001b[32m19\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m.name == \u001b[43mother\u001b[49m\u001b[43m.\u001b[49m\u001b[43mname\u001b[49m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m.phone == other.phone\n",
      "\u001b[31mAttributeError\u001b[39m: 'str' object has no attribute 'name'"
     ]
    }
   ],
   "source": [
    "\"hello\" == p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "7d63e750",
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'str' object has no attribute 'name'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mAttributeError\u001b[39m                            Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[38]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mp\u001b[49m\u001b[43m \u001b[49m\u001b[43m==\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mhello\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[29]\u001b[39m\u001b[32m, line 19\u001b[39m, in \u001b[36mperson.__eq__\u001b[39m\u001b[34m(self, other)\u001b[39m\n\u001b[32m     18\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m__eq__\u001b[39m(\u001b[38;5;28mself\u001b[39m, other):\n\u001b[32m---> \u001b[39m\u001b[32m19\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m.name == \u001b[43mother\u001b[49m\u001b[43m.\u001b[49m\u001b[43mname\u001b[49m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m.phone == other.phone\n",
      "\u001b[31mAttributeError\u001b[39m: 'str' object has no attribute 'name'"
     ]
    }
   ],
   "source": [
    "p == \"hello\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "10bda8fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "class person:\n",
    "    def __init__(self, name, phone):\n",
    "        self.name = name\n",
    "        self.phone = phone\n",
    "    def set_phone(self, phone):\n",
    "        self.phone = phone\n",
    "    def call(self, msg):\n",
    "        print(\"calling\", self.phone)\n",
    "        print(\"driiinnnn\")\n",
    "        print(\"hello?\")\n",
    "        print(\"hi\", self.name)\n",
    "        print(msg)\n",
    "        print(\"ok, bye\")\n",
    "    def __str__(self):\n",
    "        return f\"{self.name} with phone {self.phone}\"\n",
    "    def __repr__(self):\n",
    "        return self.__str__()\n",
    "    def __eq__(self, other):\n",
    "        return (isinstance(other, person) and\n",
    "                self.name == other.name and self.phone == other.phone)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "1398f547",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = person(\"Nikos\", \"123\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "8fbb664d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p == \"hello\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "4dab23fc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "42 == p"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04152829",
   "metadata": {},
   "source": [
    "## Εστιατόριο\n",
    "\n",
    "Ορίστε την κλάση `Restaurant` που θα χρησιμοποιηθεί για την τήρηση των κρατήσεων ενός εστιατορίου.  \n",
    "Η κλάση αυτή πρέπει να υποστηρίζει τις παρακάτω λειτουργίες:\n",
    "-  Κατασκευή εστιατορίου με συγκεκριμένο συνολικό πλήθος τραπεζιών.\n",
    "   Θεωρούμε ότι τα τραπέζια είναι αριθμημένα ξεκινώντας από το 1.\n",
    "-  Μέθοδος `available` που επιστρέφει πόσα τραπέζια είναι διαθέσιμα (αρχικά είναι όλα διαθέσιμα).\n",
    "-  Μέθοδος `book` που επιστρέφει το διαθέσιμο τραπέζι με τον μικρότερο αριθμό, το οποίο μετά την κλήση της παύει να είναι διαθέσιμο.\n",
    "-  Μέθοδος `release` που αποδεσμεύει ένα τραπέζι, το οποίο γίνεται πάλι διαθέσιμο.\n",
    "\n",
    "Ορίστε μία κατάλληλη υλοποίηση για την κλάση Restaurant.  \n",
    "Φροντίστε η υλοποίηση να είναι όσο το δυνατόν αποδοτικότερη για μεγάλο πλήθος τραπεζιών."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "0d7c60c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Restaurant:\n",
    "    def __init__(self, tables):\n",
    "        self.tables = tables\n",
    "        self.available_tables = set()\n",
    "        self.up_to = 0\n",
    "    def available(self):\n",
    "        return len(self.available_tables) + self.tables - self.up_to\n",
    "    def book(self):\n",
    "        if self.available() == 0:\n",
    "            raise \"no more available tables\"\n",
    "        if self.available_tables:\n",
    "            t = min(self.available_tables)    # assuming a set implementation\n",
    "                                              # where finding the min is < O(N)\n",
    "            self.available_tables.remove(t)\n",
    "            return t\n",
    "        self.up_to += 1\n",
    "        return self.up_to\n",
    "    def release(self, n):\n",
    "        if n < 1 or n > self.tables:\n",
    "            raise \"invalid table number\"\n",
    "        if n in self.available_tables or n > self.up_to:\n",
    "            raise \"the table is already available\"\n",
    "        self.available_tables.add(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "560413a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "r = Restaurant(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "d9a34cad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.book()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "b192af7e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.book()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "873aa6d5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.book()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "55a891c4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.available()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "e4b1b764",
   "metadata": {},
   "outputs": [],
   "source": [
    "r.release(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "65626168",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.available()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "ef898e2a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.book()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "9c936fed",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.book()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bca4c567",
   "metadata": {},
   "source": [
    "## Ο λύκος, η κατσίκα και το λάχανο"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "b62b1ad8",
   "metadata": {},
   "outputs": [],
   "source": [
    "class state:\n",
    "    def __init__(self, left, right):\n",
    "        self.left = frozenset(left)\n",
    "        self.right = frozenset(right)\n",
    "    def __str__(self):\n",
    "        return str(self.left) + \" | \" + str(self.right)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "414586ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "init = state(['man', 'wolf', 'goat', 'cabbage'], [])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "0d20a6fe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"frozenset({'goat', 'cabbage', 'man', 'wolf'}) | frozenset()\""
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(init)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "122e80b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "class state:\n",
    "    def __init__(self, left, right):\n",
    "        self.left = frozenset(left)\n",
    "        self.right = frozenset(right)\n",
    "    def __str__(self):\n",
    "        return str(self.left) + \" | \" + str(self.right)\n",
    "    def success(self):\n",
    "        return not self.left\n",
    "\n",
    "init = state(['man', 'wolf', 'goat', 'cabbage'], [])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "96560f24",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "init.success()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "3d679239",
   "metadata": {},
   "outputs": [],
   "source": [
    "class state:\n",
    "    def __init__(self, left, right):\n",
    "        self.left = frozenset(left)\n",
    "        self.right = frozenset(right)\n",
    "    def __str__(self):\n",
    "        return str(self.left) + \" | \" + str(self.right)\n",
    "    def success(self):\n",
    "        return not self.left\n",
    "    def safe(self):\n",
    "        def tragic(bank):\n",
    "            return \"man\" not in bank and (\n",
    "                (\"wolf\" in bank and \"goat\" in bank) or\n",
    "                (\"goat\" in bank and \"cabbage\" in bank)\n",
    "            )\n",
    "        return not tragic(self.left) and not tragic(self.right)\n",
    "\n",
    "init = state(['man', 'wolf', 'goat', 'cabbage'], [])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "ae86872d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "init.safe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "3458be0e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "state(['man', 'wolf'], ['cabbage', 'goat']).safe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "fd199fe0",
   "metadata": {},
   "outputs": [],
   "source": [
    "class state:\n",
    "    def __init__(self, left, right):\n",
    "        self.left = frozenset(left)\n",
    "        self.right = frozenset(right)\n",
    "    def __str__(self):\n",
    "        return str(self.left) + \" | \" + str(self.right)\n",
    "    def success(self):\n",
    "        return not self.left\n",
    "    def safe(self):\n",
    "        def tragic(bank):\n",
    "            return \"man\" not in bank and (\n",
    "                (\"wolf\" in bank and \"goat\" in bank) or\n",
    "                (\"goat\" in bank and \"cabbage\" in bank)\n",
    "            )\n",
    "        return not tragic(self.left) and not tragic(self.right)\n",
    "    def accessible(self):\n",
    "        if \"man\" in self.left:\n",
    "            for x in self.left:\n",
    "                moving = frozenset([\"man\", x])\n",
    "                yield state(self.left - moving, self.right | moving)\n",
    "        else:\n",
    "            for x in self.right:\n",
    "                moving = frozenset([\"man\", x])\n",
    "                yield state(self.left | moving, self.right - moving)         \n",
    "\n",
    "init = state(['man', 'wolf', 'goat', 'cabbage'], [])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "5117285b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "frozenset({'cabbage', 'wolf'}) | frozenset({'man', 'goat'})\n"
     ]
    }
   ],
   "source": [
    "for s in init.accessible():\n",
    "    if not s.safe(): continue\n",
    "    print(str(s))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "93e86abf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "frozenset({'cabbage', 'man', 'wolf'}) | frozenset({'goat'})\n",
      "frozenset({'cabbage', 'goat', 'man', 'wolf'}) | frozenset()\n"
     ]
    }
   ],
   "source": [
    "for s1 in init.accessible():\n",
    "    if not s1.safe(): continue\n",
    "    for s2 in s1.accessible():\n",
    "        if not s2.safe(): continue\n",
    "        print(str(s2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ff4652c-fdf8-4a39-b185-bb19d8da166d",
   "metadata": {},
   "source": [
    "to be continued..."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.14.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
