diff --git a/Algebra/Cholesky.py b/Algebra/Cholesky.py index 436cde6..8e8c120 100644 --- a/Algebra/Cholesky.py +++ b/Algebra/Cholesky.py @@ -1,16 +1,34 @@ import numpy as np from math import sqrt +def is_symmetric(A): + """Check if a matrix A is symmetric.""" + return np.allclose(A, A.T) + +def is_positive_definite(A): + """Check if a matrix A is positive definite by testing eigenvalues.""" + return np.all(np.linalg.eigvals(A) > 0) + def cholesky_decomposition(A): """ - Perform Cholesky decomposition on a matrix A. - A must be a symmetric, positive-definite matrix. + Perform Cholesky decomposition on a symmetric, positive-definite matrix A. + + Parameters: + A (ndarray): Symmetric, positive-definite matrix of size (n, n). - Returns the lower triangular matrix L such that A = L * L^T. + Returns: + ndarray: Lower triangular matrix L such that A = L * L.T. """ + # Validate the input matrix + if not is_symmetric(A): + raise ValueError("Matrix must be symmetric.") + if not is_positive_definite(A): + raise ValueError("Matrix must be positive-definite.") + n = len(A) L = np.zeros((n, n)) # Initialize L with zeros + # Perform Cholesky decomposition for k in range(n): # Calculate the diagonal element L[k][k] sum_squares = sum(L[k][j] ** 2 for j in range(k)) @@ -22,3 +40,18 @@ def cholesky_decomposition(A): L[i][k] = (A[i][k] - sum_products) / L[k][k] return L + +# Example usage +if __name__ == "__main__": + A = np.array([ + [4, 12, -16], + [12, 37, -43], + [-16, -43, 98] + ]) + + try: + L = cholesky_decomposition(A) + print("Cholesky Decomposition (Lower triangular matrix L):") + print(L) + except ValueError as e: + print(f"Error: {e}") diff --git a/Algebra/Gauss.py b/Algebra/Gauss.py index 01a629d..cdb381f 100644 --- a/Algebra/Gauss.py +++ b/Algebra/Gauss.py @@ -1,57 +1,74 @@ -from numpy import zeros,array, eye, copy, dot +import numpy as np -def Gauss(A,b): +def gaussian_elimination_with_pivoting(A, b): + """Perform Gaussian elimination with partial pivoting on matrix A and vector b.""" size = len(A) - A = array(A) - P = eye(size) - for i in range(size-1): - maxRow = i - for j in range(i+1,size): - if abs(A[j][i]) > abs(A[maxRow][i]): - maxRow = j - if maxRow != i: - #### Swap - P[[maxRow,i]] = P[[i, maxRow]] - A[[maxRow,i]] = A[[i, maxRow]] - for k in range(i+1, size): - A[k][i] /= A[i][i] - for j in range(i+1, size): - A[k][j] -= A[k][i]*A[i][j] - - L = eye(size) + A = np.array(A, dtype=float) # Ensure A is a float array + b = np.array(b, dtype=float) # Ensure b is a float array + P = np.eye(size) # Initialize the permutation matrix + + # Partial Pivoting and Elimination + for i in range(size - 1): + # Find the pivot row + max_row = max(range(i, size), key=lambda k: abs(A[k][i])) + if max_row != i: + # Swap rows in both A and P for pivoting + A[[i, max_row]] = A[[max_row, i]] + P[[i, max_row]] = P[[max_row, i]] + b[i], b[max_row] = b[max_row], b[i] # Also swap entries in b + + # Perform elimination + for k in range(i + 1, size): + factor = A[k][i] / A[i][i] + A[k, i:] -= factor * A[i, i:] # Update only remaining elements in row + b[k] -= factor * b[i] # Update b vector accordingly + + # Extract L and U matrices from A + L = np.eye(size) + U = np.zeros((size, size)) for i in range(size): - for j in range(i): - L[i][j] = A[i][j] + for j in range(size): + if i > j: + L[i][j] = A[i][j] + else: + U[i][j] = A[i][j] - U = zeros((size,size)) + return P, L, U, b + +def forward_substitution(L, Pb): + """Solve the equation Ly = Pb using forward substitution.""" + size = len(L) + y = np.zeros(size) for i in range(size): - for j in range(i,size): - U[i][j] = A[i][j] + y[i] = (Pb[i] - np.dot(L[i, :i], y[:i])) / L[i][i] + return y - b = array(b) +def backward_substitution(U, y): + """Solve the equation Ux = y using backward substitution.""" + size = len(U) + x = np.zeros(size) + for i in range(size - 1, -1, -1): + x[i] = (y[i] - np.dot(U[i, i + 1:], x[i + 1:])) / U[i][i] + return x - y = copy(dot(P,b)) +def solve_gaussian(A, b): + """Main function to solve the system Ax = b using Gaussian elimination with pivoting.""" + # Step 1: Gaussian Elimination with Partial Pivoting to get P, L, U + P, L, U, Pb = gaussian_elimination_with_pivoting(A, b) - # forwards - for i in range(size): - if L[i][i] == 0: #Division by 0 - y[i] = 0 - continue - for j in range(i): - y[i] = (y[i] - L[i][j]*y[j])/L[i][i] - - - x = zeros((size,1)) - x[size-1] = y[size-1]/U[size-1][size-1] - - for i in range(size-1,-1,-1): - if U[i][i] == 0: #Division by 0 - x[i] = 0 - continue - xv = y[i] - for j in range(i+1,size): - xv -= U[i][j]*x[j] - xv /= U[i][i] - x[i] = xv - - return x \ No newline at end of file + # Step 2: Forward substitution to solve Ly = Pb + y = forward_substitution(L, Pb) + + # Step 3: Backward substitution to solve Ux = y + x = backward_substitution(U, y) + + return x + +# Example usage: +A = [[2, -1, 1], + [3, 3, 9], + [3, 3, 5]] +b = [2, -1, 4] + +x = solve_gaussian(A, b) +print("Solution x:", x) diff --git a/Algebra/function_to_graph.py b/Algebra/function_to_graph.py index 6464621..ecde3b2 100644 --- a/Algebra/function_to_graph.py +++ b/Algebra/function_to_graph.py @@ -1,41 +1,53 @@ import matplotlib.pyplot as plt import numpy as np - - -xmin = -100 -xmax = 100 -ymin = -100 -ymax = 100 -points = xmax - xmin -x = np.linspace(xmin, xmax, points) - - -while True: - eq = input("Enter the equation for y in terms of x: ") - - # Use eval() to evaluate the user's input as a mathematical expression +import sympy as sp + +def get_user_equation(): + """Prompts the user to input an equation for y in terms of x.""" + while True: + eq = input("Enter the equation for y in terms of x: ") + try: + x = sp.symbols('x') + y_expr = sp.sympify(eq) + y_func = sp.lambdify(x, y_expr, 'numpy') + return y_func, eq + except (sp.SympifyError, TypeError): + print("Invalid equation. Please enter a valid mathematical expression.") + +def plot_graph(y_func, equation_str): + """Plots the graph of the equation y = y_func(x).""" + # Set the graph limits and generate x values + xmin, xmax = -100, 100 + ymin, ymax = -100, 100 + x = np.linspace(xmin, xmax, 500) + + # Calculate y values safely, handling any runtime issues try: - y = eval(eq) # Evaluate the expression with x as a variable - break - except: - print("Invalid input equation.") - - -fig, ax = plt.subplots() -plt.axis([xmin, xmax, ymin, ymax]) -plt.plot([xmin, xmax], [0, 0], "b") -plt.plot([0, 0], [ymin, ymax], "b") - -ax.set_xlabel("x values") -ax.set_ylabel("y values") -ax.set_title("Equation Graph") -ax.grid(True) - -ax.set_xticks(np.arange(xmin, xmax, 20)) -ax.set_yticks(np.arange(ymin, ymax, 20)) - - -plt.plot(x, y, label=f"y= {eq}") - -plt.legend() -plt.show() + y = y_func(x) + except Exception as e: + print(f"Error evaluating the equation over the range: {e}") + return + + # Initialize plot + fig, ax = plt.subplots() + ax.set_xlim(xmin, xmax) + ax.set_ylim(ymin, ymax) + ax.plot([xmin, xmax], [0, 0], "b") # x-axis + ax.plot([0, 0], [ymin, ymax], "b") # y-axis + + # Plot settings + ax.set_xlabel("x values") + ax.set_ylabel("y values") + ax.set_title(f"Graph of y = {equation_str}") + ax.grid(True) + ax.set_xticks(np.arange(xmin, xmax + 1, 20)) + ax.set_yticks(np.arange(ymin, ymax + 1, 20)) + + # Plot the equation + ax.plot(x, y, label=f"y = {equation_str}", color='red') + ax.legend() + plt.show() + +if __name__ == "__main__": + y_function, equation_text = get_user_equation() + plot_graph(y_function, equation_text) diff --git a/Algebra/graphing_calculator.py b/Algebra/graphing_calculator.py index c3122d6..e779c86 100644 --- a/Algebra/graphing_calculator.py +++ b/Algebra/graphing_calculator.py @@ -1,157 +1,159 @@ import numpy as np import matplotlib.pyplot as plt -from sympy import * +from sympy import symbols, linsolve, sqrt def main(): while True: - print("\nMenu:") - print("1. Display the graph and table of values for an equation") - print("2. Solve a system of two equations without graphing") - print("3. Graph two equations and plot the point of intersection") - print("4. Plot the roots and vertex of a quadratic equation") - print("5. Exit") + display_main_menu() + choice = input("Enter your choice (1-5): ").strip() - choice = input("Enter your choice: ") - - if choice == '1': - display_graph_and_table() - elif choice == '2': - solve_system_of_equations() - elif choice == '3': - graph_and_find_intersection() - elif choice == '4': - plot_quadratic_roots_and_vertex() - elif choice == '5': - break + options = { + '1': display_graph_and_table, + '2': solve_system_of_equations, + '3': graph_and_find_intersection, + '4': plot_quadratic_roots_and_vertex, + '5': exit_program + } + + operation = options.get(choice) + if operation: + operation() else: print("Invalid choice. Please try again.") +def display_main_menu(): + """Display the main menu options.""" + print("\nMenu:") + print("1. Display the graph and table of values for an equation") + print("2. Solve a system of two equations without graphing") + print("3. Graph two equations and plot the point of intersection") + print("4. Plot the roots and vertex of a quadratic equation") + print("5. Exit") + def display_graph_and_table(): - equation = input("Enter the equation in terms of 'x': y = ") - x = np.linspace(-10, 10, 400) # Adjust the range as needed - y = eval(equation) - plt.plot(x, y) + """Display graph and table of values for a user-input equation.""" + equation = input("Enter the equation in terms of 'x' (e.g., 'x**2 + 2*x - 3'): y = ") + x_values = np.linspace(-10, 10, 400) + try: + y_values = eval(equation) + plot_graph(x_values, y_values, equation) + display_table(x_values, y_values) + except (NameError, SyntaxError): + print("Invalid equation. Please enter a valid equation in terms of 'x'.") + +def plot_graph(x_values, y_values, equation): + """Plot a graph for the provided x and y values.""" + plt.plot(x_values, y_values) plt.xlabel('x') plt.ylabel('y') - plt.title(f'Graph of {equation}') + plt.title(f'Graph of y = {equation}') plt.grid(True) plt.show() - display_table(equation) - -def display_table(equation): - ax = plt.subplot() - ax.set_axis_off() - title = f"y = {equation}" - cols = ('x', 'y') - rows = [[0, 0]] - for x in range(1, 10): - rows.append([x, eval(equation)]) - - ax.set_title(title) - plt.table(cellText=rows, colLabels=cols, cellLoc='center', loc='upper left') - plt.show() + +def display_table(x_values, y_values): + """Display a table of values for the equation.""" + print("\n x y") + print("-----------------") + for x, y in zip(x_values[::40], y_values[::40]): + print(f"{x:.2f} {y:.2f}") def solve_system_of_equations(): + """Solve a system of two equations without graphing.""" x, y = symbols('x y') - print("Remember to use Python syntax with x and y as variables") - print("Notice how each equation is already set equal to zero") - first = input("Enter the first equation: 0 = ") - second = input("Enter the second equation: 0 = ") - solution = linsolve([first, second], (x, y)) - x_solution = solution.args[0][0] - y_solution = solution.args[0][1] - - print("x = ", x_solution) - print("y = ", y_solution) + eq1 = input("Enter the first equation in terms of x and y (e.g., 'x + y - 3'): ") + eq2 = input("Enter the second equation in terms of x and y (e.g., '2*x - y - 1'): ") + try: + solution = linsolve([eq1, eq2], (x, y)) + if solution: + x_solution, y_solution = solution.args[0] + print(f"x = {x_solution}, y = {y_solution}") + else: + print("No solutions found.") + except Exception: + print("Invalid input. Make sure the equations are in terms of x and y.") def graph_and_find_intersection(): - print("First equation: y = mx + b") - mb_1 = input("Enter m and b, separated by a comma: ") - mb_in1 = mb_1.split(",") - m1 = float(mb_in1[0]) - b1 = float(mb_in1[1]) - - print("Second equation: y = mx + b") - mb_2 = input("Enter m and b, separated by a comma: ") - mb_in2 = mb_2.split(",") - m2 = float(mb_in2[0]) - b2 = float(mb_in2[1]) - - # Solve the system of equations - x, y = symbols('x y') - first = m1 * x + b1 - y - second = m2 * x + b2 - y - solution = linsolve([first, second], (x, y)) - x_solution = round(float(solution.args[0][0]), 3) - y_solution = round(float(solution.args[0][1]), 3) - - # Make sure the window includes the solution - xmin = int(x_solution) - 20 - xmax = int(x_solution) + 20 - ymin = int(y_solution) - 20 - ymax = int(y_solution) + 20 - points = 2 * (xmax - xmin) - - # Define the x values once for the graph - graph_x = np.linspace(xmin, xmax, points) - - # Define the y values for the graph - y1 = m1 * graph_x + b1 - y2 = m2 * graph_x + b2 - - fig, ax = plt.subplots() - plt.axis([xmin, xmax, ymin, ymax]) # window size - plt.plot([xmin, xmax], [0, 0], 'b') # blue x-axis - plt.plot([0, 0], [ymin, ymax], 'b') # blue y-axis - - # line 1 - plt.plot(graph_x, y1) - - # line 2 - plt.plot(graph_x, y2) - - # point - plt.plot([x_solution], [y_solution], 'ro') + """Graph two linear equations and plot their intersection point.""" + m1, b1 = get_slope_intercept("first") + m2, b2 = get_slope_intercept("second") + # Solve for the intersection + x, y = symbols('x y') + solution = linsolve([m1 * x + b1 - y, m2 * x + b2 - y], (x, y)) + if solution: + x_intersect, y_intersect = map(float, solution.args[0]) + print(f"Intersection at: ({x_intersect:.2f}, {y_intersect:.2f})") + plot_lines_with_intersection(m1, b1, m2, b2, x_intersect, y_intersect) + else: + print("The lines are parallel and do not intersect.") + +def get_slope_intercept(label): + """Prompt the user to enter the slope and intercept.""" + while True: + try: + m, b = map(float, input(f"Enter the slope and intercept for the {label} line, separated by a comma (e.g., '2, 3'): ").split(",")) + return m, b + except ValueError: + print("Invalid input. Please enter two numbers separated by a comma.") + +def plot_lines_with_intersection(m1, b1, m2, b2, x_intersect, y_intersect): + """Plot two lines and their intersection point.""" + x_vals = np.linspace(x_intersect - 10, x_intersect + 10, 200) + y1_vals = m1 * x_vals + b1 + y2_vals = m2 * x_vals + b2 + + plt.plot(x_vals, y1_vals, label=f"y = {m1}x + {b1}") + plt.plot(x_vals, y2_vals, label=f"y = {m2}x + {b2}") + plt.plot(x_intersect, y_intersect, 'ro', label=f"Intersection ({x_intersect:.2f}, {y_intersect:.2f})") + plt.xlabel('x') + plt.ylabel('y') + plt.title('Intersection of Two Lines') + plt.grid(True) + plt.legend() plt.show() - print(" ") - print("Solution: (", x_solution, ",", y_solution, ")") def plot_quadratic_roots_and_vertex(): - print("y = ax² + bx + c") - a = float(input("Enter the coefficient 'a' of the quadratic equation: ")) - b = float(input("Enter the coefficient 'b' of the quadratic equation: ")) - c = float(input("Enter the coefficient 'c' of the quadratic equation: ")) - xmin = -10 - xmax = 10 - ymin = -10 - ymax = 10 - points = 2 * (xmax - xmin) - x = np.linspace(xmin, xmax, points) - y = a * x**2 + b * x + c - plt.plot(x, y, label=f'y = {a}x^2 + {b}x + {c}') + """Plot the roots and vertex of a quadratic equation.""" + a, b, c = get_quadratic_coefficients() + x_vals = np.linspace(-10, 10, 400) + y_vals = a * x_vals**2 + b * x_vals + c + + # Plot the quadratic equation + plt.plot(x_vals, y_vals, label=f"y = {a}x^2 + {b}x + {c}") plt.xlabel('x') plt.ylabel('y') plt.title('Quadratic Equation') plt.grid(True) - # Calculate the roots using the quadratic formula + # Calculate roots discriminant = b**2 - 4 * a * c - if discriminant > 0: + if discriminant >= 0: root1 = (-b + np.sqrt(discriminant)) / (2 * a) root2 = (-b - np.sqrt(discriminant)) / (2 * a) - plt.scatter([root1, root2], [0, 0], color='green', label=f'Roots: x1={root1}, x2={root2}') - elif discriminant == 0: - root = -b / (2 * a) - plt.scatter(root, 0, color='green', label=f'Root: x={root}') + plt.scatter([root1, root2], [0, 0], color='green', label=f"Roots: x1={root1:.2f}, x2={root2:.2f}") # Calculate the vertex vertex_x = -b / (2 * a) vertex_y = a * vertex_x**2 + b * vertex_x + c - plt.scatter(vertex_x, vertex_y, color='blue', label=f'Vertex ({vertex_x}, {vertex_y})') + plt.scatter(vertex_x, vertex_y, color='blue', label=f"Vertex ({vertex_x:.2f}, {vertex_y:.2f})") plt.legend() plt.show() +def get_quadratic_coefficients(): + """Prompt the user to enter coefficients for a quadratic equation.""" + while True: + try: + a = float(input("Enter coefficient 'a': ")) + b = float(input("Enter coefficient 'b': ")) + c = float(input("Enter coefficient 'c': ")) + return a, b, c + except ValueError: + print("Invalid input. Please enter numeric coefficients.") + +def exit_program(): + """Exit the program.""" + exit() + if __name__ == '__main__': main() diff --git a/Algebra/simple_calculator.py b/Algebra/simple_calculator.py index 3f18edd..355af36 100644 --- a/Algebra/simple_calculator.py +++ b/Algebra/simple_calculator.py @@ -4,169 +4,164 @@ import sys def main(): - - while True: - - main_menu() - choice = input("Enter your choice (1-12): ") - - if choice == '1': - perform_operation(add) - elif choice == '2': - perform_operation(subtract) - elif choice == '3': - perform_operation(multiply) - elif choice == '4': - perform_operation(divide) - elif choice == '5': - perform_operation(prime_number) - elif choice == '6': - perform_operation(prime_factor) - elif choice == '7': - perform_operation(square_root) - elif choice == '8': - perform_operation(solve) - elif choice == '9': - perform_operation(convert_decimals_to) - elif choice == '10': - perform_operation(convert_fractions_to) - elif choice == '11': - perform_operation(convert_percents_to) - elif choice == '12': - print("Goodbye!") - break - else: - print("Invalid choice. Please choose a valid option (1-12).") - - - - - + while True: + main_menu() + choice = input("Enter your choice (1-12): ").strip() + + options = { + '1': add, + '2': subtract, + '3': multiply, + '4': divide, + '5': prime_number, + '6': prime_factors, + '7': square_root_factorization, + '8': solve_equation, + '9': convert_decimals_to, + '10': convert_fractions_to, + '11': convert_percents_to, + '12': exit_program + } + + operation = options.get(choice) + if operation: + perform_operation(operation) + else: + print("Invalid choice. Please choose a valid option (1-12).") def add(): - try: - a = int(input('Enter an integer: ')) - b = int(input('Enter an integer: ')) - print(f"a+b = {a+b}") - except ValueError: - print("Invalid input. Please enter integers only.") + """Add two integers.""" + a, b = get_two_integers() + print(f"{a} + {b} = {a + b}") def subtract(): - try: - a = int(input('Enter an integer: ')) - b = int(input('Enter an integer: ')) - print(f"a-b = {a-b}") - except ValueError: - print("Invalid input. Please enter integers only.") + """Subtract two integers.""" + a, b = get_two_integers() + print(f"{a} - {b} = {a - b}") def multiply(): - try: - a = int(input('Enter an integer: ')) - b = int(input('Enter an integer: ')) - print(f"a*b = {a*b}") - except ValueError: - print("Invalid input. Please enter integers only.") + """Multiply two integers.""" + a, b = get_two_integers() + print(f"{a} * {b} = {a * b}") def divide(): - try: - a = int(input('Enter an integer: ')) - b = int(input('Enter an integer: ')) + """Divide two integers.""" + a, b = get_two_integers() if b == 0: - print("Cannot divide by zero!") + print("Cannot divide by zero!") else: - print(f"a/b = {a/b}") - except ValueError: - print("Invalid input. Please enter integers only.") + print(f"{a} / {b} = {a / b}") + def prime_number(): - try: - number = int(input("Enter a positive integer: ")) - if number <= 0: - print("Invalid input. Please enter a positive integer.") - return - is_prime = all(number % i != 0 for i in range(2, number)) - print("prime" if is_prime else "composite") - except ValueError: - print("Invalid input. Please enter a positive integer.") - -def prime_factor(): - try: - number = int(input('Enter an integer: ')) - if number <= 0: - print("Invalid input. Please enter a positive integer.") + """Check if a number is prime.""" + number = get_positive_integer() + if number < 2: + print("Numbers less than 2 are not prime.") return - factors = [i for i in range(1, number + 1) if number % i == 0] - print(factors) - except ValueError: - print("Invalid input. Please enter a positive integer.") - -def square_root(): - try: - n = int(input('Without the radical, enter a square root to factor: ')) - if n <= 0: - print("Invalid input. Please enter a positive integer.") - return - max_factor = max(i**2 for i in range(1, math.isqrt(n) + 1) if n % (i**2) == 0) - other_factor = n // max_factor - square_root = int(math.sqrt(max_factor)) - output = square_root * sqrt(other_factor) - print(output) - except ValueError: - print("Invalid input. Please enter a positive integer.") - -def solve(): - try: + is_prime = all(number % i != 0 for i in range(2, int(math.sqrt(number)) + 1)) + print("Prime" if is_prime else "Composite") + +def prime_factors(): + """Find all prime factors of a number.""" + number = get_positive_integer() + factors = [] + divisor = 2 + while number > 1: + while number % divisor == 0: + factors.append(divisor) + number //= divisor + divisor += 1 + print(f"Prime factors: {factors}") + +def square_root_factorization(): + """Factor a number under the square root.""" + n = get_positive_integer() + max_square = max(i**2 for i in range(1, int(math.isqrt(n)) + 1) if n % (i**2) == 0) + other_factor = n // max_square + result = int(math.sqrt(max_square)) * sqrt(other_factor) + print(f"√{n} = {result}") + +def solve_equation(): + """Solve an equation for x.""" x = symbols('x') - eq = input('Enter an equation to solve for x: 0 = ') - solutions = solve(eq, x) - print(f"x = {solutions[0]}" if solutions else "No solutions found.") - except (ValueError, TypeError, IndexError): - print("Invalid equation or no solutions found.") + eq = input('Enter an equation to solve for x (in the form "0 = equation"): ').strip() + try: + solutions = solve(eq, x) + print(f"x = {solutions[0]}" if solutions else "No solutions found.") + except (ValueError, TypeError): + print("Invalid equation or no solutions found.") def convert_decimals_to(): - try: - decimal = float(input("Enter a decimal number to convert: ")) + """Convert decimal to fraction and percent.""" + decimal = get_float("Enter a decimal number to convert: ") fraction = Fraction(decimal).limit_denominator() percent = decimal * 100 - print(f"The decimal is {decimal}") print(f"The fraction is {fraction}") print(f"The percent is {percent}%") - except ValueError: - print("Invalid input. Please enter a valid decimal number.") def convert_fractions_to(): - try: - fraction = input("Enter a fraction (numerator/denominator): ") - numerator, denominator = map(int, fraction.split("/")) - decimal = numerator / denominator - percent = decimal * 100 - print(f"The decimal is {decimal}") - print(f"The percent is {percent}%") - except (ValueError, ZeroDivisionError): - print("Invalid input. Please enter a valid fraction.") + """Convert fraction to decimal and percent.""" + try: + fraction = input("Enter a fraction (numerator/denominator): ").strip() + numerator, denominator = map(int, fraction.split("/")) + decimal = numerator / denominator + percent = decimal * 100 + print(f"The decimal is {decimal}") + print(f"The percent is {percent}%") + except (ValueError, ZeroDivisionError): + print("Invalid input. Please enter a valid fraction.") def convert_percents_to(): - try: - percent = float(input("Enter a percent: ").strip("%")) + """Convert percent to decimal and fraction.""" + percent = get_float("Enter a percent (without % sign): ") decimal = percent / 100 fraction = Fraction(decimal).limit_denominator() print(f"The decimal is {decimal}") print(f"The fraction is {fraction}") - except ValueError: - print("Invalid input. Please enter a valid percent.") -# Write your code here +def get_two_integers(): + """Get two integers from the user with error handling.""" + try: + a = int(input('Enter first integer: ')) + b = int(input('Enter second integer: ')) + return a, b + except ValueError: + print("Invalid input. Please enter integers only.") + return get_two_integers() + +def get_positive_integer(): + """Get a positive integer from the user with error handling.""" + try: + n = int(input('Enter a positive integer: ')) + if n <= 0: + raise ValueError + return n + except ValueError: + print("Invalid input. Please enter a positive integer.") + return get_positive_integer() + +def get_float(prompt): + """Get a float value from the user with error handling.""" + try: + return float(input(prompt)) + except ValueError: + print("Invalid input. Please enter a valid number.") + return get_float(prompt) def perform_operation(operation_func): + """Perform a selected operation.""" operation_func() if not continue_calculations(): sys.exit("Goodbye") def continue_calculations(): - check = input("Do you want to continue calculations? (Y/N): ").upper() - return check != "N" + """Prompt the user to continue calculations.""" + check = input("Do you want to continue calculations? (Y/N): ").strip().upper() + return check == "Y" def main_menu(): - print("Menu:") + """Display the main menu.""" + print("\nMenu:") print("1. Add") print("2. Subtract") print("3. Multiply") @@ -180,6 +175,9 @@ def main_menu(): print("11. Convert percents to decimals and fractions") print("12. Exit") +def exit_program(): + """Exit the program.""" + sys.exit() -if __name__=='__main__': +if __name__ == '__main__': main() diff --git a/Algebra/slope_intecept.py b/Algebra/slope_intecept.py index df1c899..b844b9d 100644 --- a/Algebra/slope_intecept.py +++ b/Algebra/slope_intecept.py @@ -1,37 +1,64 @@ import matplotlib.pyplot as plt -x1 = int(input("Please type x1 value :")) -y1 = int(input("Please type y1 value :")) -x2 = int(input("Please type x2 value :")) -y2 = int(input("Please type y2 value :")) +def get_point_input(point_label): + """Get the (x, y) coordinates of a point from user input.""" + while True: + try: + x = int(input(f"Please type the x value for {point_label}: ")) + y = int(input(f"Please type the y value for {point_label}: ")) + return x, y + except ValueError: + print("Invalid input. Please enter integer values.") -# Develop the equation y = mx + b -m = (y2 - y1) / (x2 - x1) -b = y1 - m*x1 -equation = f'y = {m}x + {b}' +def calculate_line_equation(x1, y1, x2, y2): + """Calculate the slope (m) and intercept (b) of the line passing through points (x1, y1) and (x2, y2).""" + if x1 == x2: + raise ValueError("The points have the same x-coordinate; the line is vertical, and slope is undefined.") + + m = (y2 - y1) / (x2 - x1) + b = y1 - m * x1 + return m, b -# For the graph -xmin = -10 -xmax = 10 -ymin = -10 -ymax = 10 +def plot_line_and_points(x1, y1, x2, y2, m, b): + """Plot the line y = mx + b along with the points (x1, y1) and (x2, y2) on a graph.""" + # Define the x range based on the input points, with some padding + x_min = min(x1, x2) - 5 + x_max = max(x1, x2) + 5 + y_min = min(y1, y2, m * x_min + b, m * x_max + b) - 5 + y_max = max(y1, y2, m * x_min + b, m * x_max + b) + 5 -# For the line on the graph -y3 = m*xmin + b -y4 = m*xmax + b + # Define the y values of the line at the x_min and x_max boundaries + y_start = m * x_min + b + y_end = m * x_max + b -# Basic setup for the graph -fig, ax = plt.subplots() -plt.axis([xmin,xmax,ymin,ymax]) # window size -plt.plot([xmin,xmax],[0,0],'b') # blue x axis -plt.plot([0,0],[ymin,ymax], 'b') # blue y axis + # Set up the plot + plt.figure(figsize=(8, 6)) + plt.plot([x_min, x_max], [y_start, y_end], 'r', label=f'y = {m:.2f}x + {b:.2f}') + plt.scatter([x1, x2], [y1, y2], color='green', marker='o', label=f'Points ({x1}, {y1}), ({x2}, {y2})') + + # Add axis lines and labels + plt.axhline(0, color='blue', linewidth=0.5) # x-axis + plt.axvline(0, color='blue', linewidth=0.5) # y-axis + plt.xlim(x_min, x_max) + plt.ylim(y_min, y_max) + # Title, legend, and grid + plt.xlabel('x') + plt.ylabel('y') + plt.title('Graph of the Linear Equation') + plt.legend() + plt.grid(True) + plt.show() -# Plot the linear function as a red line -plt.plot([xmin,xmax],[y3,y4],'r',label=equation) -plt.scatter([x1, x2], [y1, y2], color='green', marker='o', label=f'Points ({x1}, {y1}), ({x2}, {y2})') +def main(): + print("Let's find the equation of the line passing through two points and plot it.") + try: + x1, y1 = get_point_input("point 1") + x2, y2 = get_point_input("point 2") + m, b = calculate_line_equation(x1, y1, x2, y2) + plot_line_and_points(x1, y1, x2, y2, m, b) + except ValueError as e: + print(e) - - -plt.legend() -plt.show() \ No newline at end of file +if __name__ == "__main__": + main() diff --git a/Neuronal-Red/temperature_prediction.py b/Neuronal-Red/temperature_prediction.py index 08bff20..f286d4b 100644 --- a/Neuronal-Red/temperature_prediction.py +++ b/Neuronal-Red/temperature_prediction.py @@ -1,35 +1,54 @@ import tensorflow as tf import numpy as np -# Input data +# Input data: Celsius to Fahrenheit conversion data celsius = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=np.float16) fahrenheit = np.array([-40, 14, 32, 46, 59, 72, 100], dtype=np.float16) -# Model definition -hidden1 = tf.keras.layers.Dense(units=3, input_shape=[1]) -hidden2 = tf.keras.layers.Dense(units=3) -output = tf.keras.layers.Dense(units=1) -model = tf.keras.Sequential([hidden1, hidden2, output]) - -# Model compilation -model.compile( - optimizer=tf.keras.optimizers.Adam(0.1), - loss='mean_squared_error' -) - -# Model training -print("Starting training...") -history = model.fit(celsius, fahrenheit, epochs=1000, verbose=False) -print("Model trained!") - -# Making a prediction -print("Let's make a prediction!") -result = model.predict([89.0]) -print("The result is " + str(result) + " fahrenheit") - -# Viewing the internal variables of the model -print("Internal model variables") -print(hidden1.get_weights()) -print(hidden2.get_weights()) -print(output.get_weights()) +def build_model(): + """Build a simple neural network model for temperature conversion.""" + # Model definition with two hidden layers and one output layer + hidden1 = tf.keras.layers.Dense(units=3, input_shape=[1], activation="relu") + hidden2 = tf.keras.layers.Dense(units=3, activation="relu") + output = tf.keras.layers.Dense(units=1) # Linear output for regression + model = tf.keras.Sequential([hidden1, hidden2, output]) + # Model compilation + model.compile(optimizer=tf.keras.optimizers.Adam(0.1), + loss='mean_squared_error') + return model, hidden1, hidden2, output + +def train_model(model, inputs, targets, epochs=1000): + """Train the model on the provided inputs and targets.""" + print("Starting training...") + history = model.fit(inputs, targets, epochs=epochs, verbose=False) + print("Model trained!") + return history + +def make_prediction(model, value): + """Make a prediction with the trained model.""" + print(f"Making a prediction for Celsius value: {value}") + result = model.predict([value]) + print(f"The result is {result[0][0]:.2f} Fahrenheit") + return result[0][0] + +def view_model_weights(hidden1, hidden2, output): + """Display weights for each layer in the model.""" + print("\nInternal model variables (weights and biases):") + print("Hidden Layer 1 weights and biases:") + print(hidden1.get_weights()) + print("\nHidden Layer 2 weights and biases:") + print(hidden2.get_weights()) + print("\nOutput Layer weights and biases:") + print(output.get_weights()) + +if __name__ == "__main__": + # Build and train the model + model, hidden1, hidden2, output = build_model() + history = train_model(model, celsius, fahrenheit, epochs=1000) + + # Make a prediction + fahrenheit_prediction = make_prediction(model, 89.0) + + # View the internal weights of the model + view_model_weights(hidden1, hidden2, output) diff --git a/Password_Manager/project.py b/Password_Manager/project.py index 3c695b1..765f28e 100644 --- a/Password_Manager/project.py +++ b/Password_Manager/project.py @@ -4,11 +4,14 @@ import os import time from colorama import Fore, Style +import hashlib +import bcrypt STRING_LENGTH = 6 PUNCTUATION_LENGTH = 4 PASSWORD_FILE = "password.csv" + def main_menu(): """Display the main menu and get the user's choice.""" menu = [ @@ -25,6 +28,7 @@ def main_menu(): print("\n".join(menu)) return input("Pick a number: ") + def validate_aim(aim): """Validate if the aim is not empty.""" if not aim: @@ -32,6 +36,7 @@ def validate_aim(aim): return False return True + def read_csv_file(): """Read the CSV file and return the data as a list of dictionaries.""" if not os.path.isfile(PASSWORD_FILE): @@ -39,6 +44,7 @@ def read_csv_file(): with open(PASSWORD_FILE, "r") as csvfile: return list(csv.DictReader(csvfile)) + def write_csv_file(data): """Write the data to the CSV file.""" with open(PASSWORD_FILE, "w", newline="") as csvfile: @@ -46,6 +52,7 @@ def write_csv_file(data): writer.writeheader() writer.writerows(data) + def password_generator(): """Generate a random password with lowercase, uppercase, punctuation, and numeric characters.""" char_sets = [string.ascii_lowercase, string.ascii_uppercase, string.punctuation, string.digits] @@ -54,52 +61,65 @@ def password_generator(): random.shuffle(password) return "".join(password) + def display_message(message, color=Fore.GREEN): """Display a message in the specified color.""" print(color + message + Style.RESET_ALL) time.sleep(2) + def create_password(aim): """Create a new password for a given aim and save it to the CSV file.""" if not validate_aim(aim): return data = read_csv_file() + if aim in [row["aim"] for row in data]: display_message(f"'{aim}' is unavailable. Please use a different aim.", Fore.RED) return + password = password_generator() - data.append({"aim": aim, "password": password}) + hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') + data.append({"aim": aim, "password": hashed_password}) write_csv_file(data) display_message(f"Password created successfully.\n{aim} password is: {password}") + def check_password(aim): """Check the password for a given aim from the CSV file.""" if not validate_aim(aim): return None data = read_csv_file() + for row in data: if aim == row["aim"]: return row["password"] display_message("No password found for the specified aim.", Fore.RED) return None + def edit_password(aim): """Edit the password for a given aim in the CSV file.""" if not validate_aim(aim): return data = read_csv_file() + for row in data: if aim == row["aim"]: new_password = input("Enter the new password: ") if new_password != input("Re-enter the new password: "): display_message("Passwords do not match. Password update failed.", Fore.RED) return - row["password"] = new_password + + hashed_password = bcrypt.hashpw(new_password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') + row["password"] = hashed_password write_csv_file(data) display_message(f"Password updated successfully.\nYour new password is {new_password}.") return + display_message(f"No password found for '{aim}'.", Fore.RED) + def del_password(aim): """Delete a password entry for a given aim from the CSV file.""" if not validate_aim(aim): @@ -112,22 +132,26 @@ def del_password(aim): write_csv_file(new_data) display_message(f"Password deleted successfully for aim: {aim}") + def main(): while True: - os.system('clear') + os.system('clear') # clear the screen (or 'cls' for Windows) selected = main_menu() + if selected == "5": display_message("Exiting the Password Manager App. Goodbye!") break + if selected in "1234": os.system('clear') aim = input("Enter aim: ") + if selected == "1": create_password(aim) elif selected == "2": - password = check_password(aim) - if password: - display_message(f"Password is: {password}") + hashed_password = check_password(aim) + if hashed_password: + display_message(f"Password found for '{aim}'. (hashed)", Fore.CYAN) # Note: show hashed password elif selected == "3": edit_password(aim) elif selected == "4": @@ -135,5 +159,6 @@ def main(): else: display_message("Invalid option. Please select a valid option (1-5).", Fore.RED) + if __name__ == "__main__": main() diff --git a/Stock-Analysis/app.py b/Stock-Analysis/app.py index 3418893..7ea3016 100644 --- a/Stock-Analysis/app.py +++ b/Stock-Analysis/app.py @@ -1,27 +1,25 @@ -from multiprocessing import Pool +import os import logging +from multiprocessing import Pool from load_stocks import StockLoader from fetch_stocks import StockFetcher from data_processor import DataProcessor from plot_stocks import StockPlotter -class Main: +class Main: def __init__(self): - # Assign Log message + """Initialize the Main class with the necessary components and configure logging.""" + # Create a logger instance self.logger = logging.getLogger(__name__) - # Create handler - stream_handler = logging.StreamHandler() # Create a stream handler to output logs to console - stream_handler.setLevel(logging.INFO) # Set the log level to INFO - - # Assign handler - stream_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s') # Define the format for log messages - stream_handler.setFormatter(stream_format) # Assign the format to the stream handler + # Set up logging configuration + logging.basicConfig( + level=logging.INFO, # Set the logging level to INFO + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', # Define the log format + handlers=[logging.StreamHandler()] # Log to console + ) - # Add handler - self.logger.addHandler(stream_handler) # Add the stream handler to the logger - # Initialize instances of other classes self.stock_loader = StockLoader() self.stock_fetcher = StockFetcher() @@ -30,36 +28,48 @@ def __init__(self): def main(self): """Main function to orchestrate the execution flow.""" - logging.basicConfig( - filename='myapp.log', - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - level=logging.INFO - ) - self.logger.info('Session started') # Log that the session has started + self.logger.info('Session started') # Log the start of the session + + # Get the input filename and handle paths filename = input("Enter the filename containing the list of stocks: ") path = "/workspaces/Python_Project/Stock-Analysis/data/" - filename = path + filename - + filename = os.path.join(path, filename) + + # Ensure the file has a '.csv' extension if not filename.endswith('.csv'): filename += '.csv' - + + # Ask the user if they want to sort the data sort_data = input("Sort data? (yes/no): ").lower() == 'yes' + + # Initialize a list to store successful stock symbols successful_symbols = [] + # Load and process stock data try: + if not os.path.exists(filename): + raise FileNotFoundError(f"The file {filename} does not exist.") + + # Load stock symbols from the file stocks = self.stock_loader.load_stocks(filename) - # Use multiprocessing to fetch data for multiple stocks concurrently + + # Use multiprocessing to fetch stock data concurrently with Pool() as pool: data = pool.map(self.stock_fetcher.fetch_stock_data, stocks) + + # Process the fetched data and filter out unsuccessful fetches for stock_info in data: if stock_info is not None and stock_info[0] is not None: successful_symbols.append(stock_info[1]) + + # Display the data and plot df = self.data_processor.display_data(data, sort=sort_data) self.stock_plotter.plot_data(df, save_figure=True, figure_filename="stock_ratings.png") except Exception as e: - self.logger.error(f"An error occurred: {e}", exc_info=True) # Log error if an exception occurs + self.logger.error(f"An error occurred: {e}", exc_info=True) finally: + # Optionally save successful symbols save_successful = input("Do you want to save successful symbols? (yes/no): ").lower() == 'yes' if successful_symbols and save_successful: output_filename = input("Enter the filename to save successful symbols: ") @@ -67,9 +77,11 @@ def main(self): output_filename += '.csv' self.data_processor.save_successful_symbols(output_filename, successful_symbols) - self.logger.info('Session stopped') # Log that the session has stopped + # Log the end of the session + self.logger.info('Session stopped') # Log the stop of the session -if __name__ == '__main__': # If the script is being run directly, call the main function - app = Main() # Create an instance of the class - app.main() # Call the main function to start the script +# If the script is being run directly, instantiate and call the main function +if __name__ == '__main__': + app = Main() # Create an instance of the Main class + app.main() # Start the execution diff --git a/Stock-Analysis/bist_scrape_symbols.py b/Stock-Analysis/bist_scrape_symbols.py index 4145202..bc1c9db 100644 --- a/Stock-Analysis/bist_scrape_symbols.py +++ b/Stock-Analysis/bist_scrape_symbols.py @@ -1,12 +1,27 @@ import csv import requests from bs4 import BeautifulSoup +import logging + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') # Define the URL of the webpage to scrape url = "https://www.kap.org.tr/tr/bist-sirketler" +# Set up the headers to mimic a real browser request +headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' +} + # Send a GET request to the URL and get the response -response = requests.get(url) +try: + response = requests.get(url, headers=headers) + response.raise_for_status() # Raise an exception if the request was unsuccessful (status code 4xx or 5xx) + logging.info("Successfully fetched the webpage.") +except requests.exceptions.RequestException as e: + logging.error(f"Failed to fetch webpage: {e}") + exit(1) # Exit the program if the request fails # Parse the HTML content of the response using BeautifulSoup soup = BeautifulSoup(response.text, "html.parser") @@ -15,21 +30,28 @@ links = soup.find_all('a', class_='vcell') # Open a CSV file in write mode to store the extracted data -with open('symbols.csv', 'w', newline='', encoding='utf-8') as csvfile: - # Create a CSV writer object - csvwriter = csv.writer(csvfile) - - # Write the header row - csvwriter.writerow(['Symbol']) - - # Iterate through each link found on the webpage - for link in links: - # Extract the text from the link and remove any leading/trailing whitespace - text = link.get_text(strip=True) +csv_filename = 'symbols.csv' +try: + with open(csv_filename, 'w', newline='', encoding='utf-8') as csvfile: + # Create a CSV writer object + csvwriter = csv.writer(csvfile) + + # Write the header row + csvwriter.writerow(['Symbol']) - # Check if the extracted text contains unwanted phrases - if "PwC BAĞIMSIZ DENETİM VE SERBEST MUHASEBECİ MALİ MÜŞAVİRLİK A.Ş" not in text and "A.Ş." not in text: - # Split the text by commas - for symbol in text.split(","): - # Append '.IS' to each symbol and write it to the CSV file - csvwriter.writerow([symbol.strip() + ".IS"]) + # Iterate through each link found on the webpage + for link in links: + # Extract the text from the link and remove any leading/trailing whitespace + text = link.get_text(strip=True) + + # Check if the extracted text contains unwanted phrases + if "PwC BAĞIMSIZ DENETİM VE SERBEST MUHASEBECİ MALİ MÜŞAVİRLİK A.Ş" not in text and "A.Ş." not in text: + # Split the text by commas + for symbol in text.split(","): + # Append '.IS' to each symbol and write it to the CSV file + cleaned_symbol = symbol.strip() + ".IS" + csvwriter.writerow([cleaned_symbol]) + logging.info(f"Symbol '{cleaned_symbol}' written to CSV.") + logging.info(f"Symbols successfully saved to {csv_filename}.") +except Exception as e: + logging.error(f"An error occurred while writing to CSV: {e}") diff --git a/Stock-Analysis/data_processor.py b/Stock-Analysis/data_processor.py index 455d3ad..bcfb18a 100644 --- a/Stock-Analysis/data_processor.py +++ b/Stock-Analysis/data_processor.py @@ -3,23 +3,30 @@ import pandas as pd import logging +# Configure logging at the module level +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') + class DataProcessor: @staticmethod - def display_data(data, sort=False): + def display_data(data, sort=False, top_n=10): """Display stock data in tabular format. Args: data (list): List of stock data. sort (bool): Whether to sort the data by rating. + top_n (int): Number of rows to display. Default is 10. Returns: DataFrame: Pandas DataFrame containing stock data. """ df = pd.DataFrame(data, columns=['Rate', 'Symbol']) + if sort: - df = df.dropna().sort_values(by=['Rate']) - print(df.head()) + df = df.dropna().sort_values(by=['Rate'], ascending=False) + + # Display top_n rows, useful when data is large + print(df.head(top_n)) return df @staticmethod @@ -27,18 +34,24 @@ def save_successful_symbols(filename, successful_symbols): """Save successfully fetched stock symbols to a CSV file. Args: - - filename (str): Filename to save the symbols. - successful_symbols (list): List of successfully fetched stock symbols. + filename (str): Filename to save the symbols. + successful_symbols (list): List of successfully fetched stock symbols. """ try: - path = "/workspaces/Python_Project/Stock-Analysis/data/" + # Construct the full path for saving the file + path = os.path.join(os.getcwd(), "data") # Use current working directory + os.makedirs(path, exist_ok=True) # Ensure directory exists + + # Construct the new filename with CSV extension new_filename = os.path.splitext(filename)[0] + ".csv" - new_filename = path + new_filename - with open(new_filename, 'w') as file: + new_filename = os.path.join(path, new_filename) + + with open(new_filename, 'w', newline='', encoding='utf-8') as file: writer = csv.writer(file) + writer.writerow(['Symbol']) # Optional header for CSV file for symbol in successful_symbols: writer.writerow([symbol]) - logging.getLogger(__name__).info(f"Successful symbols saved to {new_filename}.") # Log that symbols have been saved + + logging.getLogger(__name__).info(f"Successful symbols saved to {new_filename}.") except Exception as e: - logging.getLogger(__name__).error(f"An error occurred while saving successful symbols to {new_filename}: {e}") # Log error if saving fails + logging.getLogger(__name__).error(f"An error occurred while saving successful symbols to {new_filename}: {e}") diff --git a/Stock-Analysis/fetch_stocks.py b/Stock-Analysis/fetch_stocks.py index 3111c36..f7a6218 100644 --- a/Stock-Analysis/fetch_stocks.py +++ b/Stock-Analysis/fetch_stocks.py @@ -2,6 +2,8 @@ import yfinance as yf import logging +# Configure logging at the module level +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') class StockFetcher: @@ -17,7 +19,22 @@ def fetch_stock_data(stock): """ try: ticker = yf.Ticker(stock) - return [ticker.info.get("recommendationMean"), ticker.info.get("symbol")] - except (KeyError, requests.exceptions.HTTPError): - logging.getLogger(__name__).error(f"Failed to load data for {stock}", exc_info=True) # Log error if data couldn't be fetched + info = ticker.info + + # Extract necessary data, ensuring they exist + recommendation_mean = info.get("recommendationMean") + symbol = info.get("symbol") + + # Check if the expected data is available + if recommendation_mean is None or symbol is None: + logging.error(f"Missing data for stock {stock}. Recommendation or symbol is None.") + return None + + return [recommendation_mean, symbol] + + except (requests.exceptions.RequestException, yfinance.YahooFinanceError) as e: + logging.error(f"Error fetching data for {stock}: {e}", exc_info=True) # Log specific error + return None + except Exception as e: + logging.error(f"Unexpected error fetching data for {stock}: {e}", exc_info=True) return None diff --git a/Stock-Analysis/load_stocks.py b/Stock-Analysis/load_stocks.py index e44d4bc..cf69c56 100644 --- a/Stock-Analysis/load_stocks.py +++ b/Stock-Analysis/load_stocks.py @@ -1,5 +1,9 @@ import csv import logging +import os + +# Set up logging for the module +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') class StockLoader: @@ -13,7 +17,17 @@ def load_stocks(filename): Returns: list: A list of stock symbols. """ - with open(filename, 'r') as file: - reader = csv.reader(file) - logging.getLogger(__name__).info('Files loaded') # Log that the file has been loaded - return [line[0] for line in reader] + if not os.path.isfile(filename): # Check if the file exists + logging.error(f"File {filename} does not exist.") + return [] # Return an empty list if the file does not exist + + try: + with open(filename, 'r') as file: + reader = csv.reader(file) + stock_symbols = [line[0] for line in reader if line] # Ensures non-empty lines are read + logging.info(f"Successfully loaded {len(stock_symbols)} stock symbols from {filename}.") + return stock_symbols + except Exception as e: + logging.error(f"Error reading the file {filename}: {e}") + return [] + diff --git a/Stock-Analysis/plot_stocks.py b/Stock-Analysis/plot_stocks.py index f1c3464..8199d72 100644 --- a/Stock-Analysis/plot_stocks.py +++ b/Stock-Analysis/plot_stocks.py @@ -1,31 +1,51 @@ import matplotlib.pyplot as plt import logging import datetime +import os + +# Set up logging for the module +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') class StockPlotter: @staticmethod - def plot_data(df, save_figure=False, figure_filename="plot.png", bar_width=0.6, font_size=3, dpi=700): - """Plot stock ratings. + def plot_data(df, save_figure=False, figure_filename=None, bar_width=0.6, font_size=12, dpi=700): + """Plot stock ratings in a bar plot. Args: - df (DataFrame): Pandas DataFrame containing stock data. - save_figure (bool): Whether to save the plot as an image file. - figure_filename (str): Filename to save the plot. - bar_width (float): Width of the bars in the bar plot. - font_size (int): Font size for plot labels. - dpi (int): Dots per inch for the saved image. + df (pd.DataFrame): Pandas DataFrame containing stock data. It must have columns ['Symbol', 'Rate']. + save_figure (bool): Whether to save the plot as an image file. Defaults to False. + figure_filename (str, optional): Filename to save the plot. If None, a default filename is generated. + bar_width (float): Width of the bars in the bar plot. Defaults to 0.6. + font_size (int): Font size for plot labels. Defaults to 12. + dpi (int): Dots per inch for the saved image. Defaults to 700. """ + # Ensure that the DataFrame contains the necessary columns + if 'Symbol' not in df or 'Rate' not in df: + logging.error("DataFrame must contain 'Symbol' and 'Rate' columns.") + return + + # Create the bar plot plt.bar(df['Symbol'], df['Rate'], color='skyblue', width=bar_width) plt.xlabel('Symbol', fontsize=font_size) plt.ylabel('Rate', fontsize=font_size) plt.title('Stock Ratings', fontsize=font_size) plt.xticks(rotation=45, ha='right', fontsize=font_size) plt.tight_layout() + + # Save the figure if required if save_figure: - current_time = datetime.datetime.now().strftime("%d-%m-%Y") - figure_filename = f"/workspaces/Python_Project/Stock-Analysis/results/plot_{current_time}.png" - plt.savefig(figure_filename, dpi=dpi) # Save the figure to a file with higher resolution - logging.getLogger(__name__).info(f"Figure saved as {figure_filename}.") # Log that the figure has been saved + if figure_filename is None: + current_time = datetime.datetime.now().strftime("%d-%m-%Y") + figure_filename = os.path.join("results", f"plot_{current_time}.png") + + # Ensure that the directory exists + os.makedirs(os.path.dirname(figure_filename), exist_ok=True) + + # Save the figure with the specified DPI + plt.savefig(figure_filename, dpi=dpi) + logging.info(f"Figure saved as {figure_filename}.") # Log that the figure has been saved else: - plt.show() \ No newline at end of file + # Display the plot if not saving it + plt.show() + diff --git a/tictactoe/runner.py b/tictactoe/runner.py index 375c058..c2678c2 100644 --- a/tictactoe/runner.py +++ b/tictactoe/runner.py @@ -1,146 +1,150 @@ import pygame import sys import time - import tictactoe as ttt +# Initialize Pygame pygame.init() -size = width, height = 600, 400 - -# Colors -black = (0, 0, 0) -white = (255, 255, 255) -screen = pygame.display.set_mode(size) +# Constants +WIDTH, HEIGHT = 600, 400 +TILE_SIZE = 80 +TILE_ORIGIN = (WIDTH / 2 - 1.5 * TILE_SIZE, HEIGHT / 2 - 1.5 * TILE_SIZE) +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) -mediumFont = pygame.font.Font("OpenSans-Regular.ttf", 28) -largeFont = pygame.font.Font("OpenSans-Regular.ttf", 40) -moveFont = pygame.font.Font("OpenSans-Regular.ttf", 60) +# Initialize the screen and fonts +screen = pygame.display.set_mode((WIDTH, HEIGHT)) +medium_font = pygame.font.Font("OpenSans-Regular.ttf", 28) +large_font = pygame.font.Font("OpenSans-Regular.ttf", 40) +move_font = pygame.font.Font("OpenSans-Regular.ttf", 60) +# Initialize game state user = None board = ttt.initial_state() ai_turn = False -while True: - - for event in pygame.event.get(): - if event.type == pygame.QUIT: - sys.exit() - - screen.fill(black) - - # Let user choose a player. - if user is None: - - # Draw title - title = largeFont.render("Play Tic-Tac-Toe", True, white) - titleRect = title.get_rect() - titleRect.center = ((width / 2), 50) - screen.blit(title, titleRect) - - # Draw buttons - playXButton = pygame.Rect((width / 8), (height / 2), width / 4, 50) - playX = mediumFont.render("Play as X", True, black) - playXRect = playX.get_rect() - playXRect.center = playXButton.center - pygame.draw.rect(screen, white, playXButton) - screen.blit(playX, playXRect) - - playOButton = pygame.Rect(5 * (width / 8), (height / 2), width / 4, 50) - playO = mediumFont.render("Play as O", True, black) - playORect = playO.get_rect() - playORect.center = playOButton.center - pygame.draw.rect(screen, white, playOButton) - screen.blit(playO, playORect) - - # Check if button is clicked - click, _, _ = pygame.mouse.get_pressed() - if click == 1: - mouse = pygame.mouse.get_pos() - if playXButton.collidepoint(mouse): - time.sleep(0.2) - user = ttt.X - elif playOButton.collidepoint(mouse): - time.sleep(0.2) - user = ttt.O - - else: - - # Draw game board - tile_size = 80 - tile_origin = (width / 2 - (1.5 * tile_size), - height / 2 - (1.5 * tile_size)) - tiles = [] - for i in range(3): - row = [] - for j in range(3): - rect = pygame.Rect( - tile_origin[0] + j * tile_size, - tile_origin[1] + i * tile_size, - tile_size, tile_size - ) - pygame.draw.rect(screen, white, rect, 3) - - if board[i][j] != ttt.EMPTY: - move = moveFont.render(board[i][j], True, white) - moveRect = move.get_rect() - moveRect.center = rect.center - screen.blit(move, moveRect) - row.append(rect) - tiles.append(row) - - game_over = ttt.terminal(board) - player = ttt.player(board) - - # Show title - if game_over: - winner = ttt.winner(board) - if winner is None: - title = f"Game Over: Tie." - else: - title = f"Game Over: {winner} wins." - elif user == player: - title = f"Play as {user}" - else: - title = f"Computer thinking..." - title = largeFont.render(title, True, white) - titleRect = title.get_rect() - titleRect.center = ((width / 2), 30) - screen.blit(title, titleRect) - - # Check for AI move - if user != player and not game_over: - if ai_turn: - time.sleep(0.5) - move = ttt.minimax(board) - board = ttt.result(board, move) - ai_turn = False - else: - ai_turn = True - - # Check for a user move - click, _, _ = pygame.mouse.get_pressed() - if click == 1 and user == player and not game_over: - mouse = pygame.mouse.get_pos() - for i in range(3): - for j in range(3): - if (board[i][j] == ttt.EMPTY and tiles[i][j].collidepoint(mouse)): - board = ttt.result(board, (i, j)) - - if game_over: - againButton = pygame.Rect(width / 3, height - 65, width / 3, 50) - again = mediumFont.render("Play Again", True, black) - againRect = again.get_rect() - againRect.center = againButton.center - pygame.draw.rect(screen, white, againButton) - screen.blit(again, againRect) +def draw_title(text, y_offset=30): + """Helper function to draw the title text on the screen.""" + title = large_font.render(text, True, WHITE) + title_rect = title.get_rect(center=(WIDTH / 2, y_offset)) + screen.blit(title, title_rect) + +def draw_buttons(): + """Draw the buttons for selecting player X or O.""" + play_x_button = pygame.Rect(WIDTH / 8, HEIGHT / 2, WIDTH / 4, 50) + play_o_button = pygame.Rect(5 * (WIDTH / 8), HEIGHT / 2, WIDTH / 4, 50) + + play_x_text = medium_font.render("Play as X", True, BLACK) + play_o_text = medium_font.render("Play as O", True, BLACK) + + pygame.draw.rect(screen, WHITE, play_x_button) + pygame.draw.rect(screen, WHITE, play_o_button) + screen.blit(play_x_text, play_x_text.get_rect(center=play_x_button.center)) + screen.blit(play_o_text, play_o_text.get_rect(center=play_o_button.center)) + + return play_x_button, play_o_button + +def draw_board(): + """Draw the Tic-Tac-Toe grid and the current game state.""" + tiles = [] + for i in range(3): + row = [] + for j in range(3): + rect = pygame.Rect(TILE_ORIGIN[0] + j * TILE_SIZE, TILE_ORIGIN[1] + i * TILE_SIZE, TILE_SIZE, TILE_SIZE) + pygame.draw.rect(screen, WHITE, rect, 3) + + if board[i][j] != ttt.EMPTY: + move = move_font.render(board[i][j], True, WHITE) + move_rect = move.get_rect(center=rect.center) + screen.blit(move, move_rect) + row.append(rect) + tiles.append(row) + return tiles + +def handle_game_over(): + """Draw the 'Play Again' button if the game is over.""" + again_button = pygame.Rect(WIDTH / 3, HEIGHT - 65, WIDTH / 3, 50) + again_text = medium_font.render("Play Again", True, BLACK) + pygame.draw.rect(screen, WHITE, again_button) + screen.blit(again_text, again_text.get_rect(center=again_button.center)) + + return again_button + +def main(): + global user, board, ai_turn + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + + screen.fill(BLACK) + + # Handle user selection of X or O + if user is None: + draw_title("Play Tic-Tac-Toe", y_offset=50) + play_x_button, play_o_button = draw_buttons() + click, _, _ = pygame.mouse.get_pressed() if click == 1: mouse = pygame.mouse.get_pos() - if againButton.collidepoint(mouse): + if play_x_button.collidepoint(mouse): + user = ttt.X + time.sleep(0.2) + elif play_o_button.collidepoint(mouse): + user = ttt.O time.sleep(0.2) - user = None - board = ttt.initial_state() + + else: + # Draw the game board and handle game states + tiles = draw_board() + game_over = ttt.terminal(board) + current_player = ttt.player(board) + + if game_over: + winner = ttt.winner(board) + title = f"Game Over: Tie." if winner is None else f"Game Over: {winner} wins." + elif user == current_player: + title = f"Play as {user}" + else: + title = "Computer thinking..." + + draw_title(title) + + # Handle AI turn if it is AI's turn + if user != current_player and not game_over: + if ai_turn: + time.sleep(0.5) + move = ttt.minimax(board) + board = ttt.result(board, move) ai_turn = False + else: + ai_turn = True - pygame.display.flip() + # Handle user input for their move + click, _, _ = pygame.mouse.get_pressed() + if click == 1 and user == current_player and not game_over: + mouse = pygame.mouse.get_pos() + for i in range(3): + for j in range(3): + if board[i][j] == ttt.EMPTY and tiles[i][j].collidepoint(mouse): + board = ttt.result(board, (i, j)) + + # If the game is over, offer to play again + if game_over: + again_button = handle_game_over() + click, _, _ = pygame.mouse.get_pressed() + if click == 1: + mouse = pygame.mouse.get_pos() + if again_button.collidepoint(mouse): + time.sleep(0.2) + user = None + board = ttt.initial_state() + ai_turn = False + + pygame.display.flip() + +if __name__ == "__main__": + main()