diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 000000000..ddf0417c3
Binary files /dev/null and b/.DS_Store differ
diff --git a/Labs/.DS_Store b/Labs/.DS_Store
new file mode 100644
index 000000000..08a737166
Binary files /dev/null and b/Labs/.DS_Store differ
diff --git a/Labs/Lab.2/.DS_Store b/Labs/Lab.2/.DS_Store
new file mode 100644
index 000000000..5008ddfcf
Binary files /dev/null and b/Labs/Lab.2/.DS_Store differ
diff --git a/Labs/Lab.2/Lab.2.ipynb b/Labs/Lab.2/Lab.2.ipynb
index f0b38e38a..fb55044de 100644
--- a/Labs/Lab.2/Lab.2.ipynb
+++ b/Labs/Lab.2/Lab.2.ipynb
@@ -84,20 +84,41 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 83,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution here\n",
+ "def make_board(n):\n",
+ " empty = 0\n",
+ " X = 1\n",
+ " O = 2\n",
+ " board = list()\n",
+ " for i in range(n):\n",
+ " row = list()\n",
+ " for j in range(n):\n",
+ " row.append(1)\n",
+ " board.append(row)\n",
+ " return board"
]
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 6,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[[1, 1, 1], [1, 1, 1], [1, 1, 1]]\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "board = make_board(3)\n",
+ "print(board)"
]
},
{
@@ -107,7 +128,96 @@
"outputs": [],
"source": [
"# (Optional) Ask an LLM for 3 different solutions here\n",
- "# Then compare them to your own."
+ "#Solution 1\n",
+ "def make_board_1(n):\n",
+ " board = []\n",
+ " for i in range(n):\n",
+ " row = []\n",
+ " for j in range(n):\n",
+ " row.append(0)\n",
+ " board.append(row)\n",
+ " return board\n",
+ "\n",
+ "#solution 2\n",
+ "def make_board_2(n):\n",
+ " return [[0 for _ in range(n)] for _ in range(n)]\n",
+ "\n",
+ "#solution 3\n",
+ "def make_board_3(n):\n",
+ " board = []\n",
+ " for _ in range(n):\n",
+ " board.append([0] * n)\n",
+ " return board"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
For Solution 1
\n",
+ "\n",
+ "Same:
\n",
+ "\n",
+ "Both use nested loops\n",
+ "\n",
+ "Both construct the board row by row\n",
+ "\n",
+ "Both use append() to add values\n",
+ "\n",
+ "Both return an n × n list of lists\n",
+ "\n",
+ "Both are easy to understand and beginner-friendly\n",
+ "\n",
+ "\n",
+ "Different:
\n",
+ "\n",
+ "Your solution defines empty, X, and O, while Solution 1 directly uses 0\n",
+ "\n",
+ "Your solution documents the meaning of values more clearly\n",
+ "\n",
+ "Solution 1 is slightly shorter\n",
+ "\n",
+ "\n",
+ "For Solution 2
\n",
+ "\n",
+ "Same:
\n",
+ "\n",
+ "Both return an n × n Tic Tac Toe board\n",
+ "\n",
+ "Both use 0 to represent empty spaces\n",
+ "\n",
+ "Both solve the same problem correctly\n",
+ "\n",
+ "\n",
+ "Different:
\n",
+ "\n",
+ "Your solution uses explicit loops, Solution 2 uses list comprehension\n",
+ "\n",
+ "Your solution is more readable for beginners\n",
+ "\n",
+ "Solution 2 is more compact but less transparent\n",
+ "\n",
+ "Your solution clearly shows how the matrix is built step by step\n",
+ "\n",
+ "\n",
+ "For Solution 3
\n",
+ "\n",
+ "Same:
\n",
+ "\n",
+ "Both create each row separately\n",
+ "\n",
+ "Both store rows in a board list\n",
+ "\n",
+ "Both correctly initialize all cells as empty (0)\n",
+ "\n",
+ "\n",
+ "Different:
\n",
+ "\n",
+ "Your solution fills rows using an inner loop, Solution 3 uses [0] * n\n",
+ "\n",
+ "Your approach is more detailed and instructional\n",
+ "\n",
+ "Solution 3 is more concise and slightly more efficient\n"
]
},
{
@@ -117,6 +227,19 @@
"**Question:** Which solution most closely matches your solution? What are the main differences?"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Solution 1 is the closest match because:
\n",
+ "\n",
+ "It follows the same structure\n",
+ "\n",
+ "Uses the same logic\n",
+ "\n",
+ "Builds the matrix step-by-step just like my implementation"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -138,20 +261,45 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 84,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution \n",
+ "def draw_board(r,c):\n",
+ " for i in range(r):\n",
+ " row = \"\"\n",
+ " empty = \" \"\n",
+ " print(\" --- \" *c)\n",
+ " for j in range(c):\n",
+ " row += \"| \" + empty + \" |\"\n",
+ " \n",
+ " print(row)\n",
+ " print(\" --- \" *c)"
]
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 86,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " --- --- --- \n",
+ "| || || |\n",
+ " --- --- --- \n",
+ "| || || |\n",
+ " --- --- --- \n",
+ "| || || |\n",
+ " --- --- --- \n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution \n",
+ "draw_board(3,3)"
]
},
{
@@ -163,20 +311,48 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 88,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution \n",
+ "def draw_board(board):\n",
+ " n = len(board)\n",
+ " m = len(board[0])\n",
+ " icons = {1:\"X\",2:\"O\",0:\" \"}\n",
+ " for i in range(n):\n",
+ " row = \"\"\n",
+ " print(\" --- \"*m)\n",
+ " for j in range(m):\n",
+ " row += (f\"| {icons[int(board[i][j])]} |\")\n",
+ " print(row)\n",
+ "\n",
+ " print(\" --- \"*m)"
]
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": 89,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " --- --- --- \n",
+ "| X || X || X |\n",
+ " --- --- --- \n",
+ "| X || X || X |\n",
+ " --- --- --- \n",
+ "| X || X || X |\n",
+ " --- --- --- \n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution \n",
+ "b= make_board(3)\n",
+ "draw_board(b)"
]
},
{
@@ -193,27 +369,51 @@
"Here are some example inputs you can use to test your code:\n"
]
},
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Write your solution here"
- ]
- },
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
- "# Test your solution here"
+ "# Write your solution \n",
+ "def check_play(board):\n",
+ " r = len(board)\n",
+ " c = len(board[0])\n",
+ "\n",
+ " for i in range(r):\n",
+ " if all(board[i][j] == 1 for j in range(c)):\n",
+ " return 1\n",
+ " elif all(board[i][j] == 2 for j in range(c)):\n",
+ " return 2\n",
+ " \n",
+ " for j in range(c):\n",
+ " if all(board[i][j] == 1 for i in range(r)):\n",
+ " return 1\n",
+ " elif all(board[i][j] == 2 for i in range(r)):\n",
+ " return 2\n",
+ " \n",
+ " \n",
+ " if all(board[i][i] == 1 for i in range(r)):\n",
+ " return 1\n",
+ " elif all(board[i][i] == 2 for i in range(r)):\n",
+ " return 2\n",
+ "\n",
+ " if all(board[i][r-1-i] == 1 for i in range(r)):\n",
+ " return 1\n",
+ " elif all(board[i][r-1-i] == 2 for i in range(r)):\n",
+ " return 2\n",
+ "\n",
+ "\n",
+ " for i in range(r):\n",
+ " if any(board[i][j] == 0 for j in range(c)):\n",
+ " return -1\n",
+ " \n",
+ " return 0"
]
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
@@ -235,7 +435,38 @@
"\n",
"also_no_winner = [[1, 2, 0],\n",
"\t[2, 1, 0],\n",
- "\t[2, 1, 0]]"
+ "\t[2, 1, 0]]\n",
+ "\n",
+ "draw = [[1,2,1],\n",
+ " [2,2,1],\n",
+ " [1,1,2]]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2\n",
+ "1\n",
+ "1\n",
+ "-1\n",
+ "-1\n",
+ "0\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(check_play(winner_is_2))\n",
+ "print(check_play(winner_is_1))\n",
+ "print(check_play(winner_is_also_1))\n",
+ "print(check_play(no_winner))\n",
+ "print(check_play(also_no_winner))\n",
+ "print(check_play(draw))"
]
},
{
@@ -252,20 +483,85 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution here\n",
+ "def player_move(board, player, x, y):\n",
+ " col = ord(x.upper()) - ord('A')\n",
+ " row = int(y) - 1\n",
+ "\n",
+ " if board[row][col] != 0:\n",
+ " return \"Invalid move!\"\n",
+ "\n",
+ " board[row][col] = player\n",
+ " return True"
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 59,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | | X |\n",
+ " --- --- --- \n",
+ "2 | | X | |\n",
+ " --- --- --- \n",
+ "3 | O | O | |\n",
+ " --- --- --- \n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Press 1 for X and 2 for O 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Enter co-ordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the x co-ordinates: b\n",
+ "Enter the y co-ordinates: 1\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 59,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "b = [[1, 0, 1],\n",
+ "\t[0, 1, 0],\n",
+ "\t[2, 2, 0]]\n",
+ "draw_board(b)\n",
+ "a = input(\"Press 1 for X and 2 for O\")\n",
+ "print(\"Enter co-ordinates to make the move\")\n",
+ "x1 = input(\"Enter the x co-ordinates:\")\n",
+ "x2 = input(\"Enter the y co-ordinates:\")\n",
+ "player_move(b,a,x1,x2)"
]
},
{
@@ -277,20 +573,60 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": 92,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "def draw_board(board):\n",
+ " n = len(board)\n",
+ " m = len(board[0])\n",
+ "\n",
+ " icons = {1: \"X\", 2: \"O\", 0: \" \"}\n",
+ "\n",
+ " header = \" \"\n",
+ " for j in range(m):\n",
+ " header += f\" {chr(65 + j)} \"\n",
+ " print(header)\n",
+ "\n",
+ " for i in range(n):\n",
+ " print(\" \" + \"--- \" * m)\n",
+ " row = f\"{i + 1} \"\n",
+ " for j in range(m):\n",
+ " row += f\"| {icons[int(board[i][j])]} \"\n",
+ " row += \"|\"\n",
+ " print(row)\n",
+ "\n",
+ " print(\" \" + \"--- \" * m)"
]
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 24,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | X | X |\n",
+ " --- --- --- \n",
+ "2 | O | X | O |\n",
+ " --- --- --- \n",
+ "3 | O | X | X |\n",
+ " --- --- --- \n",
+ "4 | X | O | |\n",
+ " --- --- --- \n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution \n",
+ "draw_board([[1, 1, 1],\n",
+ "\t[2, 1, 2],\n",
+ "\t[2, 1, 1],\n",
+ " [1,2,0]])"
]
},
{
@@ -302,7 +638,7 @@
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 70,
"metadata": {
"ExecuteTime": {
"end_time": "2026-01-26T21:09:58.171399Z",
@@ -311,16 +647,39 @@
},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution here\n",
+ "def move(board,player,a,b):\n",
+ " player_move(board,player,a,b)\n",
+ " draw_board(board)\n",
+ " "
]
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 71,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | X | X |\n",
+ " --- --- --- \n",
+ "2 | O | | O |\n",
+ " --- --- --- \n",
+ "3 | O | X | X |\n",
+ " --- --- --- \n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "board1=[[1, 0, 1],\n",
+ "\t[2, 0, 2],\n",
+ "\t[2, 1, 1]]\n",
+ "move(board1,1,'b',1)"
]
},
{
@@ -334,20 +693,90 @@
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 72,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution here\n",
+ "def play_turn(board, player):\n",
+ " while True:\n",
+ " a = input(\"Enter the column letter: \")\n",
+ " b = input(\"Enter the row number: \")\n",
+ "\n",
+ " try:\n",
+ " if player_move(board, player, a, b) == True:\n",
+ " move(board, player, a, b)\n",
+ " break\n",
+ " else:\n",
+ " print(\"Invalid move! Try again.\")\n",
+ " except:\n",
+ " print(\"Invalid input! Try again.\")"
]
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 73,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter (e.g., A, B, C): s\n",
+ "Enter the row number (e.g., 1, 2, 3): 9\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Invalid input! Please enter a valid letter and row number.\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter (e.g., A, B, C): a\n",
+ "Enter the row number (e.g., 1, 2, 3): 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Invalid move! That spot is already taken.\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter (e.g., A, B, C): b\n",
+ "Enter the row number (e.g., 1, 2, 3): 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | X | X |\n",
+ " --- --- --- \n",
+ "2 | O | | O |\n",
+ " --- --- --- \n",
+ "3 | O | X | X |\n",
+ " --- --- --- \n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "bord1=[[1, 0, 1],\n",
+ "\t[2, 0, 2],\n",
+ "\t[2, 1, 1]]\n",
+ "play_game(bord1,1)"
]
},
{
@@ -364,20 +793,258 @@
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": 90,
"metadata": {},
"outputs": [],
"source": [
- "# Write yourrr solution here"
+ "# Write yourrr solution here\n",
+ "def make_board(n,m):\n",
+ " empty = 0\n",
+ " X = 1\n",
+ " O = 2\n",
+ " board = list()\n",
+ " for i in range(n):\n",
+ " row = list()\n",
+ " for j in range(m):\n",
+ " row.append(0)\n",
+ " board.append(row)\n",
+ " return board\n",
+ " \n",
+ "def play_game():\n",
+ " n = int(input(\"Enter the number of rows on board\"))\n",
+ " m = int(input(\"Enter the number of columns on board: \"))\n",
+ " board = make_board(n, m)\n",
+ " current_player = 1\n",
+ " \n",
+ " draw_board(board)\n",
+ " \n",
+ " while check_play(board) == -1:\n",
+ " print(f\"Player {current_player}'s turn\")\n",
+ " play_turn(board,current_player)\n",
+ " \n",
+ " status = check_play(board)\n",
+ " \n",
+ " if status == 1 or status == 2:\n",
+ " print(f\"Player {status} wins!\")\n",
+ " return\n",
+ " elif status == 0:\n",
+ " print(\"It's a draw!\")\n",
+ " return\n",
+ " \n",
+ " if current_player == 1:\n",
+ " current_player = 2\n",
+ " else:\n",
+ " current_player = 1"
]
},
{
"cell_type": "code",
- "execution_count": 20,
+ "execution_count": 93,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the number of rows on board 4\n",
+ "Enter the number of columns on board: 4\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | | | | |\n",
+ " --- --- --- --- \n",
+ "2 | | | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | | |\n",
+ " --- --- --- --- \n",
+ "4 | | | | |\n",
+ " --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: a\n",
+ "Enter the row number: 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | X | | | |\n",
+ " --- --- --- --- \n",
+ "2 | | | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | | |\n",
+ " --- --- --- --- \n",
+ "4 | | | | |\n",
+ " --- --- --- --- \n",
+ "Player 2's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: b\n",
+ "Enter the row number: 4\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | X | | | |\n",
+ " --- --- --- --- \n",
+ "2 | | | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | | |\n",
+ " --- --- --- --- \n",
+ "4 | | O | | |\n",
+ " --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: b\n",
+ "Enter the row number: 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | X | | | |\n",
+ " --- --- --- --- \n",
+ "2 | | X | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | | |\n",
+ " --- --- --- --- \n",
+ "4 | | O | | |\n",
+ " --- --- --- --- \n",
+ "Player 2's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: b\n",
+ "Enter the row number: 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | X | O | | |\n",
+ " --- --- --- --- \n",
+ "2 | | X | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | | |\n",
+ " --- --- --- --- \n",
+ "4 | | O | | |\n",
+ " --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: c\n",
+ "Enter the row number: 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | X | O | | |\n",
+ " --- --- --- --- \n",
+ "2 | | X | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | X | |\n",
+ " --- --- --- --- \n",
+ "4 | | O | | |\n",
+ " --- --- --- --- \n",
+ "Player 2's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: d\n",
+ "Enter the row number: 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | X | O | | |\n",
+ " --- --- --- --- \n",
+ "2 | | X | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | X | O |\n",
+ " --- --- --- --- \n",
+ "4 | | O | | |\n",
+ " --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: d\n",
+ "Enter the row number: 4\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D \n",
+ " --- --- --- --- \n",
+ "1 | X | O | | |\n",
+ " --- --- --- --- \n",
+ "2 | | X | | |\n",
+ " --- --- --- --- \n",
+ "3 | | | X | O |\n",
+ " --- --- --- --- \n",
+ "4 | | O | | X |\n",
+ " --- --- --- --- \n",
+ "Player 1 wins!\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "play_game()"
]
},
{
@@ -389,11 +1056,283 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": 94,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the number of rows on board 5\n",
+ "Enter the number of columns on board: 5\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: a\n",
+ "Enter the row number: 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 2's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: e\n",
+ "Enter the row number: 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | | | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: b\n",
+ "Enter the row number: 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | X | | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | | | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 2's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: c\n",
+ "Enter the row number: 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | X | O | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | | | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: c\n",
+ "Enter the row number: 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | X | O | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | X | | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 2's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: d\n",
+ "Enter the row number: 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | X | O | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | X | O | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: d\n",
+ "Enter the row number: 4\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | |\n",
+ " --- --- --- --- --- \n",
+ "2 | | X | O | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | X | O | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | X | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 2's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: e\n",
+ "Enter the row number: 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | O |\n",
+ " --- --- --- --- --- \n",
+ "2 | | X | O | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | X | O | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | X | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | |\n",
+ " --- --- --- --- --- \n",
+ "Player 1's turn\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column letter: e\n",
+ "Enter the row number: 5\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C D E \n",
+ " --- --- --- --- --- \n",
+ "1 | X | | | | O |\n",
+ " --- --- --- --- --- \n",
+ "2 | | X | O | | |\n",
+ " --- --- --- --- --- \n",
+ "3 | | | X | O | O |\n",
+ " --- --- --- --- --- \n",
+ "4 | | | | X | |\n",
+ " --- --- --- --- --- \n",
+ "5 | | | | | X |\n",
+ " --- --- --- --- --- \n",
+ "Player 1 wins!\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "play_game()"
]
},
{
@@ -409,20 +1348,274 @@
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 95,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution here\n",
+ "import random\n",
+ "\n",
+ "def computer_move(board, computer, human):\n",
+ " r = len(board)\n",
+ " c = len(board[0])\n",
+ "\n",
+ " def try_move(player):\n",
+ " for i in range(r):\n",
+ " for j in range(c):\n",
+ " if board[i][j] == 0:\n",
+ " board[i][j] = player\n",
+ " if check_play(board) == player:\n",
+ " return (i, j)\n",
+ " board[i][j] = 0\n",
+ " return \n",
+ "\n",
+ " move = try_move(computer)\n",
+ " if move:\n",
+ " board[move[0]][move[1]] = computer\n",
+ " return\n",
+ " move = try_move(human)\n",
+ " if move:\n",
+ " board[move[0]][move[1]] = computer\n",
+ " return\n",
+ " empty = [(i, j) for i in range(r) for j in range(c) if board[i][j] == 0]\n",
+ " if empty:\n",
+ " i, j = random.choice(empty)\n",
+ " board[i][j] = computer"
]
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 96,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the number of rows on board: 3\n",
+ "Enter the number of columns on board: 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | | | |\n",
+ " --- --- --- \n",
+ "2 | | | |\n",
+ " --- --- --- \n",
+ "3 | | | |\n",
+ " --- --- --- \n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Press 1 for 2-player game, 2 to play vs computer: 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): c\n",
+ "Enter the row (1, 2, 3...): 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | | | |\n",
+ " --- --- --- \n",
+ "2 | | | |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | | |\n",
+ " --- --- --- \n",
+ "2 | | | |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): c\n",
+ "Enter the row (1, 2, 3...): 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | | X |\n",
+ " --- --- --- \n",
+ "2 | | | |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | | X |\n",
+ " --- --- --- \n",
+ "2 | | | O |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): a\n",
+ "Enter the row (1, 2, 3...): 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | | X |\n",
+ " --- --- --- \n",
+ "2 | | | O |\n",
+ " --- --- --- \n",
+ "3 | X | | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | | X |\n",
+ " --- --- --- \n",
+ "2 | | O | O |\n",
+ " --- --- --- \n",
+ "3 | X | | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): a\n",
+ "Enter the row (1, 2, 3...): 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | | X |\n",
+ " --- --- --- \n",
+ "2 | X | O | O |\n",
+ " --- --- --- \n",
+ "3 | X | | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | | X |\n",
+ " --- --- --- \n",
+ "2 | X | O | O |\n",
+ " --- --- --- \n",
+ "3 | X | O | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): b\n",
+ "Enter the row (1, 2, 3...): 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | O | X | X |\n",
+ " --- --- --- \n",
+ "2 | X | O | O |\n",
+ " --- --- --- \n",
+ "3 | X | O | X |\n",
+ " --- --- --- \n",
+ "Its a draw.\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "x_size = int(input(\"Enter the number of rows on board: \"))\n",
+ "y_size = int(input(\"Enter the number of columns on board: \"))\n",
+ "\n",
+ "b = make_board(x_size, y_size)\n",
+ "draw_board(b)\n",
+ "\n",
+ "mode = int(input(\"Press 1 for 2-player game, 2 to play vs computer: \"))\n",
+ "player = 1\n",
+ "computer = 2 if mode == 2 else None\n",
+ "moves = -1\n",
+ "\n",
+ "while moves == -1:\n",
+ "\n",
+ " if mode == 2 and player == computer:\n",
+ " print(\"Computer is making a move...\")\n",
+ " computer_move(b, computer, 1)\n",
+ " else:\n",
+ " print(\"Enter coordinates to make the move\")\n",
+ " x1 = input(\"Enter the column (A, B, C...): \")\n",
+ " x2 = input(\"Enter the row (1, 2, 3...): \")\n",
+ "\n",
+ " result = player_move(b, player, x1, x2)\n",
+ " if result != True:\n",
+ " print(result)\n",
+ " continue\n",
+ "\n",
+ " draw_board(b)\n",
+ " moves = check_play(b)\n",
+ "\n",
+ " if moves == -1:\n",
+ " player = 2 if player == 1 else 1\n",
+ "\n",
+ "if moves == 1:\n",
+ " print(\"X won.\")\n",
+ "elif moves == 2:\n",
+ " print(\"O won.\")\n",
+ "else:\n",
+ " print(\"Its a draw.\")"
]
},
{
@@ -434,20 +1627,319 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 97,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution here\n",
+ "import random\n",
+ "\n",
+ "def minimax(board, depth, max_depth, player, smart, dumb):\n",
+ " result = check_play(board)\n",
+ "\n",
+ " if result == smart:\n",
+ " return 100 - depth\n",
+ " if result == dumb:\n",
+ " return depth - 100\n",
+ " if result == 0:\n",
+ " return 0\n",
+ "\n",
+ " if depth == max_depth:\n",
+ " return 0\n",
+ "\n",
+ " r = len(board)\n",
+ " c = len(board[0])\n",
+ "\n",
+ " if player == smart:\n",
+ " best = -float(\"inf\")\n",
+ "\n",
+ " for i in range(r):\n",
+ " for j in range(c):\n",
+ " if board[i][j] == 0:\n",
+ " board[i][j] = smart\n",
+ " score = minimax(board, depth + 1, max_depth,\n",
+ " dumb, smart, dumb)\n",
+ " board[i][j] = 0\n",
+ " best = max(best, score)\n",
+ "\n",
+ " return best\n",
+ "\n",
+ " else:\n",
+ " best = float(\"inf\")\n",
+ "\n",
+ " for i in range(r):\n",
+ " for j in range(c):\n",
+ " if board[i][j] == 0:\n",
+ " board[i][j] = dumb\n",
+ " score = minimax(board, depth + 1, max_depth,\n",
+ " smart, smart, dumb)\n",
+ " board[i][j] = 0\n",
+ " best = min(best, score)\n",
+ "\n",
+ " return best\n",
+ "\n",
+ "\n",
+ "def computer_move_exhaustive(board, player, opponent, depth):\n",
+ " r = len(board)\n",
+ " c = len(board[0])\n",
+ "\n",
+ " best_score = -float(\"inf\")\n",
+ " best_move = None\n",
+ "\n",
+ " for i in range(r):\n",
+ " for j in range(c):\n",
+ " if board[i][j] == 0:\n",
+ " board[i][j] = player\n",
+ " score = minimax(board, 0, depth,\n",
+ " opponent, player, opponent)\n",
+ " board[i][j] = 0\n",
+ "\n",
+ " if score > best_score:\n",
+ " best_score = score\n",
+ " best_move = (i, j)\n",
+ "\n",
+ " if best_move:\n",
+ " board[best_move[0]][best_move[1]] = player\n"
]
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": 99,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the number of rows on board: 3\n",
+ "Enter the number of columns on board: 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | | | |\n",
+ " --- --- --- \n",
+ "2 | | | |\n",
+ " --- --- --- \n",
+ "3 | | | |\n",
+ " --- --- --- \n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Press 1 for 2-player game, 2 to play vs computer: 2\n",
+ "Enter search depth (recommended 3-5): 6\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): c\n",
+ "Enter the row (1, 2, 3...): 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | | | |\n",
+ " --- --- --- \n",
+ "2 | | | |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | | | |\n",
+ " --- --- --- \n",
+ "2 | | O | |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): a\n",
+ "Enter the row (1, 2, 3...): 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | | |\n",
+ " --- --- --- \n",
+ "2 | | O | |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | O | |\n",
+ " --- --- --- \n",
+ "2 | | O | |\n",
+ " --- --- --- \n",
+ "3 | | | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): b\n",
+ "Enter the row (1, 2, 3...): 3\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | O | |\n",
+ " --- --- --- \n",
+ "2 | | O | |\n",
+ " --- --- --- \n",
+ "3 | | X | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | O | |\n",
+ " --- --- --- \n",
+ "2 | | O | |\n",
+ " --- --- --- \n",
+ "3 | O | X | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): c\n",
+ "Enter the row (1, 2, 3...): 1\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | O | X |\n",
+ " --- --- --- \n",
+ "2 | | O | |\n",
+ " --- --- --- \n",
+ "3 | O | X | X |\n",
+ " --- --- --- \n",
+ "Computer is making a move...\n",
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | O | X |\n",
+ " --- --- --- \n",
+ "2 | | O | O |\n",
+ " --- --- --- \n",
+ "3 | O | X | X |\n",
+ " --- --- --- \n",
+ "Enter coordinates to make the move\n"
+ ]
+ },
+ {
+ "name": "stdin",
+ "output_type": "stream",
+ "text": [
+ "Enter the column (A, B, C...): a\n",
+ "Enter the row (1, 2, 3...): 2\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " A B C \n",
+ " --- --- --- \n",
+ "1 | X | O | X |\n",
+ " --- --- --- \n",
+ "2 | X | O | O |\n",
+ " --- --- --- \n",
+ "3 | O | X | X |\n",
+ " --- --- --- \n",
+ "Its a draw.\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution \n",
+ "# Test your solution here\n",
+ "x_size = int(input(\"Enter the number of rows on board: \"))\n",
+ "y_size = int(input(\"Enter the number of columns on board: \"))\n",
+ "\n",
+ "b = make_board(x_size, y_size)\n",
+ "draw_board(b)\n",
+ "\n",
+ "mode = int(input(\"Press 1 for 2-player game, 2 to play vs computer: \"))\n",
+ "player = 1\n",
+ "computer = 2 if mode == 2 else None\n",
+ "if mode == 2:\n",
+ " max_depth = int(input(\"Enter search depth (recommended 3-5): \"))\n",
+ "\n",
+ "moves = -1\n",
+ "\n",
+ "while moves == -1:\n",
+ "\n",
+ " if mode == 2 and player == computer:\n",
+ " print(\"Computer is making a move...\")\n",
+ " computer_move_exhaustive(b, computer, 1, max_depth)\n",
+ " else:\n",
+ " print(\"Enter coordinates to make the move\")\n",
+ " x1 = input(\"Enter the column (A, B, C...): \")\n",
+ " x2 = input(\"Enter the row (1, 2, 3...): \")\n",
+ "\n",
+ " result = player_move(b, player, x1, x2)\n",
+ " if result != True:\n",
+ " print(result)\n",
+ " continue\n",
+ "\n",
+ " draw_board(b)\n",
+ " moves = check_play(b)\n",
+ "\n",
+ " if moves == -1:\n",
+ " player = 2 if player == 1 else 1\n",
+ "\n",
+ "if moves == 1:\n",
+ " print(\"X won.\")\n",
+ "elif moves == 2:\n",
+ " print(\"O won.\")\n",
+ "else:\n",
+ " print(\"Its a draw.\")"
]
},
{
@@ -459,20 +1951,67 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 103,
"metadata": {},
"outputs": [],
"source": [
- "# Write your solution here"
+ "# Write your solution \n",
+ "def play_ai_vs_ai(size, depth_smart, depth_dumb, games=10):\n",
+ " smart_wins = 0\n",
+ " draw= 0\n",
+ " for g in range(games):\n",
+ " board = make_board(size, size)\n",
+ "\n",
+ " smart = 1 if g % 2 == 0 else 2\n",
+ " dumb = 2 if smart == 1 else 1\n",
+ "\n",
+ " player = 1\n",
+ " result = -1\n",
+ "\n",
+ " while result == -1:\n",
+ " if player == smart:\n",
+ " computer_move_exhaustive(board, smart, dumb, depth_smart)\n",
+ " else:\n",
+ " computer_move_exhaustive(board, dumb, smart, depth_dumb)\n",
+ "\n",
+ " result = check_play(board)\n",
+ " player = 2 if player == 1 else 1\n",
+ "\n",
+ " if result == smart:\n",
+ " smart_wins += 1\n",
+ " elif result == 0:\n",
+ " draw += 1\n",
+ "\n",
+ " win_rate = smart_wins / games * 100\n",
+ " print(f\"{size}x{size} grid → Smart AI win rate: {win_rate:.1f}% with {draw} draws.\")\n"
]
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 104,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "AI vs AI experiment:\n",
+ "\n",
+ "3x3 grid → Smart AI win rate: 50.0% with 5 draws.\n",
+ "4x4 grid → Smart AI win rate: 0.0% with 10 draws.\n",
+ "5x5 grid → Smart AI win rate: 0.0% with 10 draws.\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "# Test your solution here\n",
+ "print(\"\\nAI vs AI experiment:\\n\")\n",
+ "\n",
+ "play_ai_vs_ai(3, depth_smart=5, depth_dumb=2)\n",
+ "play_ai_vs_ai(4, depth_smart=4, depth_dumb=2)\n",
+ "play_ai_vs_ai(5, depth_smart=3, depth_dumb=1)"
]
},
{
@@ -510,7 +2049,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.13.7"
+ "version": "3.12.12"
}
},
"nbformat": 4,
diff --git a/Labs/Lab.3/.DS_Store b/Labs/Lab.3/.DS_Store
new file mode 100644
index 000000000..b64e8a66b
Binary files /dev/null and b/Labs/Lab.3/.DS_Store differ
diff --git a/Labs/Lab.3/Lab.3.ipynb b/Labs/Lab.3/Lab.3.ipynb
index 3dc0438eb..0154b718e 100644
--- a/Labs/Lab.3/Lab.3.ipynb
+++ b/Labs/Lab.3/Lab.3.ipynb
@@ -207,9 +207,17 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The Value of x is 0.9036066841881488\n"
+ ]
+ }
+ ],
"source": [
"import random\n",
"x=random.random()\n",
@@ -227,7 +235,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -235,18 +243,30 @@
"def generate_uniform(N,x_min,x_max):\n",
" out = []\n",
" ### BEGIN SOLUTION\n",
- "\n",
- " # Fill in your solution here \n",
- " \n",
+ " for _ in range(N):\n",
+ " d = random.random()\n",
+ " out.append(int(x_min + d * (x_max - x_min)))\n",
" ### END SOLUTION\n",
" return out"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Data Type: \n",
+ "Data Length: 1000\n",
+ "Type of Data Contents: \n",
+ "Data Minimum: -9\n",
+ "Data Maximum: 9\n"
+ ]
+ }
+ ],
"source": [
"# Test your solution here\n",
"data=generate_uniform(1000,-10,10)\n",
@@ -268,7 +288,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@@ -276,10 +296,10 @@
"def mean(Data):\n",
" m=0.\n",
" \n",
- " ### BEGIN SOLUTION\n",
- "\n",
- " # Fill in your solution here \n",
- " \n",
+ " ### BEGIN SOLUTION \n",
+ " n = len(Data)\n",
+ " Summation = sum(Data)\n",
+ " m = Summation/n\n",
" ### END SOLUTION\n",
" \n",
" return m"
@@ -287,11 +307,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Mean of Data: 9.0\n"
+ ]
+ }
+ ],
"source": [
"# Test your solution here\n",
+ "data = [8,10]\n",
"print (\"Mean of Data:\", mean(data))"
]
},
@@ -305,7 +334,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@@ -314,9 +343,14 @@
" m=0.\n",
" \n",
" ### BEGIN SOLUTION\n",
- "\n",
- " # Fill in your solution here \n",
- " \n",
+ " n = len(Data)\n",
+ " x_bar = mean(Data)\n",
+ " summation = 0\n",
+ " for i in range(n):\n",
+ " difference_sq = (Data[i] - x_bar) * (Data[i] - x_bar)\n",
+ " summation += difference_sq\n",
+ " \n",
+ " m = (1/(n-1)) * summation\n",
" ### END SOLUTION\n",
" \n",
" return m"
@@ -324,11 +358,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Variance of Data: 542.1944444444445\n"
+ ]
+ }
+ ],
"source": [
"# Test your solution here\n",
+ "data = [12,19,45,68,90,42,47,50,48]\n",
"print (\"Variance of Data:\", variance(data))"
]
},
@@ -358,16 +401,24 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# Solution\n",
"def histogram(x,n_bins=10,x_min=None,x_max=None):\n",
" ### BEGIN SOLUTION\n",
- "\n",
- " # Fill in your solution here \n",
- " \n",
+ " x_min, x_max = min(x), max(x)\n",
+ " bin_size = (x_max - x_min) / n_bins\n",
+ " hist = [0] * n_bins\n",
+ " bin_edges = [x_min + i * bin_size for i in range(n_bins + 1)]\n",
+ " for value in x:\n",
+ " for i in range(n_bins):\n",
+ " lower_bound = bin_edges[i]\n",
+ " upper_bound = bin_edges[i+1]\n",
+ " if lower_bound <= value <= upper_bound:\n",
+ " hist[i] += 1\n",
+ " break\n",
" ### END SOLUTION\n",
"\n",
" return hist,bin_edges"
@@ -375,13 +426,24 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[3, 2, 2]\n",
+ "[1.0, 4.666666666666666, 8.333333333333332, 12.0]\n"
+ ]
+ }
+ ],
"source": [
"# Test your solution here\n",
- "h,b=histogram(data,100)\n",
- "print(h)"
+ "data = [1, 2, 2, 5, 8, 10, 12]\n",
+ "h,b=histogram(data,3)\n",
+ "print(h)\n",
+ "print(b)"
]
},
{
@@ -407,29 +469,59 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
- "# Solution\n",
- "def draw_histogram(x,n_bins,x_min=None,x_max=None,character=\"#\",max_character_per_line=20):\n",
+ "def draw_histogram(x, n_bins, x_min=None, x_max=None, character=\"#\", max_character_per_line=20):\n",
" ### BEGIN SOLUTION\n",
- "\n",
- " # Fill in your solution here \n",
+ " hist, bin_edges = histogram(x, n_bins)\n",
+ " max_h = max(hist)\n",
" \n",
+ " for i in range(len(hist)):\n",
+ " if max_h > 0:\n",
+ " num_chars = int((hist[i] / max_h) * max_character_per_line)\n",
+ " else:\n",
+ " num_chars = 0\n",
+ " \n",
+ " bar = character * num_chars\n",
+ " lower = bin_edges[i]\n",
+ " upper = bin_edges[i+1]\n",
+ " print(f\"[{lower:>3.0f}, {upper:>3.0f}] : {bar}\")\n",
" ### END SOLUTION\n",
"\n",
- " return hist,bin_edges"
+ " return hist, bin_edges"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[ 0, 1] : ######\n",
+ "[ 1, 2] : ######\n",
+ "[ 2, 3] : #############\n",
+ "[ 3, 4] : ####################\n",
+ "[ 4, 4] : #############\n",
+ "[ 4, 5] : ####################\n",
+ "[ 5, 6] : #############\n",
+ "[ 6, 7] : ####################\n",
+ "[ 7, 8] : #############\n",
+ "[ 8, 9] : ####################\n"
+ ]
+ }
+ ],
"source": [
"# Test your solution here\n",
- "h,b=histogram(data,20)"
+ "# Create simple data from 0 to 10 to match your image\n",
+ "data = [0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9]\n",
+ "\n",
+ "# This line will now print the graph to the screen\n",
+ "h, b = draw_histogram(data, n_bins=10)"
]
},
{
@@ -443,29 +535,40 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
- "def where(mylist,myfunc):\n",
- " out= []\n",
- " \n",
- " ### BEGIN SOLUTION\n",
+ "def where(mylist, myfunc):\n",
+ " out = []\n",
"\n",
- " # Fill in your solution here \n",
- " \n",
+ " ### BEGIN SOLUTION\n",
+ " for i in range(len(mylist)):\n",
+ " if myfunc(mylist[i]):\n",
+ " out.append(i)\n",
" ### END SOLUTION\n",
- " \n",
+ "\n",
" return out"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[1, 3]\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution here"
+ "# Test your solution here\n",
+ "data = [0.1, 0.6, 0.3, 0.8, 0.2]\n",
+ "indices = where(data, lambda x: x > 0.5)\n",
+ "print(indices)"
]
},
{
@@ -483,9 +586,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True True False False False\n",
+ "False False True True False\n",
+ "Number of Entries passing F1: 5\n",
+ "Number of Entries passing F2: 0\n"
+ ]
+ }
+ ],
"source": [
"def in_range(mymin,mymax):\n",
" def testrange(x):\n",
@@ -493,8 +607,8 @@
" return testrange\n",
"\n",
"# Examples:\n",
- "F1=inrange(0,10)\n",
- "F2=inrange(10,20)\n",
+ "F1=in_range(0,10)\n",
+ "F2=in_range(10,20)\n",
"\n",
"# Test of in_range\n",
"print (F1(0), F1(1), F1(10), F1(15), F1(20))\n",
@@ -506,24 +620,63 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"### BEGIN SOLUTION\n",
- "\n",
- " # Fill in your solution here \n",
- " \n",
+ "def is_even(x):\n",
+ " return x % 2 == 0\n",
+ "\n",
+ "def is_odd(x):\n",
+ " return x % 2 != 0\n",
+ "\n",
+ "def greater_than(val):\n",
+ " def tester(x):\n",
+ " return x > val\n",
+ " return tester\n",
+ "\n",
+ "def less_than(val):\n",
+ " def tester(x):\n",
+ " return x < val\n",
+ " return tester\n",
+ "\n",
+ "def equal(val):\n",
+ " def tester(x):\n",
+ " return x == val\n",
+ " return tester\n",
+ "\n",
+ "def divisible_by(val):\n",
+ " def tester(x):\n",
+ " return x % val == 0\n",
+ " return tester \n",
"### END SOLUTION"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Even indices: [1, 3, 5, 6]\n",
+ "Greater than 5 indices: [5, 6, 7]\n",
+ "Divisible by 3 indices: [2, 5, 7]\n"
+ ]
+ }
+ ],
"source": [
- "# Test your solution"
+ "# Test your solution\n",
+ "data = [1, 2, 3, 4, 5, 6, 10, 15]\n",
+ "\n",
+ "print(\"Even indices:\", where(data, is_even))\n",
+ "\n",
+ "print(\"Greater than 5 indices:\", where(data, greater_than(5)))\n",
+ "\n",
+ "print(\"Divisible by 3 indices:\", where(data, divisible_by(3)))"
]
},
{
@@ -535,14 +688,30 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Even: 4\n",
+ "Odd: 4\n",
+ "Greater than: 8\n",
+ "Less than: 0\n",
+ "Equal: 0\n",
+ "Divisible by: 3\n"
+ ]
+ }
+ ],
"source": [
"### BEGIN SOLUTION\n",
- "\n",
- " # Fill in your solution here \n",
- " \n",
+ "print(\"Even:\", sum(map(lambda x: x % 2 == 0, data)))\n",
+ "print(\"Odd:\", sum(map(lambda x: x % 2 != 0, data)))\n",
+ "print(\"Greater than:\", sum(map(lambda x: x > 0.5, data)))\n",
+ "print(\"Less than:\", sum(map(lambda x: x < 0.5, data)))\n",
+ "print(\"Equal:\", sum(map(lambda x: x == 0, data)))\n",
+ "print(\"Divisible by:\", sum(map(lambda x: x % 3 == 0, data)))\n",
"### END SOLUTION"
]
},
@@ -561,30 +730,73 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"def generate_function(func,x_min,x_max,N=1000):\n",
" out = list()\n",
" ### BEGIN SOLUTION\n",
+ " import random\n",
"\n",
- " # Fill in your solution here \n",
+ " y_max = 0\n",
+ " steps = 1000\n",
+ " step_size = (x_max - x_min) / steps\n",
" \n",
+ " for i in range(steps):\n",
+ " val = func(x_min + i * step_size)\n",
+ " if val > y_max:\n",
+ " y_max = val\n",
+ " \n",
+ " while len(out) < N:\n",
+ " test_x = random.uniform(x_min, x_max)\n",
+ " p = random.uniform(0, y_max)\n",
+ " \n",
+ " if p <= func(test_x):\n",
+ " out.append(test_x)\n",
" ### END SOLUTION\n",
- " \n",
" return out"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[ -5, -5] : ####################\n",
+ "[ -5, -4] : ##################\n",
+ "[ -4, -4] : ################\n",
+ "[ -4, -3] : ##############\n",
+ "[ -3, -3] : ##########\n",
+ "[ -3, -3] : #########\n",
+ "[ -3, -2] : #######\n",
+ "[ -2, -2] : ####\n",
+ "[ -2, -1] : ##\n",
+ "[ -1, -1] : #\n",
+ "[ -1, -1] : #\n",
+ "[ -1, -0] : ##\n",
+ "[ -0, 0] : #####\n",
+ "[ 0, 1] : #######\n",
+ "[ 1, 1] : #########\n",
+ "[ 1, 1] : ###########\n",
+ "[ 1, 2] : ##############\n",
+ "[ 2, 2] : ###############\n",
+ "[ 2, 3] : #################\n",
+ "[ 3, 3] : ##################\n",
+ "([950, 863, 792, 686, 521, 432, 354, 219, 142, 54, 54, 137, 262, 362, 442, 565, 695, 741, 835, 894], [-4.999913621869641, -4.599928144478, -4.199942667086358, -3.7999571896947164, -3.3999717123030746, -2.999986234911433, -2.6000007575197914, -2.2000152801281496, -1.8000298027365078, -1.400044325344866, -1.0000588479532242, -0.6000733705615824, -0.20008789316994147, 0.19989758422170034, 0.5998830616133422, 0.999868539004984, 1.3998540163966258, 1.7998394937882676, 2.1998249711799094, 2.599810448571551, 2.999795925963193])\n"
+ ]
+ }
+ ],
"source": [
"# A test function\n",
"def test_func(x,a=1,b=1):\n",
- " return abs(a*x+b)"
+ " return abs(a*x+b)\n",
+ "data = generate_function(test_func, x_min=-5, x_max=3, N=10000)\n",
+ "print(draw_histogram(data, n_bins=20))"
]
},
{
@@ -596,9 +808,38 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Mean: -0.0052738494072836215\n",
+ "Variance: 0.9638367958021714\n",
+ "[ -4, -3] : \n",
+ "[ -3, -3] : \n",
+ "[ -3, -3] : \n",
+ "[ -3, -2] : \n",
+ "[ -2, -2] : ##\n",
+ "[ -2, -1] : ###\n",
+ "[ -1, -1] : #########\n",
+ "[ -1, -1] : #############\n",
+ "[ -1, -0] : ################\n",
+ "[ -0, 0] : ####################\n",
+ "[ 0, 0] : ###############\n",
+ "[ 0, 1] : ###############\n",
+ "[ 1, 1] : ###########\n",
+ "[ 1, 2] : ######\n",
+ "[ 2, 2] : ###\n",
+ "[ 2, 2] : ##\n",
+ "[ 2, 3] : \n",
+ "[ 3, 3] : \n",
+ "[ 3, 3] : \n",
+ "[ 3, 4] : \n"
+ ]
+ }
+ ],
"source": [
"import math\n",
"\n",
@@ -607,6 +848,17 @@
" return math.exp(-((x-mean)**2)/(2*sigma**2))/math.sqrt(math.pi*sigma)\n",
" return f\n",
"\n",
+ "g1 = gaussian(0, 1)\n",
+ "data = generate_function(g1, -5, 5, N=1000)\n",
+ "\n",
+ "calc_mean = sum(data) / len(data)\n",
+ "calc_var = sum([(x - calc_mean)**2 for x in data]) / len(data)\n",
+ "\n",
+ "print(f\"Mean: {calc_mean}\")\n",
+ "print(f\"Variance: {calc_var}\")\n",
+ "\n",
+ "draw_histogram(data, n_bins=20)\n",
+ "\n",
"# Example Instantiation\n",
"g1=gaussian(0,1)\n",
"g2=gaussian(10,3)"
@@ -621,19 +873,42 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"def integrate(func, x_min, x_max, n_points=1000):\n",
- " \n",
+ " ### BEGIN SOLUTION\n",
+ " all_data = generate_function(func, x_min - 5, x_max + 5, N=n_points)\n",
+ " checker = in_range(x_min, x_max)\n",
+ " valid_indices = where(all_data, checker)\n",
+ " integral = len(valid_indices) / n_points\n",
+ " ### END SOLUTION\n",
" return integral"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0.6908\n"
+ ]
+ }
+ ],
+ "source": [
+ "g1 = gaussian(0, 1)\n",
+ "print(integrate(g1, -1, 1, n_points=5000))"
+ ]
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3 (ipykernel)",
+ "display_name": "ds",
"language": "python",
"name": "python3"
},
@@ -647,7 +922,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.13.7"
+ "version": "3.11.14"
}
},
"nbformat": 4,
diff --git a/Labs/Lab.4/.ipynb_checkpoints/Lab.4-checkpoint.ipynb b/Labs/Lab.4/.ipynb_checkpoints/Lab.4-checkpoint.ipynb
new file mode 100644
index 000000000..2b630cf98
--- /dev/null
+++ b/Labs/Lab.4/.ipynb_checkpoints/Lab.4-checkpoint.ipynb
@@ -0,0 +1,397 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Lab 4- Object Oriented Programming\n",
+ "\n",
+ "For all of the exercises below, make sure you provide tests of your solutions.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "1. Write a \"counter\" class that can be incremented up to a specified maximum value, will print an error if an attempt is made to increment beyond that value, and allows reseting the counter. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Error: Attempted to increment beyond maximum value.\n",
+ "Error: Attempted to increment beyond maximum value.\n"
+ ]
+ }
+ ],
+ "source": [
+ "class SimpleCounter:\n",
+ " def __init__(self, max_value):\n",
+ " self.count = 0\n",
+ " self.max_value = max_value\n",
+ "\n",
+ " def increment(self):\n",
+ " if self.count >= self.max_value:\n",
+ " print(\"Error: Attempted to increment beyond maximum value.\")\n",
+ " else:\n",
+ " self.count += 1\n",
+ "\n",
+ " def reset(self):\n",
+ " self.count = 0\n",
+ "\n",
+ "# --- Test ---\n",
+ "c1 = SimpleCounter(2)\n",
+ "c1.increment()\n",
+ "c1.increment()\n",
+ "c1.increment() # This will print the error\n",
+ "c1.reset()\n",
+ "c1.increment() \n",
+ "c1.increment()\n",
+ "c1.increment() # This will print the error again"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "2. Copy and paste your solution to question 1 and modify it so that all the data held by the counter is private. Implement functions to check the value of the counter, check the maximum value, and check if the counter is at the maximum."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Value: 2, Is Max?: False\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Counter:\n",
+ " def __init__(self, max_value):\n",
+ " self.__count = 0 \n",
+ " self.__max_value = max_value\n",
+ "\n",
+ " def increment(self):\n",
+ " if self.__count >= self.__max_value:\n",
+ " print(\"Error: Attempted to increment beyond maximum value.\")\n",
+ " else:\n",
+ " self.__count += 1\n",
+ "\n",
+ " def reset(self):\n",
+ " self.__count = 0\n",
+ "\n",
+ " def get_value(self):\n",
+ " return self.__count\n",
+ "\n",
+ " def get_max(self):\n",
+ " return self.__max_value\n",
+ "\n",
+ " def is_at_max(self):\n",
+ " return self.__count == self.__max_value\n",
+ "\n",
+ "c2 = Counter(3)\n",
+ "c2.increment()\n",
+ "c2.increment()\n",
+ "print(f\"Value: {c2.get_value()}, Is Max?: {c2.is_at_max()}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "3. Implement a class to represent a rectangle, holding the length, width, and $x$ and $y$ coordinates of a corner of the object. Implement functions that compute the area and perimeter of the rectangle. Make all data members private and privide accessors to retrieve values of data members. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Area: 8, Perimeter: 12.\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Rectangle:\n",
+ " def __init__(self, length, width, x, y):\n",
+ " self.__length = length\n",
+ " self.__width = width\n",
+ " self.__x = x\n",
+ " self.__y = y\n",
+ "\n",
+ " def get_length(self): return self.__length\n",
+ " def get_width(self): return self.__width\n",
+ " def get_x(self): return self.__x\n",
+ " def get_y(self): return self.__y\n",
+ "\n",
+ " def area(self):\n",
+ " return self.__length * self.__width\n",
+ " \n",
+ " def perimeter(self):\n",
+ " return 2 * (self.__length + self.__width)\n",
+ " \n",
+ "# Test\n",
+ "rect = Rectangle(4, 2, 0, 0)\n",
+ "print(f\"Area: {rect.area()}, Perimeter: {rect.perimeter()}.\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "4. Implement a class to represent a circle, holding the radius and $x$ and $y$ coordinates of center of the object. Implement functions that compute the area and perimeter of the rectangle. Make all data members private and privide accessors to retrieve values of data members. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "5. Implement a common base class for the classes implemented in 3 and 4 above which implements all common methods as not implemented functions (virtual). Re-implement your regtangle and circule classes to inherit from the base class and overload the functions accordingly. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "6. Implement a triangle class analogous to the rectangle and circle in question 5."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "7. Add a function to the object classes, including the base, that returns a list of up to 16 pairs of $x$ and $y$ points on the parameter of the object. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "8. Add a function to the object classes, including the base, that tests if a given set of $x$ and $y$ coordinates are inside of the object. You'll have to think through how to determine if a set of coordinates are inside an object for each object type."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "9. Add a function in the base class of the object classes that returns true/false testing that the object overlaps with another object."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "10. Copy the `Canvas` class from lecture to in a python file creating a `paint` module. Copy your classes from above into the module and implement paint functions. Implement a `CompoundShape` class. Create a simple drawing demonstrating that all of your classes are working."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "11. Create a `RasterDrawing` class. Demonstrate that you can create a drawing made of several shapes, paint the drawing, modify the drawing, and paint it again. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "12. Implement the ability to load/save raster drawings and demonstate that your method works. One way to implement this ability:\n",
+ "\n",
+ " * Overload `__repr__` functions of all objects to return strings of the python code that would construct the object.\n",
+ " \n",
+ " * In the save method of raster drawing class, store the representations into the file.\n",
+ " * Write a loader function that reads the file and uses `eval` to instantiate the object.\n",
+ "\n",
+ "For example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class foo:\n",
+ " def __init__(self,a,b=None):\n",
+ " self.a=a\n",
+ " self.b=b\n",
+ " \n",
+ " def __repr__(self):\n",
+ " return \"foo(\"+repr(self.a)+\",\"+repr(self.b)+\")\"\n",
+ " \n",
+ " def save(self,filename):\n",
+ " f=open(filename,\"w\")\n",
+ " f.write(self.__repr__())\n",
+ " f.close()\n",
+ " \n",
+ " \n",
+ "def foo_loader(filename):\n",
+ " f=open(filename,\"r\")\n",
+ " tmp=eval(f.read())\n",
+ " f.close()\n",
+ " return tmp\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "foo(1,'hello')\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Test\n",
+ "print(repr(foo(1,\"hello\")))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create an object and save it\n",
+ "ff=foo(1,\"hello\")\n",
+ "ff.save(\"Test.foo\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "foo(1,'hello')"
+ ]
+ }
+ ],
+ "source": [
+ "# Check contents of the saved file\n",
+ "!cat Test.foo"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "foo(1,'hello')"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Load the object\n",
+ "ff_reloaded=foo_loader(\"Test.foo\")\n",
+ "ff_reloaded"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "ds",
+ "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.11.14"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Labs/Lab.4/Lab.4.ipynb b/Labs/Lab.4/Lab.4.ipynb
index 98e6e4341..02b5083c6 100644
--- a/Labs/Lab.4/Lab.4.ipynb
+++ b/Labs/Lab.4/Lab.4.ipynb
@@ -18,10 +18,43 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Error: Attempted to increment beyond maximum value.\n",
+ "Error: Attempted to increment beyond maximum value.\n"
+ ]
+ }
+ ],
+ "source": [
+ "class SimpleCounter:\n",
+ " def __init__(self, max_value):\n",
+ " self.count = 0\n",
+ " self.max_value = max_value\n",
+ "\n",
+ " def increment(self):\n",
+ " if self.count >= self.max_value:\n",
+ " print(\"Error: Attempted to increment beyond maximum value.\")\n",
+ " else:\n",
+ " self.count += 1\n",
+ "\n",
+ " def reset(self):\n",
+ " self.count = 0\n",
+ "\n",
+ "# --- Test ---\n",
+ "c1 = SimpleCounter(2)\n",
+ "c1.increment()\n",
+ "c1.increment()\n",
+ "c1.increment() # This will print the error\n",
+ "c1.reset()\n",
+ "c1.increment() \n",
+ "c1.increment()\n",
+ "c1.increment() # This will print the error again"
+ ]
},
{
"cell_type": "markdown",
@@ -32,10 +65,46 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Value: 2, Is Max?: False\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Counter:\n",
+ " def __init__(self, max_value):\n",
+ " self.__count = 0 \n",
+ " self.__max_value = max_value\n",
+ "\n",
+ " def increment(self):\n",
+ " if self.__count >= self.__max_value:\n",
+ " print(\"Error: Attempted to increment beyond maximum value.\")\n",
+ " else:\n",
+ " self.__count += 1\n",
+ "\n",
+ " def reset(self):\n",
+ " self.__count = 0\n",
+ "\n",
+ " def get_value(self):\n",
+ " return self.__count\n",
+ "\n",
+ " def get_max(self):\n",
+ " return self.__max_value\n",
+ "\n",
+ " def is_at_max(self):\n",
+ " return self.__count == self.__max_value\n",
+ "\n",
+ "c2 = Counter(3)\n",
+ "c2.increment()\n",
+ "c2.increment()\n",
+ "print(f\"Value: {c2.get_value()}, Is Max?: {c2.is_at_max()}\")"
+ ]
},
{
"cell_type": "markdown",
@@ -46,10 +115,40 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Area: 8, Perimeter: 12.\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Rectangle:\n",
+ " def __init__(self, length, width, x, y):\n",
+ " self.__length = length\n",
+ " self.__width = width\n",
+ " self.__x = x\n",
+ " self.__y = y\n",
+ "\n",
+ " def get_length(self): return self.__length\n",
+ " def get_width(self): return self.__width\n",
+ " def get_x(self): return self.__x\n",
+ " def get_y(self): return self.__y\n",
+ "\n",
+ " def area(self):\n",
+ " return self.__length * self.__width\n",
+ " \n",
+ " def perimeter(self):\n",
+ " return 2 * (self.__length + self.__width)\n",
+ " \n",
+ "# Test\n",
+ "rect = Rectangle(4, 2, 0, 0)\n",
+ "print(f\"Area: {rect.area()}, Perimeter: {rect.perimeter()}.\")\n"
+ ]
},
{
"cell_type": "markdown",
@@ -60,10 +159,44 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Circle Area: 50.27, Perimeter: 25.13\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "\n",
+ "class Circle:\n",
+ " def __init__(self, radius, x, y):\n",
+ " self.__radius = radius\n",
+ " self.__x = x\n",
+ " self.__y = y\n",
+ "\n",
+ " def get_radius(self):\n",
+ " return self.__radius\n",
+ " def get_x(self):\n",
+ " return self.__x\n",
+ " def get_y(self):\n",
+ " return self.__y\n",
+ "\n",
+ " def area(self):\n",
+ " return np.pi * (self.__radius ** 2)\n",
+ "\n",
+ " def perimeter(self):\n",
+ " return 2 * np.pi * self.__radius\n",
+ "\n",
+ "# Test\n",
+ "c = Circle(4, 5, 5)\n",
+ "print(f\"Circle Area: {c.area():.2f}, Perimeter: {c.perimeter():.2f}\")\n",
+ " "
+ ]
},
{
"cell_type": "markdown",
@@ -74,10 +207,50 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Rectangle Area: 12.00\n",
+ "Circle Area: 12.57\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Shape:\n",
+ " def area(self):\n",
+ " raise NotImplementedError\n",
+ " \n",
+ " def perimeter(self):\n",
+ " raise NotImplementedError\n",
+ "\n",
+ "class Rectangle(Shape):\n",
+ " def __init__(self, length, width, x, y):\n",
+ " self.__length = length\n",
+ " self.__width = width\n",
+ " self.__x = x\n",
+ " self.__y = y\n",
+ " \n",
+ " def area(self): return self.__length * self.__width\n",
+ " def perimeter(self): return 2 * (self.__length + self.__width)\n",
+ "\n",
+ "class Circle(Shape):\n",
+ " def __init__(self, radius, cx, cy):\n",
+ " self.__radius = radius\n",
+ " self.__cx = cx\n",
+ " self.__cy = cy\n",
+ " \n",
+ " def area(self): return np.pi * (self.__radius ** 2)\n",
+ " def perimeter(self): return 2 * np.pi * self.__radius\n",
+ "\n",
+ "# --- Test ---\n",
+ "shapes = [Rectangle(4, 3, 0, 0), Circle(2, 0, 0)]\n",
+ "for s in shapes:\n",
+ " print(f\"{s.__class__.__name__} Area: {s.area():.2f}\")"
+ ]
},
{
"cell_type": "markdown",
@@ -88,10 +261,36 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 6,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Triangle Area: 6.0, Perimeter: 12.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Triangle(Shape):\n",
+ " def __init__(self, base, height, x, y):\n",
+ " self.__base = base\n",
+ " self.__height = height\n",
+ " self.__x = x\n",
+ " self.__y = y\n",
+ " \n",
+ " def area(self): \n",
+ " return 0.5 * self.__base * self.__height\n",
+ " \n",
+ " def perimeter(self): \n",
+ " hypotenuse = np.sqrt(self.__base**2 + self.__height**2)\n",
+ " return self.__base + self.__height + hypotenuse\n",
+ "\n",
+ "# --- Test ---\n",
+ "t = Triangle(3, 4, 0, 0)\n",
+ "print(f\"Triangle Area: {t.area()}, Perimeter: {t.perimeter()}\")"
+ ]
},
{
"cell_type": "markdown",
@@ -102,10 +301,73 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"metadata": {},
"outputs": [],
- "source": []
+ "source": [
+ "import math\n",
+ "\n",
+ "class Shape:\n",
+ " def area(self): raise NotImplementedError\n",
+ " def perimeter(self): raise NotImplementedError\n",
+ " \n",
+ " def get_perimeter_points(self): raise NotImplementedError\n",
+ "\n",
+ "class Rectangle(Shape):\n",
+ " def __init__(self, length, width, x, y):\n",
+ " self.__length = length\n",
+ " self.__width = width\n",
+ " self.__x = x\n",
+ " self.__y = y\n",
+ " \n",
+ " def area(self): return self.__length * self.__width\n",
+ " def perimeter(self): return 2 * (self.__length + self.__width)\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(4):\n",
+ " points.append((self.__x + (self.__length * i / 4), self.__y)) # Top edge\n",
+ " points.append((self.__x + (self.__length * i / 4), self.__y - self.__width)) # Bottom edge\n",
+ " points.append((self.__x, self.__y - (self.__width * i / 4))) # Left edge\n",
+ " points.append((self.__x + self.__length, self.__y - (self.__width * i / 4))) # Right edge\n",
+ " return points\n",
+ "\n",
+ "class Circle(Shape):\n",
+ " def __init__(self, radius, cx, cy):\n",
+ " self.__radius = radius\n",
+ " self.__cx = cx\n",
+ " self.__cy = cy\n",
+ " \n",
+ " def area(self): return math.pi * (self.__radius ** 2)\n",
+ " def perimeter(self): return 2 * math.pi * self.__radius\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(16):\n",
+ " angle = 2 * math.pi * i / 16\n",
+ " px = self.__cx + self.__radius * math.cos(angle)\n",
+ " py = self.__cy + self.__radius * math.sin(angle)\n",
+ " points.append((px, py))\n",
+ " return points\n",
+ "\n",
+ "class Triangle(Shape):\n",
+ " def __init__(self, base, height, x, y):\n",
+ " self.__base = base\n",
+ " self.__height = height\n",
+ " self.__x = x\n",
+ " self.__y = y\n",
+ " \n",
+ " def area(self): return 0.5 * self.__base * self.__height\n",
+ " def perimeter(self): return self.__base + self.__height + math.sqrt(self.__base**2 + self.__height**2)\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(5):\n",
+ " points.append((self.__x + (self.__base * i / 5), self.__y)) \n",
+ " points.append((self.__x, self.__y + (self.__height * i / 5))) \n",
+ " points.append((self.__x + (self.__base * i / 5), self.__y + self.__height - (self.__height * i / 5))) \n",
+ " points.append((self.__x + self.__base, self.__y)) "
+ ]
},
{
"cell_type": "markdown",
@@ -116,10 +378,90 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 8,
"metadata": {},
"outputs": [],
- "source": []
+ "source": [
+ "class Shape:\n",
+ " def area(self): raise NotImplementedError\n",
+ " def perimeter(self): raise NotImplementedError\n",
+ " def get_perimeter_points(self): raise NotImplementedError\n",
+ " def contains(self, x, y): raise NotImplementedError\n",
+ "\n",
+ "class Rectangle(Shape):\n",
+ " def __init__(self, length, width, x, y):\n",
+ " self.length = length\n",
+ " self.width = width\n",
+ " self.x = x\n",
+ " self.y = y\n",
+ " \n",
+ " def area(self): return self.length * self.width\n",
+ " def perimeter(self): return 2 * (self.length + self.width)\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(4):\n",
+ " points.append((self.x + (self.length * i / 4), self.y))\n",
+ " points.append((self.x + (self.length * i / 4), self.y - self.width))\n",
+ " points.append((self.x, self.y - (self.width * i / 4)))\n",
+ " points.append((self.x + self.length, self.y - (self.width * i / 4)))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " return (self.x <= px <= self.x + self.length) and (self.y - self.width <= py <= self.y)\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Rectangle({self.length}, {self.width}, {self.x}, {self.y})\"\n",
+ "\n",
+ "class Circle(Shape):\n",
+ " def __init__(self, radius, cx, cy):\n",
+ " self.radius = radius\n",
+ " self.cx = cx\n",
+ " self.cy = cy\n",
+ " \n",
+ " def area(self): return math.pi * (self.radius ** 2)\n",
+ " def perimeter(self): return 2 * math.pi * self.radius\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(16):\n",
+ " angle = 2 * math.pi * i / 16\n",
+ " points.append((self.cx + self.radius * math.cos(angle), self.cy + self.radius * math.sin(angle)))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " return math.sqrt((px - self.cx)**2 + (py - self.cy)**2) <= self.radius\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Circle({self.radius}, {self.cx}, {self.cy})\"\n",
+ "\n",
+ "class Triangle(Shape):\n",
+ " def __init__(self, base, height, x, y):\n",
+ " self.base = base\n",
+ " self.height = height\n",
+ " self.x = x\n",
+ " self.y = y\n",
+ " \n",
+ " def area(self): return 0.5 * self.base * self.height\n",
+ " def perimeter(self): return self.base + self.height + math.sqrt(self.base**2 + self.height**2)\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(5):\n",
+ " points.append((self.x + (self.base * i / 5), self.y))\n",
+ " points.append((self.x, self.y + (self.height * i / 5)))\n",
+ " points.append((self.x + (self.base * i / 5), self.y + self.height - (self.height * i / 5)))\n",
+ " points.append((self.x + self.base, self.y))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " if not ((self.x <= px <= self.x + self.base) and (self.y <= py <= self.y + self.height)):\n",
+ " return False\n",
+ " return py <= self.y + self.height - (self.height / self.base) * (px - self.x)\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Triangle({self.base}, {self.height}, {self.x}, {self.y})\""
+ ]
},
{
"cell_type": "markdown",
@@ -130,10 +472,87 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 10,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "True\n"
+ ]
+ }
+ ],
+ "source": [
+ "class Shape:\n",
+ " def area(self): raise NotImplementedError\n",
+ " def perimeter(self): raise NotImplementedError\n",
+ " def get_perimeter_points(self): raise NotImplementedError\n",
+ " def contains(self, x, y): raise NotImplementedError\n",
+ " \n",
+ " def overlaps(self, other):\n",
+ " for px, py in other.get_perimeter_points():\n",
+ " if self.contains(px, py):\n",
+ " return True\n",
+ " \n",
+ " for px, py in self.get_perimeter_points():\n",
+ " if other.contains(px, py):\n",
+ " return True\n",
+ " \n",
+ " return False\n",
+ "\n",
+ "class Rectangle(Shape):\n",
+ " def __init__(self, length, width, x, y):\n",
+ " self.length = length\n",
+ " self.width = width\n",
+ " self.x = x\n",
+ " self.y = y\n",
+ " \n",
+ " def area(self): return self.length * self.width\n",
+ " def perimeter(self): return 2 * (self.length + self.width)\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(4):\n",
+ " points.append((self.x + (self.length * i / 4), self.y))\n",
+ " points.append((self.x + (self.length * i / 4), self.y - self.width))\n",
+ " points.append((self.x, self.y - (self.width * i / 4)))\n",
+ " points.append((self.x + self.length, self.y - (self.width * i / 4)))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " return (self.x <= px <= self.x + self.length) and (self.y - self.width <= py <= self.y)\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Rectangle({self.length}, {self.width}, {self.x}, {self.y})\"\n",
+ "\n",
+ "class Circle(Shape):\n",
+ " def __init__(self, radius, cx, cy):\n",
+ " self.radius = radius\n",
+ " self.cx = cx\n",
+ " self.cy = cy\n",
+ " \n",
+ " def area(self): return math.pi * (self.radius ** 2)\n",
+ " def perimeter(self): return 2 * math.pi * self.radius\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(16):\n",
+ " angle = 2 * math.pi * i / 16\n",
+ " points.append((self.cx + self.radius * math.cos(angle), self.cy + self.radius * math.sin(angle)))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " return math.sqrt((px - self.cx)**2 + (py - self.cy)**2) <= self.radius\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Circle({self.radius}, {self.cx}, {self.cy})\"\n",
+ "\n",
+ "# --- Q9 Test ---\n",
+ "r1 = Rectangle(10, 10, 0, 10)\n",
+ "c1 = Circle(5, 5, 5)\n",
+ "print(r1.overlaps(c1))"
+ ]
},
{
"cell_type": "markdown",
@@ -144,10 +563,184 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " \n",
+ " \n",
+ " ########### \n",
+ " ########### \n",
+ " ########### O \n",
+ " ########### OOOOO \n",
+ " ########### OOOOOOO \n",
+ " ########### OOOOOOO \n",
+ " OOOOOOOOO \n",
+ " OOOOOOO \n",
+ " OOOOOOO \n",
+ " OOOOO \n",
+ " O \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n"
+ ]
+ }
+ ],
+ "source": [
+ "import math\n",
+ "\n",
+ "class Canvas:\n",
+ " def __init__(self, width, height):\n",
+ " self.width = width\n",
+ " self.height = height\n",
+ " self.data = [[' '] * width for i in range(height)]\n",
+ "\n",
+ " def set_pixel(self, row, col, char='*'):\n",
+ " if 0 <= row < self.height and 0 <= col < self.width:\n",
+ " self.data[row][col] = char\n",
+ "\n",
+ " def get_pixel(self, row, col):\n",
+ " return self.data[row][col]\n",
+ " \n",
+ " def clear_canvas(self):\n",
+ " self.data = [[' '] * self.width for i in range(self.height)]\n",
+ " \n",
+ " def display(self):\n",
+ " print(\"\\n\".join([\"\".join(row) for row in self.data]))\n",
+ "\n",
+ "class Shape:\n",
+ " def __init__(self, name=\"\", char=\"*\"):\n",
+ " self.name = name\n",
+ " self.char = char\n",
+ " \n",
+ " def area(self): raise NotImplementedError\n",
+ " def perimeter(self): raise NotImplementedError\n",
+ " def get_perimeter_points(self): raise NotImplementedError\n",
+ " def contains(self, x, y): raise NotImplementedError\n",
+ " \n",
+ " def overlaps(self, other):\n",
+ " for px, py in other.get_perimeter_points():\n",
+ " if self.contains(px, py): return True\n",
+ " for px, py in self.get_perimeter_points():\n",
+ " if other.contains(px, py): return True\n",
+ " return False\n",
+ " \n",
+ " def paint(self, canvas):\n",
+ " for row in range(canvas.height):\n",
+ " for col in range(canvas.width):\n",
+ " if self.contains(col, row):\n",
+ " canvas.set_pixel(row, col, self.char)\n",
+ "\n",
+ "class Rectangle(Shape):\n",
+ " def __init__(self, length, width, x, y, name=\"\", char=\"*\"):\n",
+ " super().__init__(name, char)\n",
+ " self.length = length\n",
+ " self.width = width\n",
+ " self.x = x\n",
+ " self.y = y\n",
+ " \n",
+ " def area(self): return self.length * self.width\n",
+ " def perimeter(self): return 2 * (self.length + self.width)\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(4):\n",
+ " points.append((self.x + (self.length * i / 4), self.y))\n",
+ " points.append((self.x + (self.length * i / 4), self.y + self.width))\n",
+ " points.append((self.x, self.y + (self.width * i / 4)))\n",
+ " points.append((self.x + self.length, self.y + (self.width * i / 4)))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " return (self.x <= px <= self.x + self.length) and (self.y <= py <= self.y + self.width)\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Rectangle({self.length}, {self.width}, {self.x}, {self.y}, '{self.name}', '{self.char}')\"\n",
+ "\n",
+ "class Circle(Shape):\n",
+ " def __init__(self, radius, cx, cy, name=\"\", char=\"*\"):\n",
+ " super().__init__(name, char)\n",
+ " self.radius = radius\n",
+ " self.cx = cx\n",
+ " self.cy = cy\n",
+ " \n",
+ " def area(self): return math.pi * (self.radius ** 2)\n",
+ " def perimeter(self): return 2 * math.pi * self.radius\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(16):\n",
+ " angle = 2 * math.pi * i / 16\n",
+ " points.append((self.cx + self.radius * math.cos(angle), self.cy + self.radius * math.sin(angle)))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " return math.sqrt((px - self.cx)**2 + (py - self.cy)**2) <= self.radius\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Circle({self.radius}, {self.cx}, {self.cy}, '{self.name}', '{self.char}')\"\n",
+ "\n",
+ "class Triangle(Shape):\n",
+ " def __init__(self, base, height, x, y, name=\"\", char=\"*\"):\n",
+ " super().__init__(name, char)\n",
+ " self.base = base\n",
+ " self.height = height\n",
+ " self.x = x\n",
+ " self.y = y\n",
+ " \n",
+ " def area(self): return 0.5 * self.base * self.height\n",
+ " def perimeter(self): return self.base + self.height + math.sqrt(self.base**2 + self.height**2)\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for i in range(5):\n",
+ " points.append((self.x + (self.base * i / 5), self.y))\n",
+ " points.append((self.x, self.y + (self.height * i / 5)))\n",
+ " points.append((self.x + (self.base * i / 5), self.y + self.height - (self.height * i / 5)))\n",
+ " points.append((self.x + self.base, self.y))\n",
+ " return points\n",
+ "\n",
+ " def contains(self, px, py):\n",
+ " if not ((self.x <= px <= self.x + self.base) and (self.y <= py <= self.y + self.height)):\n",
+ " return False\n",
+ " return py <= self.y + self.height - (self.height / self.base) * (px - self.x)\n",
+ "\n",
+ " def __repr__(self):\n",
+ " return f\"Triangle({self.base}, {self.height}, {self.x}, {self.y}, '{self.name}', '{self.char}')\"\n",
+ "\n",
+ "class CompoundShape(Shape):\n",
+ " def __init__(self, shapes, name=\"\", char=\"*\"):\n",
+ " super().__init__(name, char)\n",
+ " self.shapes = shapes\n",
+ " \n",
+ " def get_perimeter_points(self):\n",
+ " points = []\n",
+ " for s in self.shapes: \n",
+ " points.extend(s.get_perimeter_points())\n",
+ " return points\n",
+ " \n",
+ " def contains(self, x, y):\n",
+ " return any(s.contains(x, y) for s in self.shapes)\n",
+ " \n",
+ " def paint(self, canvas):\n",
+ " for s in self.shapes:\n",
+ " s.paint(canvas)\n",
+ " \n",
+ " def __repr__(self):\n",
+ " return f\"CompoundShape({self.shapes}, '{self.name}', '{self.char}')\"\n",
+ "\n",
+ "my_canvas = Canvas(40, 20)\n",
+ "comp = CompoundShape([Rectangle(10, 5, 2, 2, char=\"#\"), Circle(4, 25, 8, char=\"O\")])\n",
+ "comp.paint(my_canvas)\n",
+ "my_canvas.display()"
+ ]
},
{
"cell_type": "markdown",
@@ -158,10 +751,100 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 12,
"metadata": {},
- "outputs": [],
- "source": []
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " O TTTTTTTTT \n",
+ " OOOOOOO TTTTTTTT \n",
+ " OOOOOOOOO TTTTTTT \n",
+ " OOOOOOOOO TTTTTT \n",
+ " OOOOOOOOO TTTTT \n",
+ " OOOOOOOOOOO TTTT \n",
+ " OOOOOOOOO TTT \n",
+ " OOOOOOOOO TT \n",
+ " OOOOOOOOO T \n",
+ " OOOOOOO \n",
+ " O \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " O \n",
+ " OOOOOOO \n",
+ " OOOOOOOOOOO \n",
+ " OOOOOOOOOOOOO TTTTTTTTT \n",
+ " OOOOOOOOOOOOO TTTTTTTT \n",
+ " OOOOOOOOOOOOOOO TTTTTTT \n",
+ " OOOOOOOOOOOOOOO TTTTTT \n",
+ " OOOOOOOOOOOOOOO TTTTT \n",
+ " OOOOOOOOOOOOOOOOO TTTT \n",
+ " OOOOOOOOOOOOOOO TTT \n",
+ " OOOOOOOOOOOOOOO TT \n",
+ " OOOOOOOOOOOOOOO T \n",
+ " OOOOOOOOOOOOO \n",
+ " OOOOOOOOOOOOO \n",
+ " OOOOOOOOOOO \n",
+ " OOOOOOO \n",
+ " O \n",
+ " \n"
+ ]
+ }
+ ],
+ "source": [
+ "class RasterDrawing:\n",
+ " def __init__(self):\n",
+ " self.shapes = dict()\n",
+ " self.shape_names = list()\n",
+ " \n",
+ " def add_shape(self, shape):\n",
+ " if shape.name == \"\":\n",
+ " shape.name = self.assign_name()\n",
+ " self.shapes[shape.name] = shape\n",
+ " self.shape_names.append(shape.name)\n",
+ "\n",
+ " def update(self, canvas):\n",
+ " canvas.clear_canvas()\n",
+ " self.paint(canvas)\n",
+ " \n",
+ " def paint(self, canvas):\n",
+ " for shape_name in self.shape_names:\n",
+ " self.shapes[shape_name].paint(canvas)\n",
+ " \n",
+ " def assign_name(self):\n",
+ " name_base = \"shape\"\n",
+ " name = name_base + \"_0\"\n",
+ " i = 1\n",
+ " while name in self.shapes:\n",
+ " name = name_base + \"_\" + str(i)\n",
+ " i += 1\n",
+ " return name\n",
+ "\n",
+ "drawing_canvas = Canvas(40, 20)\n",
+ "rd = RasterDrawing()\n",
+ "rd.add_shape(Circle(5, 10, 10, char=\"O\"))\n",
+ "rd.add_shape(Triangle(8, 8, 20, 5, char=\"T\"))\n",
+ "rd.paint(drawing_canvas)\n",
+ "drawing_canvas.display()\n",
+ "\n",
+ "print(\"\\n\")\n",
+ "\n",
+ "rd.shapes[\"shape_0\"].radius = 8\n",
+ "rd.update(drawing_canvas)\n",
+ "drawing_canvas.display()"
+ ]
},
{
"cell_type": "markdown",
@@ -177,6 +860,65 @@
"For example:"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " ########### \n",
+ " ########### \n",
+ " ########### O \n",
+ " ########### OOOOO \n",
+ " ########### OOOOO \n",
+ " ########### OOOOOOO \n",
+ " OOOOO \n",
+ " OOOOO \n",
+ " O \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n"
+ ]
+ }
+ ],
+ "source": [
+ "class RasterDrawingSaveable(RasterDrawing):\n",
+ " def save(self, filename):\n",
+ " with open(filename, \"w\") as f:\n",
+ " f.write(repr(list(self.shapes.values())))\n",
+ " \n",
+ "def load_drawing(filename):\n",
+ " with open(filename, \"r\") as f:\n",
+ " shapes_list = eval(f.read())\n",
+ " \n",
+ " new_drawing = RasterDrawingSaveable()\n",
+ " for s in shapes_list:\n",
+ " new_drawing.add_shape(s)\n",
+ " return new_drawing\n",
+ "\n",
+ "drawing = RasterDrawingSaveable()\n",
+ "drawing.add_shape(Rectangle(10, 5, 5, 5, char=\"#\"))\n",
+ "drawing.add_shape(Circle(3, 25, 10, char=\"O\"))\n",
+ "\n",
+ "drawing.save(\"lab4_drawing.txt\")\n",
+ "\n",
+ "loaded = load_drawing(\"lab4_drawing.txt\")\n",
+ "test_canvas = Canvas(40, 20)\n",
+ "loaded.paint(test_canvas)\n",
+ "test_canvas.display()"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
@@ -276,7 +1018,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3 (ipykernel)",
+ "display_name": "ds",
"language": "python",
"name": "python3"
},
diff --git a/Labs/Lab.4/lab4_drawing.txt b/Labs/Lab.4/lab4_drawing.txt
new file mode 100644
index 000000000..0f104b0f0
--- /dev/null
+++ b/Labs/Lab.4/lab4_drawing.txt
@@ -0,0 +1 @@
+[Rectangle(10, 5, 5, 5, 'shape_0', '#'), Circle(3, 25, 10, 'shape_1', 'O')]
\ No newline at end of file
diff --git a/Labs/Lab.5/Lab.5.ipynb b/Labs/Lab.5/Lab.5.ipynb
index cba027097..e0dfc58d7 100644
--- a/Labs/Lab.5/Lab.5.ipynb
+++ b/Labs/Lab.5/Lab.5.ipynb
@@ -20,7 +20,91 @@
" * Matrix instances `M` can be indexed with `M[i][j]` and `M[i,j]`.\n",
" * Matrix assignment works in 2 ways:\n",
" 1. If `M_1` and `M_2` are `matrix` instances `M_1=M_2` sets the values of `M_1` to those of `M_2`, if they are the same size. Error otherwise.\n",
- " 2. In example above `M_2` can be a list of lists of correct size.\n"
+ " 2. In example above `M_2` can be a list of lists of correct size."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "--- Q1 Tests ---\n",
+ "Q1 Initialization, Indexing, and Assignment tests passed!\n"
+ ]
+ }
+ ],
+ "source": [
+ "class matrix:\n",
+ " def __init__(self, *args):\n",
+ " # I'm checking if the arguments are two integers (n, m) to create a zero matrix\n",
+ " if len(args) == 2 and isinstance(args[0], int) and isinstance(args[1], int):\n",
+ " self.n, self.m = args[0], args[1]\n",
+ " self.data = [[0 for _ in range(self.m)] for _ in range(self.n)]\n",
+ " \n",
+ " # Or if the argument is a list of lists, I need to copy it over\n",
+ " elif len(args) == 1 and isinstance(args[0], list):\n",
+ " input_list = args[0]\n",
+ " self.n = len(input_list)\n",
+ " self.m = len(input_list[0]) if self.n > 0 else 0\n",
+ " \n",
+ " # Making sure every row has the same number of columns to catch bad inputs\n",
+ " if not all(isinstance(row, list) and len(row) == self.m for row in input_list):\n",
+ " raise ValueError(\"All rows must have the same number of columns.\")\n",
+ " \n",
+ " self.data = [[val for val in row] for row in input_list]\n",
+ " else:\n",
+ " raise ValueError(\"Need either (n, m) or a list of lists.\")\n",
+ "\n",
+ " def __getitem__(self, index):\n",
+ " # Python passes M[i,j] as a tuple, so I unpack it\n",
+ " if isinstance(index, tuple):\n",
+ " i, j = index\n",
+ " return self.data[i][j]\n",
+ " # For M[i][j], the first brackets pass an int, returning the whole row\n",
+ " elif isinstance(index, int):\n",
+ " return self.data[index]\n",
+ " else:\n",
+ " raise TypeError(\"Index needs to be an int or tuple.\")\n",
+ "\n",
+ " def __setitem__(self, index, value):\n",
+ " # Allowing value assignment like M[0,1] = 5\n",
+ " if isinstance(index, tuple):\n",
+ " i, j = index\n",
+ " self.data[i][j] = value\n",
+ " elif isinstance(index, int):\n",
+ " self.data[index] = value\n",
+ "\n",
+ " def assign(self, other):\n",
+ " # The assignment operator '=' cannot be overloaded in Python. \n",
+ " # Writing M_1 = M_2 just creates a reference copy, it doesn't modify the object's values.\n",
+ " # So, I'm using an assign() method to handle the specific assignment logic requested.\n",
+ " if isinstance(other, matrix):\n",
+ " if self.n != other.n or self.m != other.m:\n",
+ " raise ValueError(\"Size mismatch.\")\n",
+ " self.data = [[val for val in row] for row in other.data]\n",
+ " elif isinstance(other, list):\n",
+ " if len(other) != self.n or not all(len(row) == self.m for row in other):\n",
+ " raise ValueError(\"Size mismatch.\")\n",
+ " self.data = [[val for val in row] for row in other]\n",
+ "\n",
+ " def __str__(self):\n",
+ " return '\\n'.join([str(row) for row in self.data])\n",
+ "\n",
+ "# --- EXPLICIT TESTS FOR Q1 ---\n",
+ "print(\"--- Q1 Tests ---\")\n",
+ "m1 = matrix(2, 3)\n",
+ "assert m1.data == [[0, 0, 0], [0, 0, 0]]\n",
+ "m2 = matrix([[1, 2], [3, 4]])\n",
+ "assert m2.data == [[1, 2], [3, 4]]\n",
+ "\n",
+ "m_target = matrix(2, 2)\n",
+ "m_target.assign(m2)\n",
+ "assert m_target.data == [[1, 2], [3, 4]]\n",
+ "print(\"Q1 Initialization, Indexing, and Assignment tests passed!\")"
]
},
{
@@ -37,6 +121,100 @@
" "
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "--- Q2 Tests ---\n",
+ "Q2 Properties and Slicing tests passed!\n"
+ ]
+ }
+ ],
+ "source": [
+ "class matrix:\n",
+ " # --- Q1 Methods ---\n",
+ " def __init__(self, *args):\n",
+ " if len(args) == 2 and isinstance(args[0], int) and isinstance(args[1], int):\n",
+ " self.n, self.m = args[0], args[1]\n",
+ " self.data = [[0 for _ in range(self.m)] for _ in range(self.n)]\n",
+ " elif len(args) == 1 and isinstance(args[0], list):\n",
+ " input_list = args[0]\n",
+ " self.n, self.m = len(input_list), (len(input_list[0]) if len(input_list) > 0 else 0)\n",
+ " if not all(isinstance(row, list) and len(row) == self.m for row in input_list):\n",
+ " raise ValueError(\"All rows must have the same number of columns.\")\n",
+ " self.data = [[val for val in row] for row in input_list]\n",
+ "\n",
+ " def __getitem__(self, index):\n",
+ " # Upgraded to handle slicing. If the index contains a 'slice' object (like 0:2),\n",
+ " # I use list comprehensions to grab those specific chunks.\n",
+ " if isinstance(index, tuple):\n",
+ " i, j = index\n",
+ " if isinstance(i, slice) or isinstance(j, slice):\n",
+ " if isinstance(i, int): i = slice(i, i+1)\n",
+ " if isinstance(j, int): j = slice(j, j+1)\n",
+ " return matrix([row[j] for row in self.data[i]])\n",
+ " return self.data[i][j]\n",
+ " elif isinstance(index, slice):\n",
+ " return matrix(self.data[index])\n",
+ " elif isinstance(index, int):\n",
+ " return self.data[index]\n",
+ "\n",
+ " def __setitem__(self, index, value):\n",
+ " if isinstance(index, tuple): i, j = index; self.data[i][j] = value\n",
+ " elif isinstance(index, int): self.data[index] = value\n",
+ "\n",
+ " def assign(self, other):\n",
+ " if isinstance(other, matrix):\n",
+ " if self.shape() != other.shape(): raise ValueError(\"Size mismatch.\")\n",
+ " self.data = [[val for val in row] for row in other.data]\n",
+ " elif isinstance(other, list):\n",
+ " self.data = [[val for val in row] for row in other]\n",
+ " \n",
+ " def __str__(self): return '\\n'.join([str(row) for row in self.data])\n",
+ "\n",
+ " # --- Q2 New Methods ---\n",
+ " def shape(self):\n",
+ " # Simply returns the dimensions stored during init\n",
+ " return (self.n, self.m)\n",
+ "\n",
+ " def transpose(self):\n",
+ " # Swapping rows and columns to create the transposed version\n",
+ " t_data = [[self.data[i][j] for i in range(self.n)] for j in range(self.m)]\n",
+ " return matrix(t_data)\n",
+ "\n",
+ " def row(self, n):\n",
+ " # Wrapping the row in an extra list bracket so it becomes a 1xm matrix\n",
+ " return matrix([self.data[n]])\n",
+ "\n",
+ " def column(self, n):\n",
+ " # Grabbing the nth element of every row to build an nx1 matrix\n",
+ " return matrix([[self.data[i][n]] for i in range(self.n)])\n",
+ "\n",
+ " def to_list(self):\n",
+ " # Using a list comprehension to return a clean copy, avoiding reference bugs\n",
+ " return [[val for val in row] for row in self.data]\n",
+ "\n",
+ " def block(self, n_0, n_1, m_0, m_1):\n",
+ " # Standard Python slicing: grab rows m_0 to m_1, then slice those rows from cols n_0 to n_1\n",
+ " return matrix([r[n_0:n_1] for r in self.data[m_0:m_1]])\n",
+ "\n",
+ "# --- EXPLICIT TESTS FOR Q2 ---\n",
+ "print(\"--- Q2 Tests ---\")\n",
+ "m_test = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
+ "assert m_test.shape() == (3, 3)\n",
+ "assert m_test.transpose().data == [[1, 4, 7], [2, 5, 8], [3, 6, 9]]\n",
+ "assert m_test.row(1).data == [[4, 5, 6]]\n",
+ "assert m_test.column(2).data == [[3], [6], [9]]\n",
+ "assert m_test.to_list() == [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n",
+ "assert m_test.block(1, 3, 0, 2).data == [[2, 3], [5, 6]]\n",
+ "print(\"Q2 Properties and Slicing tests passed!\")"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -47,6 +225,49 @@
" * `eye(n)`: returns the n by n identity matrix."
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "--- Q3 Tests ---\n",
+ "Q3 Special Matrices tests passed!\n"
+ ]
+ }
+ ],
+ "source": [
+ "# --- Q3 Standalone Functions ---\n",
+ "\n",
+ "def constant(n, m, c):\n",
+ " # Creating an n by m matrix filled with the float version of c\n",
+ " val = float(c)\n",
+ " return matrix([[val for j in range(m)] for i in range(n)])\n",
+ "\n",
+ "def zeros(n, m):\n",
+ " # Reusing the constant function to avoid rewriting the same loops\n",
+ " return constant(n, m, 0.0)\n",
+ "\n",
+ "def ones(n, m):\n",
+ " # Same trick, reusing constant for 1.0\n",
+ " return constant(n, m, 1.0)\n",
+ "\n",
+ "def eye(n):\n",
+ " # Building the identity matrix: 1.0 on the diagonal (where i == j), 0.0 elsewhere\n",
+ " return matrix([[1.0 if i == j else 0.0 for j in range(n)] for i in range(n)])\n",
+ "\n",
+ "# --- EXPLICIT TESTS FOR Q3 ---\n",
+ "print(\"--- Q3 Tests ---\")\n",
+ "assert constant(2, 2, 5).data == [[5.0, 5.0], [5.0, 5.0]]\n",
+ "assert zeros(2, 3).data == [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]\n",
+ "assert ones(2, 2).data == [[1.0, 1.0], [1.0, 1.0]]\n",
+ "assert eye(3).data == [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]\n",
+ "print(\"Q3 Special Matrices tests passed!\")"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -74,6 +295,142 @@
" * M=N\n"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "--- Q4 & Q5 Tests ---\n",
+ "Q4 Math Methods and Q5 Overloaded Operators tests passed!\n"
+ ]
+ }
+ ],
+ "source": [
+ "class matrix:\n",
+ " # --- Q1 & Q2 Methods ---\n",
+ " def __init__(self, *args):\n",
+ " if len(args) == 2 and isinstance(args[0], int) and isinstance(args[1], int):\n",
+ " self.n, self.m = args[0], args[1]\n",
+ " self.data = [[0 for _ in range(self.m)] for _ in range(self.n)]\n",
+ " elif len(args) == 1 and isinstance(args[0], list):\n",
+ " input_list = args[0]\n",
+ " self.n, self.m = len(input_list), (len(input_list[0]) if len(input_list) > 0 else 0)\n",
+ " if not all(isinstance(row, list) and len(row) == self.m for row in input_list):\n",
+ " raise ValueError(\"All rows must have the same number of columns.\")\n",
+ " self.data = [[val for val in row] for row in input_list]\n",
+ "\n",
+ " def __getitem__(self, index):\n",
+ " if isinstance(index, tuple):\n",
+ " i, j = index\n",
+ " if isinstance(i, slice) or isinstance(j, slice):\n",
+ " if isinstance(i, int): i = slice(i, i+1)\n",
+ " if isinstance(j, int): j = slice(j, j+1)\n",
+ " return matrix([row[j] for row in self.data[i]])\n",
+ " return self.data[i][j]\n",
+ " elif isinstance(index, slice): return matrix(self.data[index])\n",
+ " elif isinstance(index, int): return self.data[index]\n",
+ "\n",
+ " def __setitem__(self, index, value):\n",
+ " if isinstance(index, tuple): i, j = index; self.data[i][j] = value\n",
+ " elif isinstance(index, int): self.data[index] = value\n",
+ "\n",
+ " def assign(self, other):\n",
+ " if isinstance(other, matrix):\n",
+ " if self.shape() != other.shape(): raise ValueError(\"Size mismatch.\")\n",
+ " self.data = [[val for val in row] for row in other.data]\n",
+ " elif isinstance(other, list):\n",
+ " self.data = [[val for val in row] for row in other]\n",
+ "\n",
+ " def shape(self): return (self.n, self.m)\n",
+ " def transpose(self): return matrix([[self.data[i][j] for i in range(self.n)] for j in range(self.m)])\n",
+ " def row(self, n): return matrix([self.data[n]])\n",
+ " def column(self, n): return matrix([[self.data[i][n]] for i in range(self.n)])\n",
+ " def to_list(self): return [[val for val in row] for row in self.data]\n",
+ " def block(self, n_0, n_1, m_0, m_1): return matrix([r[n_0:n_1] for r in self.data[m_0:m_1]])\n",
+ " def __str__(self): return '\\n'.join([str(row) for row in self.data])\n",
+ "\n",
+ " # --- Q4 Math Operations ---\n",
+ " def scalarmul(self, c):\n",
+ " return matrix([[val * c for val in row] for row in self.data])\n",
+ "\n",
+ " def add(self, N):\n",
+ " if self.shape() != N.shape(): raise ValueError(\"Addition error: Size mismatch.\")\n",
+ " return matrix([[self.data[i][j] + N.data[i][j] for j in range(self.m)] for i in range(self.n)])\n",
+ "\n",
+ " def sub(self, N):\n",
+ " if self.shape() != N.shape(): raise ValueError(\"Subtraction error: Size mismatch.\")\n",
+ " return matrix([[self.data[i][j] - N.data[i][j] for j in range(self.m)] for i in range(self.n)])\n",
+ "\n",
+ " def mat_mult(self, N):\n",
+ " if self.m != N.n: raise ValueError(\"Matrix multiplication error: M columns must equal N rows.\")\n",
+ " result_data = []\n",
+ " for i in range(self.n):\n",
+ " new_row = []\n",
+ " for j in range(N.m):\n",
+ " # taking the dot product of M's row and N's column\n",
+ " new_row.append(sum(self.data[i][k] * N.data[k][j] for k in range(self.m)))\n",
+ " result_data.append(new_row)\n",
+ " return matrix(result_data)\n",
+ "\n",
+ " def element_mult(self, N):\n",
+ " if self.shape() != N.shape(): raise ValueError(\"Element multiplication error: Size mismatch.\")\n",
+ " return matrix([[self.data[i][j] * N.data[i][j] for j in range(self.m)] for i in range(self.n)])\n",
+ "\n",
+ " def equals(self, N):\n",
+ " if not isinstance(N, matrix) or self.shape() != N.shape(): return False\n",
+ " return self.data == N.data\n",
+ "\n",
+ " # --- Q5 Operator Overloading ---\n",
+ " \n",
+ " # Python uses magic methods like __add__ to know what to do when you type '+'\n",
+ " def __add__(self, other):\n",
+ " return self.add(other)\n",
+ "\n",
+ " def __sub__(self, other):\n",
+ " return self.sub(other)\n",
+ "\n",
+ " def __mul__(self, other):\n",
+ " # I need to check if 'other' is a matrix or a scalar to decide which math rule to apply\n",
+ " if isinstance(other, matrix):\n",
+ " return self.mat_mult(other)\n",
+ " elif isinstance(other, (int, float)):\n",
+ " return self.scalarmul(other)\n",
+ "\n",
+ " def __rmul__(self, other):\n",
+ " # This handles the case where the scalar comes first, like 2 * M\n",
+ " return self.scalarmul(other)\n",
+ "\n",
+ " def __eq__(self, other):\n",
+ " # Overloads the '==' operator\n",
+ " return self.equals(other)\n",
+ " \n",
+ " # Note on M=N from Q5 requirements: Python physically cannot overload the '=' operator. \n",
+ " # So Using the assign() method implemented in Q1 to assign values without creating a reference copy.\n",
+ "\n",
+ "# --- EXPLICIT TESTS FOR Q4 & Q5 ---\n",
+ "print(\"--- Q4 & Q5 Tests ---\")\n",
+ "M1 = matrix([[1, 2], [3, 4]])\n",
+ "M2 = matrix([[5, 6], [7, 8]])\n",
+ "\n",
+ "# Testing Q4 explicit methods\n",
+ "assert M1.scalarmul(3).data == [[3, 6], [9, 12]]\n",
+ "assert M1.mat_mult(M2).data == [[19, 22], [43, 50]]\n",
+ "\n",
+ "# Testing Q5 overloaded operators\n",
+ "assert (M1 + M2).data == [[6, 8], [10, 12]]\n",
+ "assert (M1 - M2).data == [[-4, -4], [-4, -4]]\n",
+ "assert (M1 * M2).data == [[19, 22], [43, 50]]\n",
+ "assert (M1 * 2).data == [[2, 4], [6, 8]]\n",
+ "assert (2 * M1).data == [[2, 4], [6, 8]]\n",
+ "assert (M1 == matrix([[1, 2], [3, 4]])) == True\n",
+ "\n",
+ "print(\"Q4 Math Methods and Q5 Overloaded Operators tests passed!\")"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -94,6 +451,72 @@
"$$"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "--- Q6 Mathematical Demonstrations ---\n",
+ "\n",
+ "1. Demonstrating (AB)C = A(BC)\n",
+ "Is it true? True\n",
+ "\n",
+ "2. Demonstrating A(B+C) = AB + AC\n",
+ "Is it true? True\n",
+ "\n",
+ "3. Demonstrating AB != BA\n",
+ "Is it true? True\n",
+ "\n",
+ "4. Demonstrating AI = A\n",
+ "Is it true? True\n",
+ "\n",
+ "All Q6 linear algebra properties successfully demonstrated!\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Create test matrices\n",
+ "A = matrix([[1, 2], [3, 4]])\n",
+ "B = matrix([[5, 6], [7, 8]])\n",
+ "C = matrix([[9, 10], [11, 12]])\n",
+ "I = eye(2) \n",
+ "\n",
+ "print(\"--- Q6 Mathematical Demonstrations ---\\n\")\n",
+ "\n",
+ "# 1. Associativity: (AB)C = A(BC)\n",
+ "left_side = (A * B) * C\n",
+ "right_side = A * (B * C)\n",
+ "print(\"1. Demonstrating (AB)C = A(BC)\")\n",
+ "print(f\"Is it true? {left_side == right_side}\\n\")\n",
+ "assert left_side == right_side\n",
+ "\n",
+ "# 2. Distributivity: A(B+C) = AB + AC\n",
+ "left_side = A * (B + C)\n",
+ "right_side = (A * B) + (A * C)\n",
+ "print(\"2. Demonstrating A(B+C) = AB + AC\")\n",
+ "print(f\"Is it true? {left_side == right_side}\\n\")\n",
+ "assert left_side == right_side\n",
+ "\n",
+ "# 3. Non-commutativity: AB != BA\n",
+ "AB = A * B\n",
+ "BA = B * A\n",
+ "print(\"3. Demonstrating AB != BA\")\n",
+ "print(f\"Is it true? {not (AB == BA)}\\n\")\n",
+ "assert not (AB == BA)\n",
+ "\n",
+ "# 4. Identity: AI = A\n",
+ "AI = A * I\n",
+ "print(\"4. Demonstrating AI = A\")\n",
+ "print(f\"Is it true? {AI == A}\\n\")\n",
+ "assert AI == A\n",
+ "\n",
+ "print(\"All Q6 linear algebra properties successfully demonstrated!\")"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -104,7 +527,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3 (ipykernel)",
+ "display_name": "base",
"language": "python",
"name": "python3"
},
@@ -118,7 +541,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.13.12"
+ "version": "3.12.12"
}
},
"nbformat": 4,
diff --git a/Lectures/.DS_Store b/Lectures/.DS_Store
new file mode 100644
index 000000000..6ffb5a0dd
Binary files /dev/null and b/Lectures/.DS_Store differ