diff --git a/cp/ex05/average.py b/cp/ex05/average.py new file mode 100644 index 0000000000000000000000000000000000000000..d9d5c4077a4324bc442beee32bd5b9b206c550ea --- /dev/null +++ b/cp/ex05/average.py @@ -0,0 +1,9 @@ +"""Exercise 5.2. Average of lists.""" + +def calculate_average(nums: list) -> float: + """Return the average of a list of numbers. + + :param nums: list of numbers + :return: average of list + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/best_buy.py b/cp/ex05/best_buy.py new file mode 100644 index 0000000000000000000000000000000000000000..bddb33a61a082fce976fada650643102e4ed2002 --- /dev/null +++ b/cp/ex05/best_buy.py @@ -0,0 +1,12 @@ +"""Exercise 5.11. Best Buy.""" + +def best_buy(prices: list, money: int, start_index: int, reverse: bool) -> int: + """Return the number of items that can be bought with the given amount of money. The function should be able to handle arbitrary starting points and to run the list in reverse. + + :param prices: list of prices + :param money: amount of money + :param start_index: starting index in list + :param reverse: boolean to indicate if list should be run in reverse + :return: number of items that can be bought with the given amount of money + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/conditioned_maximum.py b/cp/ex05/conditioned_maximum.py new file mode 100644 index 0000000000000000000000000000000000000000..c7d230ded640e8cfa59be25c1c3571c50522a015 --- /dev/null +++ b/cp/ex05/conditioned_maximum.py @@ -0,0 +1,21 @@ +"""Exercise 5.3-5.4. Conditioned maximum.""" + +def conditioned_maximum(nums: list, threshold: float) -> float: + """Return the maximum of a list of numbers, that is strictly smaller than the given threshold. + + :param nums: list of numbers + :param threshold: limit for maximum value + :return: maximum of list thats smaller than the threshold + """ + # TODO: Code has been removed from here. + + +def conditioned_maximum_name(nums: list, names: list, threshold: float) -> str: + """Return the name of the maximum of a list of numbers, that is smaller than the given threshold. + + :param nums: list of numbers with animal heights. + :param names: list of animal names + :param threshold: limit for maximum value + :return: animal name with the corresponding maximum height, which is shorter than the threshold height. + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/multiples.py b/cp/ex05/multiples.py new file mode 100644 index 0000000000000000000000000000000000000000..6a5a0de8dbd6a62b03918746bc5454914a73f97d --- /dev/null +++ b/cp/ex05/multiples.py @@ -0,0 +1,19 @@ +"""Exercise 5.8.-5-9. Count multiples.""" + +def count_multiples(numbers: list, m: int) -> int: + """Count the number of numbers that are divisible by m. + + :param numbers: list of numbers + :param m: number to divide by + :return: number of numbers that are divisible by m + """ + # TODO: Code has been removed from here. + +def multiples_list(numbers: list, m: int) -> list: + """Make a list with all numbers from a list that are divisible by m. + + :param numbers: list of numbers + :param m: number to divide by + :return: list of numbers that are divisible by m + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/rectangular.py b/cp/ex05/rectangular.py new file mode 100644 index 0000000000000000000000000000000000000000..f40ba207452ae9bc27ce3490c288c8796726aae3 --- /dev/null +++ b/cp/ex05/rectangular.py @@ -0,0 +1,9 @@ +"""Exercise 5.6. Rectangular list.""" + +def is_rectangular(nested_list: list) -> bool: + """Check if a list is rectangular. + + :param nested_list: nested list + :return: True if list is rectangular, False otherwise + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/short_words.py b/cp/ex05/short_words.py new file mode 100644 index 0000000000000000000000000000000000000000..b688235111a3f423d8f0d574665da3152903ee3b --- /dev/null +++ b/cp/ex05/short_words.py @@ -0,0 +1,10 @@ +"""Exercise 5.5. short words.""" + +def short_words(words: str, max_len: int) -> str: + """Return a string of words that are shorter than max_len. + + :param words: string of words + :param max_len: maximum length of words + :return: string of words that are shorter than max_len + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/tictactoe.py b/cp/ex05/tictactoe.py new file mode 100644 index 0000000000000000000000000000000000000000..74cba4f7ad8ec642ec8fbb87ab3a9f5b76a03018 --- /dev/null +++ b/cp/ex05/tictactoe.py @@ -0,0 +1,35 @@ +"""Exercise 5.12-5-16. TicTacToe.""" +def get_game_state(board: list) -> str: + """Check if a player has won the game, if it's a draw, or if it's ongoing. + + :param board: List of lists of strings representing the game board. + :return: A string which is 'X' if player 'X' won, 'O' if player 'O' has won, 'Draw' if the game is a draw, or '-' if the game is ongoing. + """ + # TODO: Code has been removed from here. + +def update_board(board : list, player: str, position: list) -> list: + """Update the game board with the player's move. + + :param board: List of lists of strings representing the game board. + :param player: Player making the move ('X' or 'O'). + :param position: List containing two integer indices [row, column] indicating the position to make a move. + :return: Updated game board after the move. + """ + # TODO: Code has been removed from here. + +def print_board(board: list): + """Print the current state of the game board. + + :param board: List of lists of strings representing the game board. + """ + # TODO: Code has been removed from here. + +def tictactoe(board: list, player: str, position: list) -> list: + """Play a move in the Tic-Tac-Toe game and determine the winner. + + :param board: List of lists of strings representing the game board. + :param player: Player making the move ('X' or 'O'). + :param position: List containing two integer indices [row, column] indicating the position to make a move. + :return: Updated game board after the move. + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/vector_add.py b/cp/ex05/vector_add.py new file mode 100644 index 0000000000000000000000000000000000000000..11c2f811d77a9e12991d5ac2049c7cdeb440dfb5 --- /dev/null +++ b/cp/ex05/vector_add.py @@ -0,0 +1,10 @@ +"""Exercise 5.7. Vector additon.""" + +def vector_add(v: list, w: list) -> list: + """Add two vectors. + + :param v: vector 1 (list of numbers) + :param w: vector 2 (list of numbers, same length as v) + :return: sum of v and w (list of number) + """ + # TODO: Code has been removed from here. diff --git a/cp/ex05/water_height.py b/cp/ex05/water_height.py new file mode 100644 index 0000000000000000000000000000000000000000..396f4c901611160a83d2e7f03ae2837cbbb8d625 --- /dev/null +++ b/cp/ex05/water_height.py @@ -0,0 +1,10 @@ +"""Exercise 5.10. Water height.""" + +def water_height(h0: int, r: list) -> int: + """Calculate the water height after multiple days of rain. + + :param: h0: initial height of the water + :param: r: list of rain showers + :return: height of water after days of rain + """ + # TODO: Code has been removed from here. diff --git a/cp/tests/tests_week05.py b/cp/tests/tests_week05.py new file mode 100644 index 0000000000000000000000000000000000000000..33c82a9fb04271b49a061423bfd6d4e775eb20c8 --- /dev/null +++ b/cp/tests/tests_week05.py @@ -0,0 +1,156 @@ +from unitgrade import Report +import cp +from unitgrade import UTestCase +import unittest +import io +from unittest.mock import patch + +class Week05Average(UTestCase): + def test_average(self): + from cp.ex05.average import calculate_average + self.assertAlmostEqual(calculate_average([1,2,3,4,5]),3) + self.assertAlmostEqual(calculate_average([1,2,3,4,5,6,7,8,9,10]),5.5) + +class Week05ConditionedMax(UTestCase): + def test_conditioned_maximum(self): + from cp.ex05.conditioned_maximum import conditioned_maximum + self.assertAlmostEqual(conditioned_maximum([1,2,3,4,5],3),2) + self.assertAlmostEqual(conditioned_maximum([1,2,3,4,5],6),5) + + def test_conditioned_maximum_name(self): + from cp.ex05.conditioned_maximum import conditioned_maximum_name + self.assertEqual(conditioned_maximum_name([1,2,3,4,5],["one","two","three","four","five"],3),"two") + self.assertEqual(conditioned_maximum_name([1,2,3,4,5],["one","two","three","four","five"],6),"five") + +class Week05Shortwords(UTestCase): + def test_shortwords(self): + from cp.ex05.short_words import short_words + self.assertEqual(short_words("This is a string", 4), "is a") + self.assertEqual(short_words("This is a string", 5), "This is a") + self.assertEqual(short_words("This is a string", 1), "") + self.assertEqual(short_words("Oneword", 2), "") + +class Week05Rectangular(UTestCase): + def test_is_rectangular(self): + from cp.ex05.rectangular import is_rectangular + self.assertTrue(is_rectangular([[1,2,3],[4,5,6]])) + self.assertTrue(is_rectangular([[1,2],['cat', 'dog'],[5,6]])) + self.assertTrue(is_rectangular([[1,2,3,4,5,6]])) + self.assertTrue(is_rectangular([[1],[2],[3],[4],[5],[6]])) + self.assertIs(is_rectangular([[1,2,3],[4,5]]), False) + self.assertIs(is_rectangular([[1,2,3],[4,5,6],[]]), False) + +class Week05VectorMath(UTestCase): + def test_vector_add(self): + from cp.ex05.vector_add import vector_add + self.assertEqual(vector_add([1,2,3],[4,5,6]),[5,7,9]) + +class Week05Multiples(UTestCase): + def test_count_multiples(self): + from cp.ex05.multiples import count_multiples + self.assertEqual(count_multiples([1,2,3,4,5,6,7,8,9,10],3),3) + self.assertEqual(count_multiples([1,2,3,4,5,6,7,8,9,10],2),5) + self.assertEqual(count_multiples([1,2,3,4,5,6,7,8,9,10],11),0) + + def test_multiples_list(self): + from cp.ex05.multiples import multiples_list + self.assertEqual(multiples_list([1,2,3,4,5,6,7,8,9,10],3),[3,6,9]) + self.assertEqual(multiples_list([1,2,3,4,5,6,7,8,9,10],2),[2,4,6,8,10]) + self.assertEqual(multiples_list([1,2,3,4,5,6,7,8,9,10],11),[]) + +class Week05WaterHeights(UTestCase): + def test_water_height(self): + from cp.ex05.water_height import water_height + self.assertEqual(water_height(5, [1,2,3]), 5) + self.assertEqual(water_height(2, [1,1]), 0) + self.assertEqual(water_height(0, [1,3]), 1) + +class Week05BestBuy(UTestCase): + def test_bestbuy(self): + from cp.ex05.best_buy import best_buy + self.assertEqual(best_buy([3, 2, 1, 3, 5], 10, 0, False), 4) + self.assertEqual(best_buy([3, 2, 1, 3, 5], 3, 1, False), 2) + self.assertEqual(best_buy([3, 2, 1, 3, 5], 8, 4, True), 2) + self.assertEqual(best_buy([3, 2, 1, 3, 5], 15, 4, True), 5) + + +class Week05TicTacToePrintBoard(UTestCase): + def test_print_board(self): + from cp.ex05.tictactoe import print_board + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + print_board([['-','X','-'],['-','-','O'],['X','-','-']]) + out = mock_stdout.getvalue().splitlines() + self.assertEqual(len(out), 3, msg="You did not print out 3 separate lines") + self.assertEqual(out[0], "-X-") + self.assertEqual(out[1], "--O") + self.assertEqual(out[2], "X--") + +class Week05TicTacToeGetGameState(UTestCase): + def test_get_game_state(self): + from cp.ex05.tictactoe import get_game_state + self.assertEqual(get_game_state([['-','-','-'],['-','-','-'],['-','-','-']]),'-') + self.assertEqual(get_game_state([['X','X','X'],['-','-','-'],['-','-','-']]),'X') + self.assertEqual(get_game_state([['-','-','-'],['X','X','X'],['-','-','-']]),'X') + self.assertEqual(get_game_state([['X','-','-'],['-','X','-'],['O','O','X']]),'X') + self.assertEqual(get_game_state([['X','-','-'],['-','X','-'],['O','O','O']]),'O') + self.assertEqual(get_game_state([['X','O','X'],['X','O','O'],['O','X','X']]),'Draw') + +class Week05TicTacToeUpdateBoard(UTestCase): + def test_update_board(self): + from cp.ex05.tictactoe import update_board + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + self.assertEqual(update_board([['-','-','-'],['-','-','-'],['-','-','-']],'X',[1,0]),[['-', '-', '-'], ['X', '-', '-'], ['-', '-', '-']]) + self.assertEqual(update_board([['X','X','-'],['-','-','-'],['-','-','-']],'O',[0,2]),[['X', 'X', 'O'], ['-', '-', '-'], ['-', '-', '-']]) + self.assertEqual(update_board([['-','-','-'],['X','X','X'],['-','-','-']],'X',[2,0]),[['-', '-', '-'], ['X', 'X', 'X'], ['X', '-', '-']]) + self.assertEqual(update_board([['X','-','-'],['-','X','-'],['O','O','X']],'O',[1,2]),[['X', '-', '-'], ['-', 'X', 'O'], ['O', 'O', 'X']]) + self.assertEqual(update_board([['X','-','-'],['-','X','-'],['O','O','O']],'X',[0,2]),[['X', '-', 'X'], ['-', 'X', '-'], ['O', 'O', 'O']]) + self.assertEqual(update_board([['O','-','-'],['O','X','-'],['O','X','X']],'O',[0,2]),[['O', '-', 'O'], ['O', 'X', '-'], ['O', 'X', 'X']]) + out = mock_stdout.getvalue() + self.assertEqual(out, "", "You should not print anything for valid moves") + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + update_board([['O','-','-'],['O','X','-'],['O','X','X']],'O',[0,0]) + out = mock_stdout.getvalue().strip() + self.assertEqual(out, "Invalid move!") + + + +class Week05TicTacToeMain(UTestCase): + def test_tictactoe_main(self): + from cp.ex05.tictactoe import tictactoe + with unittest.mock.patch('sys.stdout', new=io.StringIO()) as mock_stdout: + tictactoe([['X','X','-'],['-','O','-'],['O','-','-']],'O',[0,2]) + out = mock_stdout.getvalue().splitlines() + self.assertEqual(len(out), 4, msg="You did not print out 4 separate lines") + self.assertEqual(out[0], "XXO") + self.assertEqual(out[1], "-O-") + self.assertEqual(out[2], "O--") + self.assertEqual(out[3],"Player O won!") + + + + + +class Week05Tests(Report): + title = "Tests for week 05" + version = 0.1 + url = "https://gitlab.compute.dtu.dk/cp/02002students/-/blob/master/cp/tests" + pack_imports = [cp] + individual_imports = [] + questions = [ + (Week05Average, 5), + (Week05ConditionedMax, 10), + (Week05Shortwords, 5), + (Week05Rectangular, 10), + (Week05VectorMath, 10), + (Week05Multiples, 10), + (Week05WaterHeights, 10), + (Week05BestBuy, 10), + (Week05TicTacToePrintBoard, 10), + (Week05TicTacToeGetGameState, 10), + (Week05TicTacToeUpdateBoard, 10), + (Week05TicTacToeMain, 10) + ] + +if __name__ == '__main__': + from unitgrade import evaluate_report_student + evaluate_report_student(Week05Tests()) diff --git a/cp/tests/unitgrade_data/Week05Average.pkl b/cp/tests/unitgrade_data/Week05Average.pkl new file mode 100644 index 0000000000000000000000000000000000000000..e86becc5db2f84713d1a2a0d7f9fa351ffd2bc28 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05Average.pkl differ diff --git a/cp/tests/unitgrade_data/Week05BestBuy.pkl b/cp/tests/unitgrade_data/Week05BestBuy.pkl new file mode 100644 index 0000000000000000000000000000000000000000..011ca316797a8338b36d5be59766248506a78507 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05BestBuy.pkl differ diff --git a/cp/tests/unitgrade_data/Week05ConditionedMax.pkl b/cp/tests/unitgrade_data/Week05ConditionedMax.pkl new file mode 100644 index 0000000000000000000000000000000000000000..f343b4d8fd795f2e6925d0b9541c7d66dcd4f311 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05ConditionedMax.pkl differ diff --git a/cp/tests/unitgrade_data/Week05Multiples.pkl b/cp/tests/unitgrade_data/Week05Multiples.pkl new file mode 100644 index 0000000000000000000000000000000000000000..2beaa28a50997a30ff5dd8bf92554cb7955d94db Binary files /dev/null and b/cp/tests/unitgrade_data/Week05Multiples.pkl differ diff --git a/cp/tests/unitgrade_data/Week05Rectangular.pkl b/cp/tests/unitgrade_data/Week05Rectangular.pkl new file mode 100644 index 0000000000000000000000000000000000000000..df1f9c24148008e089561a73025bafa0ce0fcc11 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05Rectangular.pkl differ diff --git a/cp/tests/unitgrade_data/Week05Shortwords.pkl b/cp/tests/unitgrade_data/Week05Shortwords.pkl new file mode 100644 index 0000000000000000000000000000000000000000..526a554c7dbec704e3e55c38053e0e1f58dc9b4a Binary files /dev/null and b/cp/tests/unitgrade_data/Week05Shortwords.pkl differ diff --git a/cp/tests/unitgrade_data/Week05TicTacToeGetGameState.pkl b/cp/tests/unitgrade_data/Week05TicTacToeGetGameState.pkl new file mode 100644 index 0000000000000000000000000000000000000000..a162e6718cf7a55ff6bb60fa6fd05ac9406551ad Binary files /dev/null and b/cp/tests/unitgrade_data/Week05TicTacToeGetGameState.pkl differ diff --git a/cp/tests/unitgrade_data/Week05TicTacToeMain.pkl b/cp/tests/unitgrade_data/Week05TicTacToeMain.pkl new file mode 100644 index 0000000000000000000000000000000000000000..e9a426dbc0377710a67adcf025ae7c63c273bb05 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05TicTacToeMain.pkl differ diff --git a/cp/tests/unitgrade_data/Week05TicTacToePrintBoard.pkl b/cp/tests/unitgrade_data/Week05TicTacToePrintBoard.pkl new file mode 100644 index 0000000000000000000000000000000000000000..312b7645214033a72fad1bccf0db3d2b043c39b2 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05TicTacToePrintBoard.pkl differ diff --git a/cp/tests/unitgrade_data/Week05TicTacToeUpdateBoard.pkl b/cp/tests/unitgrade_data/Week05TicTacToeUpdateBoard.pkl new file mode 100644 index 0000000000000000000000000000000000000000..7889d3ec336bccde8311d76e28522873747acef2 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05TicTacToeUpdateBoard.pkl differ diff --git a/cp/tests/unitgrade_data/Week05VectorMath.pkl b/cp/tests/unitgrade_data/Week05VectorMath.pkl new file mode 100644 index 0000000000000000000000000000000000000000..0453dbf49e0d21a1cfd7cefdce6a765c8f1ab9d1 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05VectorMath.pkl differ diff --git a/cp/tests/unitgrade_data/Week05WaterHeights.pkl b/cp/tests/unitgrade_data/Week05WaterHeights.pkl new file mode 100644 index 0000000000000000000000000000000000000000..5271cfb6ed6f2f550d11c0e7b128a7e36b374bd4 Binary files /dev/null and b/cp/tests/unitgrade_data/Week05WaterHeights.pkl differ