Skip to content

Instantly share code, notes, and snippets.

@drvinceknight
Created October 25, 2016 13:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drvinceknight/8157c4510fa58a4bc037a130f6456c96 to your computer and use it in GitHub Desktop.
Save drvinceknight/8157c4510fa58a4bc037a130f6456c96 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Object oriented programming"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q1: Classes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We build a simple class:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class Student:\n",
" pass # This is just a dummy line (we will use real code later)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<__main__.Student at 0x104868240>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince = Student()\n",
"zoe = Student()\n",
"vince"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<__main__.Student at 0x104868208>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"zoe"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<__main__.Student at 0x104868198>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"simba = Student()\n",
"simba"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Q2: Attributes"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class Student:\n",
" courses = ['Biology', 'Mathematics', 'English']\n",
" age = 12\n",
" gender = \"Female\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The class has the attribute:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"12"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Student.age"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But also the instances of the class:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['Biology', 'Mathematics', 'English']"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince = Student()\n",
"vince.courses"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"12"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince.age"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'Female'"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince.gender"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"13"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince.age += 1\n",
"vince.age"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'Male'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince.gender = 'Male'\n",
"vince.gender"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['Biology', 'Mathematics', 'English', 'Chemistry']"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince.courses.append('Chemistry')\n",
"vince.courses"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q3: Methods"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"13"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"class Student:\n",
" \"\"\"A class to represent a student\"\"\"\n",
" courses = ['Biology', 'Mathematics', 'English']\n",
" age = 12\n",
" gender = \"Female\"\n",
" def have_a_birthday(self, years=1):\n",
" \"\"\"Increment the age\"\"\"\n",
" self.age += years # self corresponds to the instance\n",
"vince = Student()\n",
"vince.have_a_birthday()\n",
"vince.age"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"23"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince.have_a_birthday(years=10)\n",
"vince.age"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are a variety of special methods:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class Student:\n",
" \"\"\"A class to represent a student\"\"\"\n",
" def __init__(self, courses, age, gender):\n",
" self.courses = courses\n",
" self.age = age\n",
" self.gender = gender\n",
" def have_a_birthday(self, years=1):\n",
" \"\"\"Increment the age\"\"\"\n",
" self.age += years # self corresponds to the instance"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can easily create instances with given attributes:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(['Maths'], 32, 'Male')"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"vince = Student([\"Maths\"], 32, \"Male\")\n",
"zoe = Student([\"Biology\"], 31, \"Female\")\n",
"vince.courses, vince.age, vince.gender"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(['Biology'], 31, 'Female')"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"zoe.courses, zoe.age, zoe.gender"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q4: Inheritance"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class LeapYearStudent(Student):\n",
" \"\"\"A class for a student born on the 29th of February\"\"\"\n",
" # Note that we do not have to rewrite the init method\n",
" def have_a_birthday(self, years=1):\n",
" self.age += int(years / 4)\n",
" def complain(self):\n",
" \"\"\"Return a string complaining about birthday\"\"\"\n",
" # This is a new method that the Student class does not have\n",
" return \"I wish I was not born on the 29th of Feb\""
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"22"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"geraint = LeapYearStudent([\"Maths\"], 22, \"Male\")\n",
"geraint.have_a_birthday()\n",
"geraint.age # Still 22"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"24"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"geraint.have_a_birthday(8)\n",
"geraint.age"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'I wish I was not born on the 29th of Feb'"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"geraint.complain()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is how we would change this if leap years were every 3 years:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"class LeapYearStudent(Student):\n",
" \"\"\"A class for a student born on the 29th of February\"\"\"\n",
" # Note that we do not have to rewrite the init method\n",
" def have_a_birthday(self, years=1):\n",
" self.age += int(years / 3)\n",
" def complain(self):\n",
" \"\"\"Return a string complaining about birthday\"\"\"\n",
" # This is a new method that the Student class does not have\n",
" return \"I wish I was not born on the 29th of Feb\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q5: Worked example"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"class LinearExpression:\n",
" \"\"\"A class for a linear expression\"\"\"\n",
" def __init__(self, a, b):\n",
" self.a = a\n",
" self.b = b\n",
" def root(self):\n",
" \"\"\"Return the root of the linear expression\"\"\"\n",
" return - self.b / self.a\n",
" def __add__(self, linexp):\n",
" \"\"\"A special method: lets us have addition between expressions\"\"\"\n",
" return LinearExpression(self.a + linexp.a, self.b + linexp.b)\n",
" def __repr__(self):\n",
" \"\"\"A special method: changes the way an instance is displayed\"\"\"\n",
" return \"Linear expression: \" + str(self.a) + \"x + \" + str(self.b)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Linear expression: 2x + 4"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"exp = LinearExpression(2, 4)\n",
"exp # This output is given by the `__repr__` method"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(2, 4)"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"exp.a, exp.b"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"-2.0"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"exp.root()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Linear expression: 7x + 2"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"exp2 = LinearExpression(5, -2)\n",
"exp + exp2 # This works because of the `__add__` method"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This class works great but we quickly see a problem:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Linear expression: 0x + 8"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"exp1 = LinearExpression(2, 4)\n",
"exp2 = LinearExpression(-2, 4)\n",
"exp3 = exp1 + exp2\n",
"exp3"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We get an error when finding the root of a line parallel to the x-axis."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "ZeroDivisionError",
"evalue": "division by zero",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-29-a70d3851bcfc>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mexp3\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mroot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m<ipython-input-23-8a286ceb2b0d>\u001b[0m in \u001b[0;36mroot\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mroot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;34m\"\"\"Return the root of the linear expression\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mb\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 9\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__add__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlinexp\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\"\"\"A special method: lets us have addition between expressions\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mZeroDivisionError\u001b[0m: division by zero"
]
}
],
"source": [
"exp3.root()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us fix this, and return `False` when there is no root:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"class LinearExpression:\n",
" \"\"\"A class for a linear expression\"\"\"\n",
" def __init__(self, a, b):\n",
" self.a = a\n",
" self.b = b\n",
" def root(self):\n",
" \"\"\"Return the root of the linear expression\"\"\"\n",
" if self.a != 0:\n",
" return - self.b / self.a\n",
" return False\n",
" def __add__(self, linexp):\n",
" \"\"\"A special method: let's us have addition between expressions\"\"\"\n",
" return LinearExpression(self.a + linexp.a, self.b + linexp.b)\n",
" def __repr__(self):\n",
" \"\"\"A special method: changes the default way an instance is displayed\"\"\"\n",
" return \"Linear expression: \" + str(self.a) + \"x + \" + str(self.b)\n",
"exp3 = LinearExpression(0, 8)\n",
"exp3.root()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us write a function to check the required formula:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def check_result(a1, a2, b1, b2):\n",
" \"\"\"Check that the relationship holds\"\"\"\n",
" f = LinearExpression(a1, b1)\n",
" g = LinearExpression(a2, b2)\n",
" k = f + g\n",
" x1 = f.root()\n",
" x2 = g.root()\n",
" x3 = k.root()\n",
" if (x1 is not False) and (x2 is not False) and (x3 is not False):\n",
" # Assuming our three expressions have a root\n",
" return (a1 * x1 + a2 * x2) / (a1 + a2) == x3\n",
" return True # If f, g have no roots the relationship is still true\n",
"check_result(2, 3, 4, 5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us check this for a number of random 4-tuples:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import random # Importing the random module\n",
"N = 1000 # THe number of samples\n",
"checks = []\n",
"for _ in range(N):\n",
" a1 = random.randint(-10, 10)\n",
" a2 = random.randint(-10, 10)\n",
" b1 = random.randint(-10, 10)\n",
" b2 = random.randint(-10, 10)\n",
" checks.append(check_result(a1, a2, b1, b2))\n",
"all(checks)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q6: Debugging exercise"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class Rectangle:\n",
" # \"\"\"A class for a rectangle\"\" Wrong number of \"\n",
" \"\"\"A class for a rectangle\"\"\"\n",
" #def __init__(width, length) Missing self and :\n",
" def __init__(self, width, length):\n",
" self.width = width\n",
" #self.length = width # Wrong assignment\n",
" self.length = length\n",
" #def obtain_area(self: Missing bracket\n",
" def obtain_area(self):\n",
" \"\"\"Obtain the area of the rectangle\"\"\"\n",
" return self.width * self.length\n",
" #def is_square(): Missing self\n",
" def is_square(self):\n",
" \"\"\"Check if the rectangle is a square\"\"\"\n",
" return self.width == self.length"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Creating a non square rectangle:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(20, False)"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rectangle = Rectangle(5, 4)\n",
"rectangle.obtain_area(), rectangle.is_square()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Creating a square rectangle:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(9, True)"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"square = Rectangle(3, 3)\n",
"square.obtain_area(), square.is_square()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q7\n",
"\n",
"Here is the quadratic expression:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import math\n",
"\n",
"class QuadraticExpression:\n",
" \"\"\"A class for a quadratic expression\"\"\"\n",
" def __init__(self, a, b, c):\n",
" self.a = a\n",
" self.b = b\n",
" self.c = c\n",
" def root(self):\n",
" \"\"\"Return the root of the linear expression\"\"\"\n",
" determinant = self.b ** 2 - 4 * self.a * self.c\n",
" if determinant >= 0:\n",
" x1 = - (self.b + math.sqrt(determinant))/ (2 * self.a)\n",
" x2 = - (self.b - math.sqrt(determinant))/ (2 * self.a)\n",
" return x1, x2\n",
" return False\n",
" def __add__(self, quadexp):\n",
" \"\"\"A special method: let's us have addition between expressions\"\"\"\n",
" return QuadraticExpression(self.a + quadexp.a, self.b + quadexp.b, self.c + quadexp.c)\n",
" def __repr__(self):\n",
" \"\"\"A special method: changes the default way an instance is displayed\"\"\"\n",
" return \"Quadratic expression: \" + str(self.a) + \"x ^ 2 + \" + str(self.b) + \"x + \" + str(self.c)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Quadratic expression: 1x ^ 2 + 5x + 2"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"quad = QuadraticExpression(1, 5, 2)\n",
"quad"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(-4.561552812808831, -0.4384471871911697)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"quad.root()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Quadratic expression: 5x ^ 2 + 10x + 4"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"quad2 = QuadraticExpression(4, 5, 2)\n",
"quad + quad2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q8: Tickable\n",
"\n",
"Let us read in the data:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'a,b,c\\n1,4,7\\n11,7,14\\n16,2,8\\n14,7,13\\n2,20,5\\n3,18,15\\n20,5,10\\n3,19,6\\n15,17,1\\n13,3,14\\n17,7,16\\n16,18,4\\n17,3,19\\n15,16,11\\n18,6,13\\n15,18,18\\n7,12,19\\n19,6,8\\n14,5,20\\n2,10,2\\n17,20,9\\n1,14,6\\n6,11,8\\n6,5,20\\n7,9,4\\n2,20,8\\n5,16,7\\n20,14,7\\n1,7,11\\n20,18,14\\n9,16,13\\n12,13,14\\n14,19,7\\n19,8,18\\n15,20,9\\n10,4,2\\n19,14,14\\n1,15,10\\n12,13,14\\n4,7,18\\n16,14,8\\n14,5,13\\n19,11,19\\n1,8,16\\n1,4,7\\n5,11,11\\n6,3,9\\n17,3,19\\n1,20,5\\n1,9,13\\n6,17,20\\n20,14,19\\n13,2,3\\n20,11,15\\n9,8,6\\n18,8,7\\n7,1,4\\n7,5,6\\n6,12,11\\n11,20,17\\n2,18,17\\n5,15,4\\n11,20,9\\n7,14,2\\n8,13,1\\n1,20,13\\n14,3,4\\n7,12,3\\n2,14,19\\n5,16,6\\n9,5,11\\n5,16,4\\n2,19,1\\n19,17,3\\n11,1,1\\n10,13,15\\n8,11,4\\n17,16,13\\n8,9,15\\n6,14,20\\n8,1,6\\n1,13,15\\n14,6,15\\n6,19,5\\n9,12,4\\n8,3,13\\n10,7,2\\n19,6,1\\n4,1,14\\n5,17,14\\n6,1,7\\n9,5,15\\n2,17,8\\n20,7,3\\n20,8,15\\n15,18,4\\n5,2,15\\n4,15,19\\n7,19,9\\n13,8,4\\n18,19,1\\n12,11,7\\n1,11,20\\n14,10,1\\n1,13,16\\n11,20,12\\n13,18,3\\n13,16,15\\n5,18,19\\n14,15,8\\n5,15,9\\n12,5,18\\n15,13,16\\n12,18,10\\n19,17,1\\n4,15,17\\n8,12,18\\n1,15,11\\n7,16,19\\n20,14,2\\n18,12,13\\n6,14,3\\n9,7,4\\n17,7,6\\n3,20,16\\n2,16,3\\n6,2,9\\n11,11,11\\n11,20,13\\n20,5,6\\n13,8,1\\n13,10,19\\n3,7,12\\n15,16,18\\n10,13,16\\n17,15,11\\n10,15,13\\n20,11,16\\n13,6,18\\n13,9,9\\n19,2,9\\n9,18,8\\n4,3,8\\n4,11,1\\n19,15,13\\n12,4,15\\n2,15,2\\n20,18,1\\n4,20,9\\n2,3,18\\n14,7,18\\n14,7,3\\n2,4,18\\n14,13,20\\n16,1,8\\n6,2,4\\n15,16,19\\n4,4,9\\n12,5,6\\n19,20,16\\n17,13,4\\n3,6,12\\n12,16,1\\n11,15,7\\n20,17,11\\n6,4,2\\n17,6,13\\n6,9,3\\n9,5,19\\n19,13,5\\n10,3,1\\n3,15,10\\n19,6,4\\n4,17,6\\n4,18,16\\n20,18,14\\n17,12,13\\n9,1,3\\n12,18,15\\n5,3,17\\n9,10,8\\n17,1,15\\n17,7,5\\n18,15,7\\n11,3,10\\n4,9,17\\n13,3,15\\n15,15,2\\n6,3,19\\n15,2,12\\n17,6,14\\n19,11,4\\n19,14,9\\n18,3,6\\n20,11,14\\n2,2,5\\n3,16,16\\n3,10,8\\n15,6,7\\n9,13,9\\n'"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"with open(\"quadratics.csv\", 'r') as f:\n",
" string = f.read()\n",
"string"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First let us split the data on the newline character:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['a,b,c', '1,4,7', '11,7,14', '16,2,8', '14,7,13']"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = string.split('\\n')\n",
"data[:5] # Looking at the first 5 rows"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now have a list of strings, we need to split each string on the `,` character. We are also going to get rid of the first row (which is just the header):"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[['1', '4', '7'],\n",
" ['11', '7', '14'],\n",
" ['16', '2', '8'],\n",
" ['14', '7', '13'],\n",
" ['2', '20', '5']]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = [s.split(',') for s in data[1:-1]]\n",
"data[:5]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That was a little bit of hard work. The format of the data in the file itself: a row of numbers seperated by a `,` is pretty normal and is called \"comma seperated value\" and to deal with this Python has an inbuilt parsing library that makes this all easier. So here is another way of doing this:"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import csv # We are using the csv module to help parse the file"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"with open(\"quadratics.csv\", 'r') as f:\n",
" csvreader = csv.reader(f)\n",
" data = [row for row in csvreader][1:] # Get rid of first row"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that we have the same elements as before:"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[['1', '4', '7'],\n",
" ['11', '7', '14'],\n",
" ['16', '2', '8'],\n",
" ['14', '7', '13'],\n",
" ['2', '20', '5']]"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data[:5]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us convert those remaining strings to integers:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[[1, 4, 7], [11, 7, 14], [16, 2, 8], [14, 7, 13], [2, 20, 5]]"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = [[int(k) for k in row] for row in data]\n",
"data[:5]"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"Now, let us create a quadratic expression for each of the rows:"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Quadratic expression: 1x ^ 2 + 4x + 7,\n",
" Quadratic expression: 11x ^ 2 + 7x + 14,\n",
" Quadratic expression: 16x ^ 2 + 2x + 8,\n",
" Quadratic expression: 14x ^ 2 + 7x + 13,\n",
" Quadratic expression: 2x ^ 2 + 20x + 5]"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"quadratics = [QuadraticExpression(row[0], row[1], row[2]) for row in data]\n",
"quadratics[:5] # Looking at first five quadratics"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, let us count how many of these have roots:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Quadratic expression: 2x ^ 2 + 20x + 5,\n",
" Quadratic expression: 3x ^ 2 + 18x + 15,\n",
" Quadratic expression: 3x ^ 2 + 19x + 6,\n",
" Quadratic expression: 15x ^ 2 + 17x + 1,\n",
" Quadratic expression: 16x ^ 2 + 18x + 4]"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"quadratics_with_real_roots = [q for q in quadratics if q.root() is not False]\n",
"quadratics_with_real_roots[:5]"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"59"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(quadratics_with_real_roots)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q9"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import random\n",
"import math # This is not necessarily needed but will be useful for some comparisons later on.\n",
"\n",
"\n",
"class Drop():\n",
" \"\"\" \n",
" A class for a rain drop falling in a random location \n",
" on a square \n",
" \"\"\"\n",
" def __init__(self, r=1):\n",
" self.x = (.5 - random.random()) * 2 * r\n",
" self.y = (.5 - random.random()) * 2 * r\n",
" self.incircle = (self.y) ** 2 + (self.x) ** 2 <= (r) ** 2 \n",
" # This returns the boolean corresponding to whether or not the point is in the circle\n",
"\n",
"\n",
"def approxpi(N=1000):\n",
" \"\"\"\n",
" Function to return an approximation for pi using montecarlo simulation\n",
" \"\"\"\n",
" numberofpointsincircle = 0\n",
" for i in range(N): # A loop to drop sufficient points\n",
" drop = Drop() # Generate a new drop\n",
" if drop.incircle: # Check if drop is in circle\n",
" numberofpointsincircle += 1\n",
" return 4 * numberofpointsincircle / float(N)"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3.18"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"approxpi()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Q10"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"\n",
"class Point():\n",
" \"\"\"\n",
" A class for a point falling in a random location on a square\n",
"\n",
" Attributes:\n",
" x: the x coordinate of the point\n",
" y: the y coordinate of the point\n",
" incircle: a boolean indicating whether or not the point is under the graph\n",
" \"\"\"\n",
" def __init__(self, r=1):\n",
" self.x = random.random()\n",
" self.y = random.random()\n",
" self.undergraph = 1 - (self.x) ** 2 >= self.y \n",
" # This returns the boolean checking whether or not the point is under the graph\n",
"\n",
"\n",
"def approxint(N=1000):\n",
" \"\"\"\n",
" Function to return an approximation for the integral using montecarlo simulation\n",
"\n",
" Arguments: N (default=1000) which is the number of points\n",
"\n",
" Outputs: An approximation of the integral\n",
" \"\"\"\n",
" numberofpointsundergraph = 0\n",
" for i in range(N): # A loop to drop sufficient points\n",
" point = Point() # Generate a new drop\n",
" if point.undergraph: # Check if drop is in circle\n",
" numberofpointsundergraph += 1\n",
" return numberofpointsundergraph / float(N)"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.66"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"approxint()"
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python [default]",
"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.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment