Skip to content
Snippets Groups Projects
Commit 2d2e037a authored by Morten Hannemose's avatar Morten Hannemose
Browse files

Removed future files

parent 270b5b75
No related branches found
No related tags found
No related merge requests found
Showing
with 0 additions and 937 deletions
"""Exercise 4.1 and 4.2."""
import math
def square_root(a : float) -> float:
r"""Compute the square root, see section 7.5 in Think Python.
:param a: A number to compute the square root of.
:return: :math:`\sqrt{a}`.
"""
# TODO: 7 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return sqrt_a
def ramanujan() -> float:
r"""Compute the Ramanujan approximation of :math:`\pi` using a sufficient number of terms.
:return: A high-quality approximation of :math:`\pi` as a ``float``.
"""
# TODO: 9 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return pi
if __name__ == "__main__":
print("approximate pi", ramanujan())
print("square root of 2 is", square_root(2))
"""Exercise 4.1: Checking if a word is a palindrome."""
def is_palindrome(word : str) -> bool:
"""Check if ``word`` is a palindrome.
:param word: The word to check
:return: ``True`` if input is a palindrome and otherwise ``False``
"""
# TODO: 2 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return is_a_palindrome
if __name__ == "__main__":
print("Is Madam a palindrome?", is_palindrome('madam'))
print("Is gentleman a palindrome?", is_palindrome('gentleman'))
"""Exercise 4.x-4.y."""
def matching(expression :str) -> bool:
"""Tell if the parenthesis match in a mathematical expression.
For instance, the parenthesis match in ``"3x(y-1)(3y+(x-1))"`` but not in ``"3x(y-4))"``
:param expression: An expression containing zero or more parenthesis.
:return: ``True`` if the number of open/close parenthesis match, otherwise ``False``
"""
# TODO: 9 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return matching
def find_index_of_equality(expression : str) -> int:
"""Find an index ``i`` which split the expression into two balanced parts.
Given an expression containing opening and closing parenthesis, for instance ``"(()())"``, this function should
return an index ``i``, such that when the string is split at ``i``, the
number of opening parenthesis ``(`` in the left-hand part equal the number of closing parenthesis ``)`` in the
right-hand part. For instance, if ``i=2``, the expression is split into the right, left hand parts:
- ``"(()"``
- ``"())"``
In this case the left-hand part contains ``2`` opening parenthesis and ``2`` closign parenthesis so ``i`` is the right index.
Similarly, for ``"()"``, the answer would be ``1``.
:param expression: An expression only consisting of opening and closing parenthesis.
:return: The index ``i`` as an int.
"""
# TODO: 6 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return i
def print_the_dialogue(s : str):
"""Print all dialogue in a manuscript.
Given a manuscript (as a ``str``), this function will find all lines of dialogue to the console, one line of
dialogue per printed line. Dialogue is enclosed by double ticks, i.e. this ``str`` contains two pieces of dialogue:
``"''My dear Mr. Bennet,'' said his lady to him one day, ''have you heard that Netherfield Park is let at last?''"``
:param s: The manuscript as a ``str``.
"""
# TODO: 4 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
def find_innermost_part(s : str) -> str:
"""Find the innermost part of a mathematical expression.
The innermost part is a substring enclosed in parenthessis but not containing parenthesis.
For instance, given ``"3(x+(4-y^2))"``, then ``"4-y^2"`` is an inner-most part.
The parenthesis can be assumed to match.
:param s: The mathematical expression as a ``str``
:return: The innermost part as a ``str``
"""
# TODO: 3 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return inner_part
if __name__ == "__main__":
print("Does the parenthesis match?", matching("2x(x+2)"))
print("Does the parenthesis match?", matching("2x(x+(2-y)^2)"))
print("Does the parenthesis match?", matching("4x"))
print("Does the parenthesis match?", matching("2x(x+2"))
print("Does the parenthesis match?", matching("2x)(x"))
print("Does the parenthesis match?", matching("4x()(()))"))
s = "(())))("
print("Index of equality for", s, "is", find_index_of_equality(s))
dialogue = "He said: ''How are you old wife''? She answered, perplexed, ''I am not your wife''"
print_the_dialogue(dialogue)
"""Play a game of hangman by loading a random word."""
import random
import os
def load_words() -> list:
"""
Return a list of valid words. Words are strings of lowercase letters.
Depending on the size of the word list, this function may
take a while to finish.
:return: The available words as a list.
"""
from cp.ex08.words import load_words
wordlist = load_words(os.path.join(os.path.dirname(__file__), "files", "5000-words.txt")).split()
return wordlist
def choose_word() -> str:
"""Select a word at random.
:return: A randomly selected word, useful for playing hangman.
"""
wordlist = load_words()
return random.choice(wordlist)
"""Exercise XX."""
def common_prefix(word1 : str, word2 : str) -> str:
"""
Return the longest string so that both ``word1``, and ``word2`` begin with that string.
:param word1: First word
:param word2: Second word
:return: The longest common prefix.
"""
# TODO: 6 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return prefix
def common_prefix3(word1 : str, word2 : str, word3 : str) -> str:
"""
Return the longest string so that both ``word1``, ``word2``, and ``word3`` begin with that string.
:param word1: First word
:param word2: Second word
:param word3: Third word
:return: The longest common prefix.
"""
# TODO: 1 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return prefix
# Driver Code
if __name__ == "__main__":
print("The longest Common Prefix is :", common_prefix("egregious", "egg"))
print("The longest Common Prefix is :", common_prefix3("egg", "egregious", "eggplant"))
"""Exercises for week 9."""
"""The Rectangle-exercises 9.1-9.2."""
import matplotlib.pyplot as plt
class Point:
"""A class that represents a Point. See Section 15.1."""
class Rectangle:
"""A class that represents a Rectangle. See Section 15.3."""
def area(rectangle : Rectangle) -> float:
"""Compute the area of a Rectangle-object.
:param rectangle: A rectangle-object. Recall it has properties such as ``rectangle.width`` and ``rectangle.height``.
:return: The area of the rectangle.
"""
# TODO: 1 lines missing.
raise NotImplementedError("Compute the area here. Try to use the debugger if you are stuck.")
return a
def make_a_rectangle(x, y, width, height):
"""Create and return a new Rectangle-object. Look at Section 15.3 to see what fields it must possess.
:param x: The x-position of the lower-left corner.
:param y: The y-position of the lower-left corner.
:param width: The width of the rectangle.
:param height: The height of the rectangle.
:return: A new Rectangle object.
"""
# TODO: 6 lines missing.
raise NotImplementedError("Create and return a Rectangle object here.")
return rect
def split_rectangle(rectangle : Rectangle, horizontally : bool) -> list:
"""Split the rectangle object into two. Either horizontally or vertically.
For instance, if ``horizontally=True`` this function should return a list such as
``[left_rectangle, right_rectangle]``.
:param rectangle: A rectangle-object.
:param horizontally: If ``True`` the Rectangle is split horizontally otherwise vertically.
:return: A list with two Rectangle-objects.
"""
# TODO: 5 lines missing.
raise NotImplementedError("Implement function body")
return split
def plot_rectangle(rectangle: Rectangle):
"""Plot the rectangle using matplotlib.
:param rectangle: The Rectangle to plot.
"""
# TODO: 5 lines missing.
raise NotImplementedError("Implement function body")
def rectangle_inception(rectangle, n):
r"""Recursively generate a list of n+1 rectangles by applying split_rectangle n times.
Note that the list should contain n+1 non-overlapping rectangles with the same total area as the original rectangle.
The function should begin with a horizontal split.
:param rectangle: The initial rectangle to split.
:param n: How many recursive splits to apply
:return: A list of n+1 Rectangle-instances of the form ``[left, right_top, ...]``
"""
# TODO: 3 lines missing.
raise NotImplementedError("Implement function body")
return rectangles
if __name__ == "__main__":
rectangles = rectangle_inception(make_a_rectangle(0, 0, 10, 10), 10)
for r in rectangles:
plot_rectangle(r)
# Optionally: Let's save the rectangle for later:
from cp import savepdf
savepdf("rectangles.pdf") # Save your pretty rectangles for later.
plt.show()
"""Project work for week 9, classes I."""
import math
class Sin:
"""A class that represents the sinus-function, i.e. sin(x) where x can be any expression."""
class Cos:
"""A class that represents the cosine-function, i.e. cos(x) where x can be any expression."""
class Variable:
"""A class that represents a (named) variable such as ``x``, ``y``, ``x2``, etc."""
def make_symbol(symbol : str) -> Variable:
"""Create a new Variable object with the given name.
If ``v = make_symbol(x)`` then ``v.symbol`` should be the string ``"x"``.
:param symbol: The symbol this variable represents, e.g. ``"x"``.
:return: A new variable object.
"""
# TODO: 2 lines missing.
raise NotImplementedError("Implement function body")
return v
def sine(arg : object) -> Sin:
"""Create a new Sin object. The object will represent sin(arg).
In other words, if we let ``s = sine(arg), then s.arg should be equal to ``arg``. In our case,
``arg`` can be either a ``Variable``, or an object such as ``Sin``.
:param arg: The argument to sin.
:return: An object representing ``sin(arg)``.
"""
# TODO: 2 lines missing.
raise NotImplementedError("Implement function body")
return s
def cosine(arg : object) -> Cos:
"""Create a new Cos object. The object will represent cos(arg).
In other words, if we let ``s = cosine(arg), then s.arg should be equal to ``arg``. In our case,
``arg`` can be either a ``Variable``, or an object such as ``Cos``.
:param arg: The argument to cos.
:return: An object representing ``cos(arg)``.
"""
# TODO: 2 lines missing.
raise NotImplementedError("Implement function body")
return s
def format_expression(expression : object) -> str:
"""Format the given expression and return it as a string.
The expression is an object either of class Variable, Sin or Cos. The function should format it as a ``str``.
:param expression: An object to format.
:return: A string representation such as ``"cos(x)"`` or ``"sin(cos(y))"``.
"""
# TODO: 6 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
if __name__ == "__main__":
exp = sine(cosine(sine(sine(make_symbol('x')))))
print( format_expression(exp) )
# print(format_expression(exp), "evaluated in x=0 is", evaluate(exp, 0) )
from sympy import sin, cos, symbols, evaluate, Symbol
evaluate_expression = sin.evalf # Get the evaluation-function. Ignore the right-hand side for now.
print_expression = sin.__str__ # Get the formatting-function. Ignore the right-hand side for now.
x = symbols('x') # Define a symbol
y = sin(cos(x))
print_expression(y)
evaluate_expression(y, subs={'x': 0})
y = sin(x)
isinstance(y, sin) # It is an instance of the sin-class
from sympy import Symbol
y.args
isinstance(y.args[0], Symbol)
y.args[0] == x
"""This file contains all the exercises relating to the Minecraft-example 9.3-9.8."""
import matplotlib.pyplot as plt
class Vector:
"""A class that represents a Vector, defined by the endpoint :math:`(x,y)`."""
def make_vector(x : float, y : float) -> Vector:
"""Create a new Vector object with end-points :math:`(x,y)`.
.. runblock:: pycon
>>> from cp.ex09.vector import make_vector
>>> v = make_vector(2,3)
>>> v.x
>>> v.y
:param x: The :math:`x`-position of the vector.
:param y: The :math:`y`-position of the vector.
:return: A Vector-object with the given end-point.
"""
# TODO: 3 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return v
def print_vector(v: Vector):
"""Print a vector object with coordinates (x,y) to the console.
The output format for a vector with coordinates :math:`x, y` should be simply ``(x, y)`` (on a single line)
:param v: A vector object instance.
"""
# TODO: 1 lines missing.
raise NotImplementedError("print(.. format the print statement here .. )")
def dot(v1 : Vector, v2 : Vector) -> float:
r"""Compute the dot-product of ``v1`` and ``v2``, i.e. :math:`\mathbf{v}_1 \cdot \mathbf{v}_2`.
:param v1: The first vector,
:param v2: The second vector,
:return: The dot product of ``v1`` and ``v2`` (as a ``float``)
"""
# TODO: 1 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return dot_product
def scale(s : float, v : Vector) -> Vector:
r"""Scale the vector :math:`\mathbf{v}` by a factor of :math:`s`.
:param s: A scalar number
:param v: A vector
:return: The vector :math:`s \mathbf{v}`.
"""
# TODO: 1 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return w
def add(v1 : Vector, v2 : Vector) -> Vector:
r"""Add the two vectors ``v1`` and ``v2`` and return the sum as a ``Vector`` object.
:param v1: The first vector,
:param v2: The second vector.
:return: Their sum :math:`\mathbf{v}_1+\mathbf{v}_2`
"""
# TODO: 1 lines missing.
raise NotImplementedError("Use make_vector to make create the new vector.")
return vector_sum
def sub(v1 : Vector, v2 : Vector) -> Vector:
r"""Subtract the two vectors ``v1`` and ``v2`` and return the difference as a ``Vector`` object.
:param v1: The first vector,
:param v2: The second vector.
:return: Their difference :math:`\mathbf{v}_1-\mathbf{v}_2`
"""
# TODO: 1 lines missing.
raise NotImplementedError("Remember that x - y = x + (-1) * y.")
return diff
def hat(v):
r"""Given a ``Vector`` v1, this function returns a new vector which is orthogonal to v1 ('Tværvektoren' in Danish).
:param v: A vector :math:`\mathbf{v}`.
:return: A ``Vector`` that is orthogonal to :math:`\mathbf{v}`, i.e. :math:`\hat{\mathbf{v}}`.
"""
# TODO: 1 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return v_hat
class LineSegment:
"""A class that represents a line segment."""
def make_line_segment(p : Vector, q : Vector) -> LineSegment:
r"""Construct a ``LineSegment`` connecting the two vectors ``p`` and ``q``.
Note you have some freedom in terms of how you wish to store ``p`` and ``q`` in the ``LineSegment`` object;
i.e. you can either store ``p`` and ``q`` directly similar to the ``Vector``, or perhaps do something slightly
smarter.
:param p: The vector the line segments begins in
:param q: The line segment the vector ends in
:return: A LineSegment class representing the LineSegment.
"""
# TODO: 3 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return l
def point_on_line(l : LineSegment, t : float) -> Vector:
r"""Interpolate between the end-points of the LineSegment.
Given a line segment, the function will interpolate between the end-points using :math:`t \in [0,1]`
and return a Vector. This can be used to compute any point on the LineSegment and :math:`t=0,1` will
correspond to the end-points. The order is not important for the following problems.
:param l: A line defined by the two end-points vectors
:param t: Weighting of the two end-point in the inerpolation, :math:`t \in [0,1]`.
:return: A ``Vector`` corresponding to :math:`\mathbf{p} + (\mathbf{q}-\mathbf{p})t`.
"""
# TODO: 1 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return s
def plot_vector(v: Vector):
"""Plot a Vector using matplotlib.
:param v: Vector to plot.
"""
plt.plot(v.x, v.y, 'ro')
def plot_line(l : LineSegment):
r"""Plot a LineSegment using matplotlib.
:param l: The line segment to plot
"""
p = point_on_line(l, 0)
q = point_on_line(l, 1)
plt.plot([p.x, q.x], [p.y, q.y], 'k-')
class SquareWithPosition:
"""Corresponds to a square located in space. I.e., each corner has an :math:`(x,y)` coordinate."""
def make_square_with_position(x : float,y : float, width : float) -> SquareWithPosition:
r"""Create a ``SquareWithPosition`` instance with lower-left corner at :math:`(x,y)` and the given ``width``.
Note: It is up to you how you want to store the information in the SquareWithLocation-class. You can for instance
choose to store the four corners as ``Vector``-objects, the four sides as ``LineSegment``-objects.
:param x: :math:`x`-position of the lower-left corner
:param y: :math:`y`-position of the lower-left corner
:param width: The side-length of the rectangle
:return: A ``SquareWithLocation`` object.
"""
# TODO: 5 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return s
def intersect(l1: LineSegment, l2: LineSegment) -> Vector:
"""Get the intersection between two line segments assuming they intersects.
:param l1: First line
:param l2: Second line
:return: A ``Vector`` representing the point of intersection.
"""
# TODO: Code has been removed from here.
raise NotImplementedError("Insert your solution and remove this error.")
return p
def do_they_intersect(l1 : LineSegment, l2 : LineSegment) -> bool:
"""Determine if two line segments intersects.
:param l1: First line segment
:param l2: Second line segment
:return: ``True`` if the two line segments intersects, otherwise ``False``.
"""
# TODO: 3 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return is_intersecting
def square_to_lines(sq : SquareWithPosition) -> list:
"""Return a list of ``LineSegment``-objects corresponding to the four sides.
:param sq: The square
:return: A list of four sides, ``[l1, l2, l3, l4]``
"""
# TODO: 1 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return lines
def plot_square(sq: SquareWithPosition):
"""Plot the ``SquareWithLocation`` instance.
:param sq: The square to plot
"""
# TODO: 2 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
def get_intersections(sq : SquareWithPosition, l : LineSegment) -> list:
"""Return a list of ``Vector``-objects corresponding to all intersections between the square and line segment.
:param sq: A square
:param l: A line segment
:return: A list of 0, 1, or 2 ``Vector``-objects corresponding to the intersections.
"""
# TODO: 1 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
return intersections
def plot_intersections(sq : SquareWithPosition, l : LineSegment):
"""Plot all intersections between the square and line.
:param sq: A square
:param l: A line segment
"""
# TODO: 2 lines missing.
raise NotImplementedError("Insert your solution and remove this error.")
if __name__ == '__main__':
square = make_square_with_position(1,1,2)
line = make_line_segment(make_vector(-1, -1), make_vector(2, 4) )
vec = make_line_segment(make_vector(1, 1), make_vector(3, 1) )
plot_square(square)
plot_line(line)
plot_intersections(square, line)
plt.show()
"""This package represents exercise 10."""
"""Exercise 10.1: A hospital with doctors and patients."""
illnesses = {'hanging toenail': ('feets', 200),
'stepped on lego': ('feets', 100),
'headache': ('head', 100),
'toothache': ('head', 200),
}
class Person:
"""A simple class that represents a person."""
# TODO: 20 lines missing.
# TODO: 73 lines missing.
if __name__ == "__main__":
p = Person("Patricia Smith", 24, 'f') # use the __init__-method to construct the person.
print(p) # Call the str-method
"""A small example of how to use the super()-keyword."""
class Pet:
"""A basic Pet-class."""
def __init__(self, name, age):
"""Create a new Pet object.
:param name: The name of the Pet
:param age: The age of the Pet.
"""
self.name = name
self.age = age
def __str__(self):
"""
Automatically called by ``print(..)``.
:return: A string representation such as ``"Fido (3 years old)"``.
"""
return f"{self.name} ({self.age} years old)"
class SimpleCat(Pet):
"""A simple Cat-class. This example contains duplicated code."""
def __init__(self, name, age, favorite_food):
"""Construct a new Cat-object. Asides the name and age, it also has a favorite food.
:param name: The name of the cat, for instance ``'Mr. Whiskers'``
:param age: The age, for instance 3.
:param favorite_food: The favorite food, for instance ``"fish"``.
"""
self.name = name
self.age = age
self.favorite_food = favorite_food
class ImprovedCat(Pet):
"""The ImprovedCat uses super() to avoid duplicate code."""
def __init__(self, name, age, favorite_food):
"""Construct a new Cat-object. The example function similar to the one before.
:param name: The name of the cat, for instance ``'Mr. Whiskers'``
:param age: The age, for instance 3.
:param favorite_food: The favorite food, for instance ``"fish"``.
"""
super().__init__(name, age) # Call the Pet.__init__()-method.
self.favorite_food = favorite_food # We stll need to store this one.
if __name__ == "__main__":
a = SimpleCat("Mr. Whiskers", 3, "fish")
print(a)
print(a.favorite_food)
# Now let's make an improved cat.
b = SimpleCat("Mr. Super-duper whiskers", 4, "whatever you are eating")
print(b)
print(b.favorite_food)
"""Project work for week 10: A do-it-yourself sympy."""
import math
class Expression:
"""A mathematical expression. Can represent a constant `1`, a symbol such as `x`, or a function such as `sin(x)`."""
def evaluate(self, substitutions : dict) -> float:
"""Evaluate the expression and return a floating-point number.
The input argument is a dictionary which is used to evaluate all symbols. E.g. if ``substitutions = {'x': 3}``,
this means all instances of the symbolic expression ``x`` will be replaced by ``3``.
:param substitutions: A dictionary of substitutions. The keys are strings, and the values are numbers.
:return: A floating-point number this expression has been evaluated to.
"""
return 0
def differentiate(self, variable : str) -> 'Expression':
r"""Differentiate the expression with respect to the variable, specified as e.g. ``"x"``.
Note that if this expression is a function of other variables, we must use the chain-rule to recursively
differentiate the other expressions. e.g. :math:`\sin(f(x))' = \cos(f(x))f'(x)`.
:param variable: The variable we differentiate with respect to (example: ``"x"``)
:return: A class that inherits from ``Expression`` which corresponds to the derivative with respect to the given variable.
"""
return Expression()
def __str__(self) -> str:
"""Provide a string representation of the expression. The function is called automatically by ``print``.
:return: A string representation of this expression.
"""
return "Remember to implement the __str__()-function."
# TODO: Code has been removed from here.
if __name__ == "__main__":
# construct some symbolic expressions
c1 = Constant(2)
c2 = Constant(3)
v = Variable('x')
# construct expression (2 * x + 3)
expr1 = Addition(Multiplication(c1, v), c2)
print(expr1)
print(expr1.differentiate("x"))
# let's evaluate this expression for x = 4
print(expr1.evaluate( {'x': 4} )) # prints 11
# let's differentiate this expression with respect to x
# it should be (2 * 1 + 0) = 2
diff_expr1 = expr1.differentiate('x')
# evaluate the derivative at x = 4
print(diff_expr1.evaluate( {'x': 2} )) # prints 2
# construct another expression (x ^ 3)
expr2 = Sin(v) # Constant(3))
# let's evaluate this expression for x = 2
print(expr2.evaluate( {'x': 2} )) # prints 8
print(expr2)
# let's differentiate this expression with respect to x
# it should be 3 * x ^ 2 which equals 3 * 2 ^ 2 = 12 at x = 2
diff_expr2 = expr2.differentiate('x')
print(diff_expr2)
print( Sin(Cos(Cos(v))).differentiate('y') )
# evaluate the derivative at x = 2
print(diff_expr2.evaluate({'x': 2})) # prints 12
# Doctor
# Person
# Patient
"""Dummy (test) project from 02465."""
This diff is collapsed.
import string
from unitgrade import hide
from cp import minput
from unittest.mock import patch
import io
import unittest
from unitgrade import UTestCase, Report
import math
class TestTheFunctionToBisect(UTestCase):
def test_f(self):
from cp.ex03.bisect import f
self.assertAlmostEqual(f(0), 0.1411200080598672)
self.assertAlmostEqual(f(1), 0.4871688735635369 )
self.assertAlmostEqual(f(2), -0.9484917234010158)
self.assertAlmostEqual(f(math.pi), 0.6145000731172406 )
self.assertAlmostEqual(f(-10), 0.244199939520782)
self.assertAlmostEqual(f(117), -0.9996260520700749)
class TestIsThereARoot(UTestCase):
def test_root_exists(self):
from cp.ex03.bisect import is_there_a_root
self.assertTrue(is_there_a_root(1, 3)) # root exists between 0 and pi
def test_no_root_exists(self):
from cp.ex03.bisect import is_there_a_root
self.assertFalse(is_there_a_root(3.2, 3.8)) # no root exists between 0 and 2pi
def test_root_not_found(self):
from cp.ex03.bisect import is_there_a_root
self.assertFalse(is_there_a_root(1, 3.5))
class TestBisect(UTestCase):
def test_base_case(self):
from cp.ex03.bisect import bisect
self.assertAlmostEqual(bisect(1, 3, 0.1), 1.8125)
self.assertAlmostEqual(bisect(1, 5.5, 0.1), 4.0234375)
def test_tolerances(self):
from cp.ex03.bisect import bisect
self.assertAlmostEqual(bisect(2, 3.5, 10), 2.75)
self.assertAlmostEqual(bisect(2, 3.5, 0.1), 3.03125)
def test_no_solution(self):
from cp.ex03.bisect import bisect
self.assertTrue(math.isnan(bisect(1, 3.5, 1)))
class HangmanIsGuessed(UTestCase):
def test_is_word_guessed(self):
from cp.ex04.hangman import is_word_guessed
self.assertTrue(is_word_guessed("dog", "tdohg"))
self.assertTrue(is_word_guessed("dog", "tdohg"))
self.assertFalse(is_word_guessed("dog", ""))
self.assertFalse(is_word_guessed("species", "sdcbwegk"))
self.assertTrue(is_word_guessed("species", "qseicps"))
class HangmanGuessedWord(UTestCase):
def test_get_guessed_word(self):
from cp.ex04.hangman import get_guessed_word
self.assertEqual(get_guessed_word('cow', 'kcw'), 'c_ w')
self.assertEqual(get_guessed_word('apple', ''), '_ _ _ _ _ ')
self.assertEqual(get_guessed_word('tasks', 'ws'), '_ _ s_ s')
class HangmanAvailableLetters(UTestCase):
def test_get_available_letters(self):
from cp.ex04.hangman import get_available_letters
self.assertEqual(len(get_available_letters('')), 26)
self.assertEqual(set(get_available_letters('bcdew')), set(string.ascii_lowercase).difference('bcdew'))
class Hangman(UTestCase):
@unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
def test_hangman_startup(self, mock_stdout):
from cp.ex04.hangman import hangman
try:
with unittest.mock.patch('builtins.input', minput([None])):
hangman("cow", guesses=4)
except GeneratorExit as e:
pass
out = mock_stdout.getvalue()
lines = out.splitlines()
self.assertEqual(len(lines), 4, msg='You must print 4 lines')
self.assertEqual(lines[0], 'Hangman! To save Bob, you must guess a 3 letter word within 4 attempts.', msg='First printed line is wrong')
self.assertEqual(lines[1], '----', msg='Second printed line is wrong')
self.assertEqual(lines[2], 'You have 4 guesses left.', msg='Third printed line is wrong')
self.assertTrue("." in lines[3] and ":" in lines[3], msg="Your fourth line must have both a colon and a period")
fp = lines[3].split(".")[0].split(":")[1].strip()
self.assertEqual(len(fp), 26, msg="The alphabet has 26 letters.")
self.assertEqual(set(fp), set(string.ascii_lowercase), msg="You failed to print the alphabet")
def chk_alphabet(self, line, missing):
self.assertTrue("." in line and ":" in line, msg="Your alphabet printout must have both a colon and a period")
fp = line.split(".")[0].split(":")[1].strip()
ab = set( [c for c in string.ascii_lowercase if c not in missing])
self.assertEqual(len(fp), len(ab), msg="The alphabet printout has to few characters")
self.assertEqual(set(fp), ab, msg="You failed to print the alphabet")
@unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
def test_hangman_correct(self, mock_stdout):
from cp.ex04.hangman import hangman
try:
with unittest.mock.patch('builtins.input', minput(['w', None])):
hangman("cow", guesses=4)
except GeneratorExit as e:
pass
out = mock_stdout.getvalue()
lines = out.splitlines()
self.assertEqual(len(lines), 8, msg='You must print 8 lines')
self.assertEqual(lines[-4], 'Good guess: _ _ w', msg='Format guessed word correctly')
self.assertEqual(lines[-3], '----')
self.assertEqual(lines[-2], 'You have 3 guesses left.', msg='Third printed line is wrong')
self.chk_alphabet(lines[-1], missing='w')
@unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
def test_hangman_false(self, mock_stdout):
from cp.ex04.hangman import hangman
try:
with unittest.mock.patch('builtins.input', minput(['q', None])):
hangman("doggy", guesses=4)
except GeneratorExit as e:
pass
out = mock_stdout.getvalue()
lines = out.splitlines()
self.assertEqual(len(lines), 8, msg='You must print 8 lines')
self.assertEqual(lines[-4], 'Oh no: _ _ _ _ _ ', msg='Format guessed word correctly')
self.assertEqual(lines[-3], '----')
self.assertEqual(lines[-2], 'You have 3 guesses left.', msg='Third printed line is wrong')
self.chk_alphabet(lines[-1], missing='q')
@unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
def test_hangman_win(self, mock_stdout):
from cp.ex04.hangman import hangman
try:
with unittest.mock.patch('builtins.input', minput(['q', 'd', 'g', 'o', 'y', None])):
hangman("doggy", guesses=8)
except GeneratorExit as e:
pass
out = mock_stdout.getvalue()
lines = out.splitlines()
self.assertEqual(len(lines), 22, msg='You must print 22 lines')
self.assertTrue(lines[-1], 'Your score is 20')
@unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
def test_hangman_loose(self, mock_stdout):
from cp.ex04.hangman import hangman
try:
with unittest.mock.patch('builtins.input', minput(['%'])):
hangman("cat", guesses=5)
except GeneratorExit as e:
pass
out = mock_stdout.getvalue()
lines = out.splitlines()
self.assertEqual(len(lines), 5, msg='You must print 5 lines')
self.assertTrue(lines[-1], 'Game over :-(. Your score is 0 points.')
class Project2(Report):
title = "Project 2"
remote_url = "https://cp.pages.compute.dtu.dk/02002public/_static/evaluation/"
abbreviate_questions = True
questions = [(TestTheFunctionToBisect, 5),
(TestIsThereARoot, 15),
(TestBisect, 15),
(HangmanIsGuessed, 10),
(HangmanGuessedWord, 10),
(HangmanAvailableLetters, 10),
(Hangman, 30),
]
import cp
pack_imports = [cp]
if __name__ == "__main__":
from unitgrade import evaluate_report_student
evaluate_report_student(Project2())
File deleted
File deleted
File deleted
File deleted
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment