chore(school): a level dump again
This commit is contained in:
parent
268b752fef
commit
c157b419b1
23 changed files with 1225 additions and 14 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -21,5 +21,7 @@ _deps
|
||||||
bin
|
bin
|
||||||
ignored
|
ignored
|
||||||
|
|
||||||
maths/**/*.pdf
|
*.docx
|
||||||
maths/**/*.synctex.gz
|
*.pptx
|
||||||
|
*.doc
|
||||||
|
*.pdf
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
from tkinter import *
|
||||||
|
|
||||||
|
def addCat(event):
|
||||||
|
global cat
|
||||||
|
cat = cat + 1
|
||||||
|
updateDisplay()
|
||||||
|
|
||||||
|
def addDog(event):
|
||||||
|
global dog
|
||||||
|
dog += 1
|
||||||
|
updateDisplay()
|
||||||
|
|
||||||
|
def resetCat(event, update = True):
|
||||||
|
global cat
|
||||||
|
cat = 0
|
||||||
|
|
||||||
|
if update: updateDisplay()
|
||||||
|
|
||||||
|
def resetDog(event, update = True):
|
||||||
|
global dog
|
||||||
|
dog = 0
|
||||||
|
|
||||||
|
if update: updateDisplay()
|
||||||
|
|
||||||
|
def reset(event):
|
||||||
|
resetCat(False)
|
||||||
|
resetDog(False)
|
||||||
|
|
||||||
|
updateDisplay()
|
||||||
|
|
||||||
|
def updateDisplay():
|
||||||
|
global cat, dog
|
||||||
|
|
||||||
|
cats = f'{cat} ' + ('cat' if cat == 1 else 'cats')
|
||||||
|
dogs = f'{dog} ' + ('dog' if dog == 1 else 'dogs')
|
||||||
|
isAre = 'is' if cat == 1 else 'are'
|
||||||
|
|
||||||
|
outputLabel.configure(text = f'There {isAre} {cats}, and {dogs}.')
|
||||||
|
|
||||||
|
cat = 0
|
||||||
|
dog = 0
|
||||||
|
|
||||||
|
window = Tk("Cat or Dog")
|
||||||
|
|
||||||
|
topFrame = Frame(window)
|
||||||
|
topFrame.pack()
|
||||||
|
|
||||||
|
bottomFrame = Frame(window)
|
||||||
|
bottomFrame.pack(side = BOTTOM, pady = 10)
|
||||||
|
|
||||||
|
welcome = Label(topFrame, fg="red", font=("Helvetica", 16), text = "Welcome to Cat or Dog Selector")
|
||||||
|
welcome.pack()
|
||||||
|
|
||||||
|
outputLabel = Label(topFrame, text = "0")
|
||||||
|
outputLabel.pack()
|
||||||
|
|
||||||
|
catButton = Button(bottomFrame, text='Cat')
|
||||||
|
catButton.bind("<1>", addCat)
|
||||||
|
catButton.bind("<3>", resetCat)
|
||||||
|
catButton.grid(row = 0, column = 0, padx = 10)
|
||||||
|
|
||||||
|
dogButton = Button(bottomFrame, text='Dog')
|
||||||
|
dogButton.bind("<1>", addDog)
|
||||||
|
dogButton.bind("<3>", resetDog)
|
||||||
|
dogButton.grid(row = 0, column = 2, padx = 20)
|
||||||
|
|
||||||
|
resetButton = Button(bottomFrame, text='Reset', bg='#000000', fg='#ffffff')
|
||||||
|
resetButton.bind("<1>", reset)
|
||||||
|
resetButton.grid(row = 0, column = 3)
|
||||||
|
|
||||||
|
updateDisplay()
|
||||||
|
|
||||||
|
window.mainloop()
|
81
school/a-level/Y12 2022-2024/GUI Programming/GUI Dice.py
Normal file
81
school/a-level/Y12 2022-2024/GUI Programming/GUI Dice.py
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter.font import Font, BOLD
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
class Window(tk.Tk):
|
||||||
|
def __init__(self):
|
||||||
|
tk.Tk.__init__(self)
|
||||||
|
|
||||||
|
self.sides = 6
|
||||||
|
self.sum = 0
|
||||||
|
self.geometry('500x500')
|
||||||
|
self.updateTitle()
|
||||||
|
|
||||||
|
self.grid_rowconfigure(0, weight = 1)
|
||||||
|
self.grid_columnconfigure(0, weight = 1)
|
||||||
|
self.option_add('*font', Font(self, size = 12))
|
||||||
|
self.tk_setPalette(background = 'white')
|
||||||
|
|
||||||
|
container = tk.Frame()
|
||||||
|
container.grid(row = 0, column = 0, sticky = '')
|
||||||
|
|
||||||
|
sideController = tk.Frame(master=container)
|
||||||
|
sideController.grid(row = 3, column = 0)
|
||||||
|
|
||||||
|
self.outputLabel = tk.Label(container, font=Font(self, size = 25, weight = BOLD))
|
||||||
|
self.sumLabel = tk.Label(container, font=Font(self, size = 20))
|
||||||
|
self.sidesLabel = tk.Label(sideController)
|
||||||
|
|
||||||
|
rollButton = tk.Button(container, text='Roll!')
|
||||||
|
decrementSides = tk.Button(sideController, text = '←', borderwidth = 0)
|
||||||
|
incrementSides = tk.Button(sideController, text = '→', borderwidth = 0)
|
||||||
|
|
||||||
|
self.outputLabel.grid(row = 0, column = 0, pady=(0, 20))
|
||||||
|
self.updateOutput()
|
||||||
|
|
||||||
|
self.sumLabel.grid(row = 1, column = 0, pady=(0, 50))
|
||||||
|
self.updateSum()
|
||||||
|
|
||||||
|
rollButton.bind("<1>", self.roll)
|
||||||
|
rollButton.grid(row = 2, column = 0, pady=(0, 30))
|
||||||
|
|
||||||
|
decrementSides.bind("<1>", self.decrementSides)
|
||||||
|
decrementSides.grid(row = 0, column = 0)
|
||||||
|
|
||||||
|
self.sidesLabel.grid(row = 0, column = 1)
|
||||||
|
self.updateSides()
|
||||||
|
|
||||||
|
incrementSides.bind("<1>", self.incrementSides)
|
||||||
|
incrementSides.grid(row = 0, column = 2)
|
||||||
|
|
||||||
|
def updateOutput(self, roll = 'N/A'):
|
||||||
|
self.outputLabel.configure(text = roll)
|
||||||
|
|
||||||
|
def updateSum(self):
|
||||||
|
self.sumLabel.configure(text = f'Sum: {self.sum}')
|
||||||
|
|
||||||
|
def roll(self, _):
|
||||||
|
number = randint(1, self.sides)
|
||||||
|
self.updateOutput(number)
|
||||||
|
|
||||||
|
def updateTitle(self):
|
||||||
|
self.wm_title(f'{self.sides}-sided Dice')
|
||||||
|
|
||||||
|
def updateSides(self):
|
||||||
|
self.sidesLabel.configure(text = self.sides)
|
||||||
|
self.updateTitle()
|
||||||
|
|
||||||
|
def decrementSides(self, _):
|
||||||
|
self.sides -= 1
|
||||||
|
|
||||||
|
if self.sides < 2:
|
||||||
|
self.sides = 2
|
||||||
|
|
||||||
|
self.updateSides()
|
||||||
|
|
||||||
|
def incrementSides(self, _):
|
||||||
|
self.sides += 1
|
||||||
|
|
||||||
|
self.updateSides()
|
||||||
|
|
||||||
|
Window().mainloop()
|
|
@ -1,5 +1,6 @@
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
# :eyes:
|
||||||
def clearTerminal():
|
def clearTerminal():
|
||||||
print('\n' * 25)
|
print('\n' * 25)
|
||||||
|
|
||||||
|
@ -26,25 +27,27 @@ def findPrimes(upperBound: int):
|
||||||
|
|
||||||
return primes
|
return primes
|
||||||
|
|
||||||
possiblePrimes = findPrimes(1_000_000)
|
POSSIBLE_PRIMES = findPrimes(1_000_000) # Would be better to hardcode this list as it is constant, however I want good marks and to show complex algorithms I guess!!!
|
||||||
inputtedPrimes = []
|
inputtedPrimes = []
|
||||||
|
|
||||||
def askForPrime():
|
def getPrime(primeList):
|
||||||
global possiblePrimes, inputtedPrimes
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
value = int(input("Please enter a prime number to add to the list: "))
|
value = int(input("Please enter a prime number to add to the list: "))
|
||||||
|
|
||||||
|
# Ensure that the value fits the requirements set out by the brief
|
||||||
if value > 999_999 or value < 0:
|
if value > 999_999 or value < 0:
|
||||||
raise ValueError('Please ensure you enter an integer at most 6 digits long!')
|
raise ValueError('Please ensure you enter an integer at most 6 digits long!')
|
||||||
elif value not in possiblePrimes:
|
elif value not in POSSIBLE_PRIMES:
|
||||||
raise ValueError('That is not a prime number! Please try again.')
|
raise ValueError('That is not a prime number! Please try again.')
|
||||||
elif value in inputtedPrimes:
|
elif value in primeList:
|
||||||
raise ValueError('You have already inputted that prime number! Please enter a different one.')
|
raise ValueError('You have already inputted that prime number! Please enter a different one.')
|
||||||
|
|
||||||
return inputtedPrimes.append(value)
|
# Mutate the prime list and return it back to the caller
|
||||||
|
primeList.append(value)
|
||||||
|
return primeList
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
|
# Check to see if the error was raised by Python or manually, and print messages accordingly
|
||||||
if e.args[0].startswith("invalid literal"):
|
if e.args[0].startswith("invalid literal"):
|
||||||
print('Please enter a valid integer!')
|
print('Please enter a valid integer!')
|
||||||
else:
|
else:
|
||||||
|
@ -69,14 +72,19 @@ What would you like to do?
|
||||||
|
|
||||||
break
|
break
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Please enter a valid integer that is at most six digits long.")
|
print("Please enter a valid option from the list (1-3)")
|
||||||
|
|
||||||
clearTerminal()
|
clearTerminal()
|
||||||
|
|
||||||
if choice == 1:
|
if choice == 1:
|
||||||
askForPrime()
|
inputtedPrimes = getPrime(inputtedPrimes)
|
||||||
elif choice == 2:
|
elif choice == 2:
|
||||||
print(', '.join(map(lambda x: str(x), inputtedPrimes)))
|
# Only print the list if there is values inside to print
|
||||||
|
if len(inputtedPrimes) > 0:
|
||||||
|
print(', '.join(map(lambda x: str(x), inputtedPrimes)))
|
||||||
|
else:
|
||||||
|
print('There is currently nothing in the list!')
|
||||||
|
|
||||||
sleep(2.5)
|
sleep(2.5)
|
||||||
elif choice == 3:
|
elif choice == 3:
|
||||||
exit()
|
exit()
|
|
@ -0,0 +1,18 @@
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from primeList import findPrimes
|
||||||
|
|
||||||
|
# My code can not be unit tested much with how I have structured it but here's proof I know how to do it I guess :D
|
||||||
|
|
||||||
|
class SieveTest(unittest.TestCase):
|
||||||
|
def test_sieve(self):
|
||||||
|
"""
|
||||||
|
Test that the sieve correctly generates a list of primes up until 100.
|
||||||
|
"""
|
||||||
|
primes = findPrimes(100)
|
||||||
|
self.assertEqual(primes, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.argv.append('-v')
|
||||||
|
unittest.main()
|
|
@ -0,0 +1,190 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
from random import uniform
|
||||||
|
from typing import List, Iterable, Callable, Union
|
||||||
|
from functools import reduce
|
||||||
|
from operator import iconcat
|
||||||
|
|
||||||
|
class OperationError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MatrixRow:
|
||||||
|
def __init__(self, length: int):
|
||||||
|
self.__values: List[float] = [0 for _ in range(length)]
|
||||||
|
self.__length = length
|
||||||
|
|
||||||
|
def __getitem__(self, column: int):
|
||||||
|
"""Index the row."""
|
||||||
|
if column <= 0 or column > self.__length:
|
||||||
|
raise IndexError("Out of bounds")
|
||||||
|
|
||||||
|
return self.__values[column - 1]
|
||||||
|
|
||||||
|
def __setitem__(self, column: int, newValue: float):
|
||||||
|
"""Update a value in the row at a given column."""
|
||||||
|
if column <= 0 or column > self.__length:
|
||||||
|
raise IndexError("Out of bounds")
|
||||||
|
|
||||||
|
self.__values[column - 1] = newValue
|
||||||
|
|
||||||
|
def __iter__(self) -> Iterable:
|
||||||
|
processedValues = []
|
||||||
|
|
||||||
|
for value in self.__values:
|
||||||
|
if type(value) == float and value.is_integer():
|
||||||
|
processedValues.append(int(value))
|
||||||
|
else:
|
||||||
|
processedValues.append(value)
|
||||||
|
|
||||||
|
return iter(processedValues)
|
||||||
|
|
||||||
|
|
||||||
|
class SquareMatrix:
|
||||||
|
def __init__(self, n: int):
|
||||||
|
self.__rows: List[MatrixRow] = [MatrixRow(n) for _ in range(n)]
|
||||||
|
self.__n = n
|
||||||
|
self.__rowFormatting = "{:^10}| " * n
|
||||||
|
self.__divider = "-" * (n * 12)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def From(rows: List[List[float]]) -> SquareMatrix:
|
||||||
|
n = len(rows)
|
||||||
|
|
||||||
|
if len(set([len(row) for row in rows])) != 1 or len(rows[0]) != n:
|
||||||
|
raise ValueError("Rows do not form a valid square matrix.")
|
||||||
|
|
||||||
|
matrix = SquareMatrix(n)
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
for j in range(n):
|
||||||
|
matrix[i + 1][j + 1] = rows[i][j]
|
||||||
|
|
||||||
|
return matrix
|
||||||
|
|
||||||
|
def size(self) -> int:
|
||||||
|
"""Returns the size of the square matrix."""
|
||||||
|
return self.__n
|
||||||
|
|
||||||
|
def populate(self, minimum: float, maximum: float) -> SquareMatrix:
|
||||||
|
"""Populates the matrix with random values."""
|
||||||
|
if minimum > maximum:
|
||||||
|
raise ValueError('Minimum value must be less than maximum value!')
|
||||||
|
|
||||||
|
for i in range(1, self.__n + 1):
|
||||||
|
for j in range(1, self.__n + 1):
|
||||||
|
self[i][j] = uniform(minimum, maximum)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def sumCorners(self) -> float:
|
||||||
|
"""Computes the sum of the corners of the matrix."""
|
||||||
|
return self[1][1] + self[1][self.__n] + self[self.__n][1] + self[self.__n][self.__n]
|
||||||
|
|
||||||
|
def values(self) -> float:
|
||||||
|
"""Return a list of all of the values in a matrix."""
|
||||||
|
return reduce(iconcat, self.__rows, [])
|
||||||
|
|
||||||
|
def averageValue(self) -> float:
|
||||||
|
"""Computes the avaerage value in the matrix."""
|
||||||
|
return sum(self.values()) / (self.__n ** 2)
|
||||||
|
|
||||||
|
def diagonalSum(self, left: bool = True) -> float:
|
||||||
|
"""Computes a diagonal sum of the matrix."""
|
||||||
|
sum = 0
|
||||||
|
|
||||||
|
for i, row in enumerate(self.__rows):
|
||||||
|
if left:
|
||||||
|
sum += row[i + 1]
|
||||||
|
else:
|
||||||
|
sum += row[self.__n - i]
|
||||||
|
|
||||||
|
return sum
|
||||||
|
|
||||||
|
def diagonalDifference(self) -> float:
|
||||||
|
"""Computes the diagonal difference of the matrix."""
|
||||||
|
left = self.diagonalSum()
|
||||||
|
right = self.diagonalSum(False)
|
||||||
|
|
||||||
|
return abs(right - left)
|
||||||
|
|
||||||
|
def transpose(self) -> SquareMatrix:
|
||||||
|
"""Transpose the matrix."""
|
||||||
|
transposed = list(zip(*self.__rows))
|
||||||
|
|
||||||
|
for i in range(self.__n):
|
||||||
|
for j in range(self.__n):
|
||||||
|
self[i + 1][j + 1] = transposed[i][j]
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
"""Represents the matrix in a string."""
|
||||||
|
out = self.__divider
|
||||||
|
|
||||||
|
for row in self.__rows:
|
||||||
|
out += f"\n|{self.__rowFormatting.format(*row)}\n{self.__divider}"
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def __getitem__(self, row: int):
|
||||||
|
"""Allows indexing of the matrix"""
|
||||||
|
if row - 1 > self.__n:
|
||||||
|
raise IndexError("Out of bounds")
|
||||||
|
|
||||||
|
return self.__rows[row - 1]
|
||||||
|
|
||||||
|
def __applyToMatrices(self, matrix: SquareMatrix, method: Callable[[float, float], float]) -> SquareMatrix:
|
||||||
|
"""Returns a new matrix containing the results of a method applied to the corresponding values of this matrix, and another one."""
|
||||||
|
if matrix.size() != self.__n:
|
||||||
|
raise OperationError("Matrix sizes are incompatible")
|
||||||
|
|
||||||
|
newMatrix = SquareMatrix(self.__n)
|
||||||
|
|
||||||
|
for i in range(1, self.__n + 1):
|
||||||
|
for j in range(1, self.__n + 1):
|
||||||
|
newMatrix[i][j] = method(self[i][j], matrix[i][j])
|
||||||
|
|
||||||
|
return newMatrix
|
||||||
|
|
||||||
|
def __applyToSelf(self, method: Callable[[float], float]) -> SquareMatrix:
|
||||||
|
"""Returns a new matrix containing the results of a method applies to the value of this matrix."""
|
||||||
|
newMatrix = SquareMatrix(self.__n)
|
||||||
|
|
||||||
|
for i in range(1, self.__n + 1):
|
||||||
|
for j in range(1, self.__n + 1):
|
||||||
|
newMatrix[i][j] = method(self[i][j])
|
||||||
|
|
||||||
|
return newMatrix
|
||||||
|
|
||||||
|
def __add__(self, value: Union[SquareMatrix, float]) -> SquareMatrix:
|
||||||
|
"""Add two matrices."""
|
||||||
|
if isinstance(value, SquareMatrix):
|
||||||
|
return self.__applyToMatrices(value, lambda x, y: x + y)
|
||||||
|
else:
|
||||||
|
return self.__applyToSelf(lambda x: x + value)
|
||||||
|
|
||||||
|
def __sub__(self, value: Union[SquareMatrix, float]) -> SquareMatrix:
|
||||||
|
"""Subtract two matrices."""
|
||||||
|
if isinstance(value, SquareMatrix):
|
||||||
|
return self.__applyToMatrices(value, lambda x, y: x - y)
|
||||||
|
else:
|
||||||
|
return self.__applyToSelf(lambda x: x - value)
|
||||||
|
|
||||||
|
def __mul__(self, scalar: float) -> SquareMatrix:
|
||||||
|
"""Multiply the matrix by a scalar."""
|
||||||
|
return self.__applyToSelf(lambda x: x * scalar)
|
||||||
|
|
||||||
|
def __floordiv__(self, scalar: float) -> SquareMatrix:
|
||||||
|
"""Floor divide the matrix by a scalar."""
|
||||||
|
return self.__applyToSelf(lambda x: x // scalar)
|
||||||
|
|
||||||
|
def __mod__(self, scalar: float) -> SquareMatrix:
|
||||||
|
"""Modulo the matrix by a scalar."""
|
||||||
|
return self.__applyToSelf(lambda x: x % scalar)
|
||||||
|
|
||||||
|
def __pow__(self, scalar: float) -> SquareMatrix:
|
||||||
|
"""Power the matrix by a scalar."""
|
||||||
|
return self.__applyToSelf(lambda x: x ** scalar)
|
||||||
|
|
||||||
|
a = SquareMatrix.From([[12.4,3,15],[4,7,8],[5,6,2]])
|
||||||
|
|
||||||
|
print(a)
|
|
@ -0,0 +1,79 @@
|
||||||
|
from typing import List, Callable
|
||||||
|
from random import randint
|
||||||
|
from functools import reduce
|
||||||
|
from operator import iconcat
|
||||||
|
|
||||||
|
def getInteger(prompt: str, err: str, validation: Callable[[int], bool] = None) -> int:
|
||||||
|
"""Fetch an integer from the user and validate it if necessary."""
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
value = int(input(prompt))
|
||||||
|
|
||||||
|
if validation and validation(value):
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
return value
|
||||||
|
except ValueError:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
def generateMatrix(n: int, min: int, max: int) -> List[List[int]]:
|
||||||
|
"""Generates an nxn square matrix and populates it with random integer values between two bounds."""
|
||||||
|
if min > max:
|
||||||
|
raise ValueError('Minimum value must be less than maximum value!')
|
||||||
|
|
||||||
|
return [[randint(min, max) for _ in range(n)] for _ in range(n)]
|
||||||
|
|
||||||
|
def printMatrix(matrix: List[List[int]]):
|
||||||
|
n = len(matrix)
|
||||||
|
rowFormatting = "{:^7}| " * n
|
||||||
|
divider = '-' * (n * 9 - 1)
|
||||||
|
|
||||||
|
print(divider)
|
||||||
|
|
||||||
|
for row in matrix:
|
||||||
|
print(rowFormatting.format(*row))
|
||||||
|
print(divider)
|
||||||
|
|
||||||
|
def diagonalSum(matrix: List[List[int]], left: bool = True) -> int:
|
||||||
|
"""Computes the diagonal sum of an nxn square matrix."""
|
||||||
|
sum = 0
|
||||||
|
n = len(matrix)
|
||||||
|
|
||||||
|
for i, row in enumerate(matrix):
|
||||||
|
if left:
|
||||||
|
sum += row[i]
|
||||||
|
else:
|
||||||
|
sum += row[n - i - 1]
|
||||||
|
|
||||||
|
return sum
|
||||||
|
|
||||||
|
def diagonalDifference(matrix: List[List[int]]) -> int:
|
||||||
|
"""Computes the diagonal difference of an nxn square matrix."""
|
||||||
|
left = diagonalSum(matrix)
|
||||||
|
right = diagonalSum(matrix, False)
|
||||||
|
|
||||||
|
return abs(right - left)
|
||||||
|
|
||||||
|
def sumOfCorners(matrix: List[List[int]]) -> int:
|
||||||
|
"""Computes the sum of the corners of an nxn square matrix."""
|
||||||
|
n = len(matrix)
|
||||||
|
|
||||||
|
return matrix[0][0] + matrix[0][n - 1] + matrix[n - 1][0] + matrix[n - 1][n - 1]
|
||||||
|
|
||||||
|
def averageValue(matrix: List[List[int]]) -> int:
|
||||||
|
"""Computes the average value in an nxn square matrix."""
|
||||||
|
values = reduce(iconcat, matrix, [])
|
||||||
|
|
||||||
|
return sum(values) / (len(matrix) ** 2)
|
||||||
|
|
||||||
|
n = getInteger('Please enter the dimension of the square matrix: ', 'Please enter a natural number greater than 1.', lambda x: x <= 1)
|
||||||
|
matrix = generateMatrix(n, 1, 100)
|
||||||
|
# matrix = [[12,3,15],[4,7,8],[5,6,2]]
|
||||||
|
difference = diagonalDifference(matrix)
|
||||||
|
corners = sumOfCorners(matrix)
|
||||||
|
average = averageValue(matrix)
|
||||||
|
|
||||||
|
printMatrix(matrix)
|
||||||
|
print(f"""Diagonal difference: {difference}
|
||||||
|
Sum of the corners: {corners}
|
||||||
|
Average value: {average}""")
|
|
@ -0,0 +1,16 @@
|
||||||
|
def intInput(name):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
number = int(input(f'Please enter an integer for {name}: '))
|
||||||
|
return number
|
||||||
|
except ValueError:
|
||||||
|
print('Please enter a valid integer.')
|
||||||
|
|
||||||
|
A = intInput('A')
|
||||||
|
B = intInput('B')
|
||||||
|
C = intInput('C')
|
||||||
|
|
||||||
|
if (A < B) or (B < C):
|
||||||
|
A = B
|
||||||
|
|
||||||
|
print(A)
|
89
school/a-level/Y12 2022-2024/Logic/Custom Expressions.py
Normal file
89
school/a-level/Y12 2022-2024/Logic/Custom Expressions.py
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Tuple, List
|
||||||
|
|
||||||
|
class Gate(Enum):
|
||||||
|
AND = '^'
|
||||||
|
OR = '∨'
|
||||||
|
XOR = '⊕'
|
||||||
|
NAND = '↑'
|
||||||
|
NOR = '↓'
|
||||||
|
XNOR = '⊙'
|
||||||
|
|
||||||
|
class Symbol:
|
||||||
|
def __init__(self, character):
|
||||||
|
self.char = character
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.char
|
||||||
|
|
||||||
|
class Expression:
|
||||||
|
def __init__(self, symbol):
|
||||||
|
self.tree: List[Tuple[Gate, Expression]] = []
|
||||||
|
self.initialSymbol = symbol
|
||||||
|
|
||||||
|
def AND(self, symbol):
|
||||||
|
self.tree.append((Gate.AND, symbol))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def OR(self, symbol):
|
||||||
|
self.tree.append((Gate.OR, symbol))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def XOR(self, symbol):
|
||||||
|
self.tree.append((Gate.XOR, symbol))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def NAND(self, symbol):
|
||||||
|
self.tree.append((Gate.NAND, symbol))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def NOR(self, symbol):
|
||||||
|
self.tree.append((Gate.NOR, symbol))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def XNOR(self, symbol):
|
||||||
|
self.tree.append((Gate.XNOR, symbol))
|
||||||
|
return self
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def treeSymbols(tree):
|
||||||
|
symbols = set([])
|
||||||
|
|
||||||
|
for _, value in tree:
|
||||||
|
if isinstance(value, Expression):
|
||||||
|
if str(value.initialSymbol) not in symbols:
|
||||||
|
symbols.add(str(value.initialSymbol))
|
||||||
|
symbols.update(Expression.treeSymbols(value.tree))
|
||||||
|
elif str(value) not in symbols:
|
||||||
|
symbols.add(str(value))
|
||||||
|
|
||||||
|
return symbols
|
||||||
|
|
||||||
|
|
||||||
|
def compile(self):
|
||||||
|
# Count symbols
|
||||||
|
symbols = Expression.treeSymbols(self.tree)
|
||||||
|
|
||||||
|
def run(*values):
|
||||||
|
for gate, value in self._tree:
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
out = str(self.initialSymbol)
|
||||||
|
|
||||||
|
for gate, value in self.tree:
|
||||||
|
if isinstance(value, Expression) and len(value.tree) > 0:
|
||||||
|
expression = f'({value})'
|
||||||
|
else:
|
||||||
|
expression = str(value)
|
||||||
|
|
||||||
|
out += f' {gate.value} {expression}'
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
A = Symbol('A')
|
||||||
|
B = Symbol('B')
|
||||||
|
C = Symbol('C')
|
||||||
|
D = Symbol('D')
|
||||||
|
# A.AND(B).execute()
|
||||||
|
|
||||||
|
Expression(A).AND(Expression(B).AND(A)).OR(Expression(C).XOR(Expression(A).OR(D))).compile()
|
30
school/a-level/Y12 2022-2024/Logic/Framework.py
Normal file
30
school/a-level/Y12 2022-2024/Logic/Framework.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class Gate(Enum):
|
||||||
|
AND = '^'
|
||||||
|
OR = '∨'
|
||||||
|
XOR = '⊕'
|
||||||
|
NAND = '↑'
|
||||||
|
NOR = '↓'
|
||||||
|
XNOR = '⊙'
|
||||||
|
|
||||||
|
class Symbol():
|
||||||
|
def __init__(self, symbol, initialValue):
|
||||||
|
self._symbol = symbol
|
||||||
|
self._value = initialValue
|
||||||
|
self._tree = []
|
||||||
|
|
||||||
|
def setValue(self, newValue):
|
||||||
|
self._value = newValue
|
||||||
|
return self
|
||||||
|
|
||||||
|
def AND(self, symbol: Symbol):
|
||||||
|
self._tree.append((Gate.AND, symbol))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def compute():
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self._symbol
|
84
school/a-level/Y12 2022-2024/Logic/Full Adder.py
Normal file
84
school/a-level/Y12 2022-2024/Logic/Full Adder.py
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
def getInt():
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
value = int(input("Please enter a natural number: "))
|
||||||
|
|
||||||
|
return value
|
||||||
|
except ValueError:
|
||||||
|
print("Please enter a valid natural number.")
|
||||||
|
|
||||||
|
def getBin(x: int) -> List[int]:
|
||||||
|
return list(map(lambda x: int(x), bin(abs(x))[2:]))
|
||||||
|
|
||||||
|
def twosComplementToInt(bits: List[int]) -> int:
|
||||||
|
sum = 0 if bits[0] == 0 else -(2 ** (len(bits) - 1))
|
||||||
|
del bits[0]
|
||||||
|
bits.reverse()
|
||||||
|
|
||||||
|
for i in range(len(bits)):
|
||||||
|
if bits[i] == 1:
|
||||||
|
sum += 2 ** i
|
||||||
|
|
||||||
|
return sum
|
||||||
|
|
||||||
|
def add(x: int, y: int) -> int:
|
||||||
|
bits = max(len(bin(x)[2:]), len(bin(y)[2:])) + 1
|
||||||
|
mask = int("1" * bits, 2)
|
||||||
|
xBin = list(map(lambda x: int(x), ("0" if x >= 0 else "1") + bin(x & mask)[2:]))
|
||||||
|
yBin = list(map(lambda x: int(x), ("0" if y >= 0 else "1") + bin(y & mask)[2:]))
|
||||||
|
|
||||||
|
print(xBin, yBin)
|
||||||
|
|
||||||
|
# Pad the shortner binary number
|
||||||
|
while len(xBin) < bits:
|
||||||
|
xBin.insert(0, 0)
|
||||||
|
while len(yBin) < bits:
|
||||||
|
yBin.insert(0, 0)
|
||||||
|
|
||||||
|
# We add from right to left
|
||||||
|
xBin.reverse(); yBin.reverse()
|
||||||
|
|
||||||
|
# Iteratively apply the full adder
|
||||||
|
cout = 0
|
||||||
|
outBin = []
|
||||||
|
|
||||||
|
for a, b in zip(xBin, yBin):
|
||||||
|
sum = cout ^ (a ^ b)
|
||||||
|
cout = (a & b) | (cout & ((~a & b) | (a & ~b)))
|
||||||
|
outBin.append(sum)
|
||||||
|
|
||||||
|
if x > 0 and y > 0: outBin.append(cout)
|
||||||
|
|
||||||
|
# We read from left to right
|
||||||
|
outBin.reverse()
|
||||||
|
print(outBin)
|
||||||
|
|
||||||
|
return twosComplementToInt(outBin)
|
||||||
|
|
||||||
|
def subtract(x: int, y: int) -> int:
|
||||||
|
return add(x, -y)
|
||||||
|
|
||||||
|
def multiply(x: int, y: int) -> int:
|
||||||
|
if x == 1:
|
||||||
|
return y
|
||||||
|
elif x == -1:
|
||||||
|
return -y
|
||||||
|
elif y == 1:
|
||||||
|
return x
|
||||||
|
elif y == -1:
|
||||||
|
return -x
|
||||||
|
|
||||||
|
sgn = -1 if (x > 0 and y < 0) or (y > 0 and x < 0) else 1
|
||||||
|
product = 0
|
||||||
|
|
||||||
|
for num in [abs(x) for _ in range(abs(y))]:
|
||||||
|
product = add(product, num)
|
||||||
|
|
||||||
|
return multiply(sgn, product)
|
||||||
|
|
||||||
|
x, y = getInt(), getInt()
|
||||||
|
|
||||||
|
# Compare the results
|
||||||
|
print(x + y, add(x, y))
|
|
@ -0,0 +1,51 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Dict, List
|
||||||
|
|
||||||
|
class VariableMismatchError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Node:
|
||||||
|
"""Represents a row of a truth table"""
|
||||||
|
variables: Dict[str, bool]
|
||||||
|
value: bool
|
||||||
|
|
||||||
|
class KMap:
|
||||||
|
def __init__(self, variables: List[str]):
|
||||||
|
self.__nodes: List[Node] = []
|
||||||
|
self.__variables = variables
|
||||||
|
|
||||||
|
def addNode(self, node: Node):
|
||||||
|
variableCount = len(self.__variables)
|
||||||
|
nodeVariableCount = len(node.variables.keys())
|
||||||
|
|
||||||
|
if variableCount < nodeVariableCount:
|
||||||
|
raise VariableMismatchError(f"You tried assigning a node with {nodeVariableCount} variables to a K-Map that supports {variableCount} variables.")
|
||||||
|
|
||||||
|
for variable, _ in node.variables:
|
||||||
|
if variable not in self.__variables:
|
||||||
|
raise VariableMismatchError(f"{variable} is not a variable in this K-Map!")
|
||||||
|
|
||||||
|
self.__nodes.append(node)
|
||||||
|
return self
|
||||||
|
|
||||||
|
map = [
|
||||||
|
Node({
|
||||||
|
"A": False,
|
||||||
|
"B": False
|
||||||
|
}, True),
|
||||||
|
Node({
|
||||||
|
"A": True,
|
||||||
|
"B": False
|
||||||
|
}, True),
|
||||||
|
Node({
|
||||||
|
"A": False,
|
||||||
|
"B": True
|
||||||
|
}, False),
|
||||||
|
Node({
|
||||||
|
"A": True,
|
||||||
|
"B": True
|
||||||
|
}, True),
|
||||||
|
]
|
||||||
|
|
||||||
|
print(map)
|
Binary file not shown.
|
@ -82,10 +82,13 @@ print('-' * (len(header) - 15 - (8 * inputQuantity)))
|
||||||
# Find the cartesian product to generate pairs
|
# Find the cartesian product to generate pairs
|
||||||
# https://en.wikipedia.org/wiki/Cartesian_product
|
# https://en.wikipedia.org/wiki/Cartesian_product
|
||||||
sets = [(0, 1)] * inputQuantity
|
sets = [(0, 1)] * inputQuantity
|
||||||
|
print(sets)
|
||||||
pairs = [[]]
|
pairs = [[]]
|
||||||
|
|
||||||
for set in sets:
|
for set in sets:
|
||||||
pairs = [x+[y] for x in pairs for y in set]
|
pairs = [x+[y] for x in pairs for y in set]
|
||||||
|
|
||||||
|
print(pairs)
|
||||||
|
|
||||||
for i, pair in enumerate(pairs):
|
for i, pair in enumerate(pairs):
|
||||||
print(formatString.format(red(i + 1), *pair, bold(applyGate(*pair))))
|
print(formatString.format(red(i + 1), *pair, bold(applyGate(*pair))))
|
196
school/a-level/Y12 2022-2024/Storage/Pickle Shop.py
Normal file
196
school/a-level/Y12 2022-2024/Storage/Pickle Shop.py
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
from pickle import load, dump
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from sys import path as sysPath
|
||||||
|
from os.path import join as pathJoin, exists as pathExists
|
||||||
|
from typing import List, Callable, TypeVar
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
class ExistsError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Product:
|
||||||
|
name: str
|
||||||
|
price: float
|
||||||
|
formatString = " {:^30} | {:^10} "
|
||||||
|
currency = "£"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format(product: Product, currency: str) -> str:
|
||||||
|
return Product.formatString.format(product.name, f"{currency}{product.price:.2f}")
|
||||||
|
|
||||||
|
class Products:
|
||||||
|
def __init__(self, friendlyName: str, currency: str = "£"):
|
||||||
|
self.__products: List[Product] = []
|
||||||
|
self.__file = self.getPath(friendlyName)
|
||||||
|
self.__currency = currency
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getPath(friendlyName: str) -> str:
|
||||||
|
return pathJoin(sysPath[0], f"{friendlyName}.products")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def From(friendlyName: str, currency: str = "£"):
|
||||||
|
path = Products.getPath(friendlyName)
|
||||||
|
|
||||||
|
if not pathExists(path):
|
||||||
|
return Products(friendlyName, currency)
|
||||||
|
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
data = load(f)
|
||||||
|
products = Products(friendlyName, data["currency"])
|
||||||
|
|
||||||
|
for product in data["products"]:
|
||||||
|
products.add(product)
|
||||||
|
|
||||||
|
return products
|
||||||
|
|
||||||
|
def __save(self) -> Products:
|
||||||
|
"""Save all of the products to a file."""
|
||||||
|
with open(self.__file, "wb") as f:
|
||||||
|
dump({
|
||||||
|
"products": self.__products,
|
||||||
|
"currency": self.__currency
|
||||||
|
}, f)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def exists(self, name: str) -> Product:
|
||||||
|
"""Checks if a product with that name already exists"""
|
||||||
|
for product in self.__products:
|
||||||
|
if product.name.lower() == name.lower():
|
||||||
|
return product
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def setCurrency(self, currency: str) -> Products:
|
||||||
|
self.__currency = currency
|
||||||
|
return self.__save()
|
||||||
|
|
||||||
|
def add(self, product: Product) -> Products:
|
||||||
|
"""Add a product to the list."""
|
||||||
|
if self.exists(product.name):
|
||||||
|
raise ExistsError(f"A product called {product.name} already exists!")
|
||||||
|
|
||||||
|
self.__products.append(product)
|
||||||
|
return self.__save()
|
||||||
|
|
||||||
|
def remove(self, name: str) -> Products:
|
||||||
|
"""Remove a product from the list"""
|
||||||
|
for i, product in enumerate(self.__products):
|
||||||
|
if product.name.lower() == name.lower():
|
||||||
|
del self.__products[i]
|
||||||
|
|
||||||
|
return self.__save()
|
||||||
|
|
||||||
|
def clear(self) -> Products:
|
||||||
|
"""Clear the list of products"""
|
||||||
|
self.__products = []
|
||||||
|
return self.__save()
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
header = Product.formatString.format("Name", "Price")
|
||||||
|
divider = "-" * len(header)
|
||||||
|
out = f"{header}\n{divider}"
|
||||||
|
|
||||||
|
for product in self.__products:
|
||||||
|
out += f"\n{Product.format(product, self.__currency)}"
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def __add__(self, product: Product) -> Products:
|
||||||
|
return self.add(product)
|
||||||
|
|
||||||
|
def __getitem__(self, index: int) -> Product:
|
||||||
|
return self.__products[index]
|
||||||
|
|
||||||
|
def __setitem__(self, index: int, product: Product):
|
||||||
|
self.__products[index] = product
|
||||||
|
self.__save()
|
||||||
|
|
||||||
|
def __len__(self) -> int:
|
||||||
|
return len(self.__products)
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
def getInput(caster: Callable[[str], T], prompt: str, error: str, validator: Callable[[T], bool] = None) -> T:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
value = caster(input(prompt))
|
||||||
|
|
||||||
|
if validator and validator(value):
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
return value
|
||||||
|
except ValueError:
|
||||||
|
print(error)
|
||||||
|
|
||||||
|
def getProduct() -> Product:
|
||||||
|
name = input("Please enter a name for the product: ")
|
||||||
|
price = getInput(float, "Please enter a price for the product: ", "Please ensure that your input was a valid float!", lambda x: x <= 0)
|
||||||
|
|
||||||
|
return Product(name, price)
|
||||||
|
|
||||||
|
def clear():
|
||||||
|
print('\n' * 50)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Load a product list
|
||||||
|
name = input("Please enter the name of a list of products: ")
|
||||||
|
products = Products.From(name.lower())
|
||||||
|
|
||||||
|
if len(products) == 0:
|
||||||
|
print(f"Created new products list \"{name}\"")
|
||||||
|
else:
|
||||||
|
print(f"Loaded pre-existing product list \"{name}\"")
|
||||||
|
|
||||||
|
# Main menu loop
|
||||||
|
while True:
|
||||||
|
clear()
|
||||||
|
print("""1) View the list of products
|
||||||
|
2) Add a product
|
||||||
|
3) Remove a product
|
||||||
|
4) Update currency
|
||||||
|
5) Clear the list of products
|
||||||
|
6) Exit
|
||||||
|
""")
|
||||||
|
|
||||||
|
choice = getInput(int, "What would you like to do? (1-5): ", "Please choose a valid option.", lambda x: x < 1 or x > 6)
|
||||||
|
print()
|
||||||
|
|
||||||
|
if choice == 1:
|
||||||
|
print(products)
|
||||||
|
elif choice == 2:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
product = getProduct()
|
||||||
|
products.add(product)
|
||||||
|
break
|
||||||
|
except ExistsError:
|
||||||
|
print("Please make sure the product's name is unique!")
|
||||||
|
|
||||||
|
print(f"Added product {product}")
|
||||||
|
elif choice == 3:
|
||||||
|
while True:
|
||||||
|
name = input("Please enter the name of a product to remove: ")
|
||||||
|
product = products.exists(name)
|
||||||
|
|
||||||
|
if product:
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Make sure you enter the name of a valid product!")
|
||||||
|
|
||||||
|
products.remove(name)
|
||||||
|
print(f"Removed product {product}")
|
||||||
|
elif choice == 4:
|
||||||
|
currency = input("Please enter a new currency symbol: ")
|
||||||
|
products.setCurrency(currency)
|
||||||
|
print(f"Currency symbol updated to {currency}")
|
||||||
|
elif choice == 5:
|
||||||
|
products.clear()
|
||||||
|
print("Cleared list of products.")
|
||||||
|
elif choice == 6:
|
||||||
|
exit()
|
||||||
|
|
||||||
|
sleep(1)
|
BIN
school/a-level/Y12 2022-2024/Storage/main.products
Normal file
BIN
school/a-level/Y12 2022-2024/Storage/main.products
Normal file
Binary file not shown.
|
@ -0,0 +1,92 @@
|
||||||
|
from typing import Generic, TypeVar
|
||||||
|
from math import ceil
|
||||||
|
|
||||||
|
K, V = TypeVar('K'), TypeVar('V')
|
||||||
|
|
||||||
|
class HashItem(Generic[K, V]):
|
||||||
|
def __init__(self, key: K, value: V):
|
||||||
|
self.key = key
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
class HashTable(Generic[K, V]):
|
||||||
|
def __init__(self):
|
||||||
|
self.__size = 256
|
||||||
|
self.__count = 0
|
||||||
|
self.__slots: list[HashItem[K, V]] = [None for _ in range(self.__size)]
|
||||||
|
|
||||||
|
def __hash(self, key: K):
|
||||||
|
multiplier = 1
|
||||||
|
hashValue = 0
|
||||||
|
|
||||||
|
for character in key:
|
||||||
|
hashValue += multiplier * ord(character)
|
||||||
|
multiplier += 1
|
||||||
|
|
||||||
|
return hashValue % self.__size
|
||||||
|
|
||||||
|
def __filledSlots(self):
|
||||||
|
return list(filter(lambda x: x is not None, self.__slots))
|
||||||
|
|
||||||
|
def __load(self):
|
||||||
|
return len(list(self.__filledSlots())) / self.__size
|
||||||
|
|
||||||
|
def __grow(self, newSize: int):
|
||||||
|
self.__slots += [None for _ in range(newSize - self.__size)]
|
||||||
|
self.__size = newSize
|
||||||
|
|
||||||
|
def put(self, key: K, value: V):
|
||||||
|
item = HashItem(key, value)
|
||||||
|
hashValue = self.__hash(key)
|
||||||
|
|
||||||
|
while self.__slots[hashValue] != None:
|
||||||
|
if self.__slots[hashValue].key == key:
|
||||||
|
break
|
||||||
|
|
||||||
|
hashValue += 1
|
||||||
|
hashValue %= self.__size
|
||||||
|
|
||||||
|
if self.__slots[hashValue] == None:
|
||||||
|
self.__count += 1
|
||||||
|
|
||||||
|
# If the hash table is nearing its maximum load, increase the size of the hash table by 10%
|
||||||
|
if self.__load() >= 0.75:
|
||||||
|
self.__grow(ceil(self.__size * 1.1))
|
||||||
|
|
||||||
|
self.__slots[hashValue] = item
|
||||||
|
|
||||||
|
def get(self, key: K):
|
||||||
|
hashValue = self.__hash(key)
|
||||||
|
|
||||||
|
for slot in self.__filledSlots():
|
||||||
|
if hashValue == self.__hash(slot.key):
|
||||||
|
return slot.value
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __setitem__(self, key: K, value: V):
|
||||||
|
self.put(key, value)
|
||||||
|
|
||||||
|
def __getitem__(self, key: K):
|
||||||
|
return self.get(key)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
template = " {: ^10} | {: ^10}"
|
||||||
|
out = template.format("Key", "Value")
|
||||||
|
out += "\n" + ("-" * (len(out) // 2)) + "|" + ("-" * (len(out) // 2)) + "\n"
|
||||||
|
|
||||||
|
slots = self.__filledSlots()
|
||||||
|
|
||||||
|
for i, slot in enumerate(slots):
|
||||||
|
out += template.format(slot.key, slot.value)
|
||||||
|
|
||||||
|
if i + 1 != len(slots):
|
||||||
|
out += "\n"
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.__slots)
|
||||||
|
|
||||||
|
ages = HashTable[str, int]()
|
||||||
|
ages["John Doe"] = 16
|
||||||
|
print(ages)
|
|
@ -0,0 +1,201 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Generic, TypeVar, Iterable, Union, List
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Node(Generic[T]):
|
||||||
|
data: T
|
||||||
|
next: Node[T] = None
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return str(self.data)
|
||||||
|
|
||||||
|
class LinkedList(Generic[T]):
|
||||||
|
def __init__(self, initialValues: Iterable[T]):
|
||||||
|
self.head: Node[T] = None
|
||||||
|
self.tail: Node[T] = None
|
||||||
|
|
||||||
|
self.extend(initialValues)
|
||||||
|
|
||||||
|
def __iter__(self) -> Iterable[T]:
|
||||||
|
"""Traverse the linked list."""
|
||||||
|
node = self.head
|
||||||
|
|
||||||
|
while node is not None:
|
||||||
|
yield node
|
||||||
|
node = node.next
|
||||||
|
|
||||||
|
def __getitem__(self, index: int) -> Node[T]:
|
||||||
|
"""Get an item by its index."""
|
||||||
|
if index > len(self) - 1:
|
||||||
|
raise IndexError("Out of bounds")
|
||||||
|
|
||||||
|
for i, node in enumerate(self):
|
||||||
|
if i == index:
|
||||||
|
return node
|
||||||
|
|
||||||
|
def __setitem__(self, index: int, data: T):
|
||||||
|
"""Set an item by its index."""
|
||||||
|
if index > len(self) - 1:
|
||||||
|
raise IndexError("Out of bounds")
|
||||||
|
|
||||||
|
for i in range(len(self)):
|
||||||
|
if i == index:
|
||||||
|
self[i].data = data
|
||||||
|
break
|
||||||
|
|
||||||
|
def __delitem__(self, index: int):
|
||||||
|
"""Delete an item using its index."""
|
||||||
|
if index > len(self) - 1:
|
||||||
|
raise IndexError("Out of bounds")
|
||||||
|
|
||||||
|
for i in range(len(self)):
|
||||||
|
if i == index:
|
||||||
|
for j in range(1, len(self) - i):
|
||||||
|
self[i + j - 1] = self[i + j].data
|
||||||
|
|
||||||
|
self[len(self) - 2].next = None
|
||||||
|
break
|
||||||
|
|
||||||
|
def __add__(self, data: Union[T, List[T], LinkedList[T]]) -> LinkedList[T]:
|
||||||
|
copy = self.copy()
|
||||||
|
|
||||||
|
if isinstance(data, LinkedList) or type(data) == list:
|
||||||
|
return copy.extend(iter(data) if type(data) == list else iter(map(lambda x: x.data, data)))
|
||||||
|
else:
|
||||||
|
return copy.append(data)
|
||||||
|
|
||||||
|
def __len__(self) -> int:
|
||||||
|
"""Get the length of the linked list."""
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for _ in self:
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
return count
|
||||||
|
|
||||||
|
def append(self, value: T) -> LinkedList[T]:
|
||||||
|
"""Append data to the end of the linked list."""
|
||||||
|
node = Node(value)
|
||||||
|
|
||||||
|
if self.head is None:
|
||||||
|
self.head = node
|
||||||
|
return self
|
||||||
|
|
||||||
|
for currentNode in self:
|
||||||
|
pass
|
||||||
|
|
||||||
|
currentNode.next = node
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def clear(self) -> LinkedList[T]:
|
||||||
|
"""Clear the linked list."""
|
||||||
|
self.head = None
|
||||||
|
self.tail = None
|
||||||
|
return self
|
||||||
|
|
||||||
|
def count(self, value: T) -> int:
|
||||||
|
"""Count the number of occurrences of a value."""
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for node in self:
|
||||||
|
if node.data == value:
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
return count
|
||||||
|
|
||||||
|
def extend(self, iterable: Iterable[T]) -> LinkedList[T]:
|
||||||
|
"""Extend the list from an iterable."""
|
||||||
|
for value in iterable:
|
||||||
|
self.append(value)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def index(self, value: T) -> int:
|
||||||
|
"""Finds the first index of a value. Returns -1 if the value is not in the list."""
|
||||||
|
for i, node in enumerate(self):
|
||||||
|
if node.data == value:
|
||||||
|
return i
|
||||||
|
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def insert(self, index: int, value: T) -> LinkedList[T]:
|
||||||
|
"""Inserts a value before an index."""
|
||||||
|
if index > len(self) - 1:
|
||||||
|
raise IndexError("Out of bounds")
|
||||||
|
|
||||||
|
for i in range(len(self)):
|
||||||
|
if i == index:
|
||||||
|
container = value
|
||||||
|
|
||||||
|
for j in range(len(self)):
|
||||||
|
try:
|
||||||
|
temp = self[i + j].data
|
||||||
|
self[i + j].data = container
|
||||||
|
container = temp
|
||||||
|
except IndexError:
|
||||||
|
self.append(container)
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def pop(self) -> Node[T]:
|
||||||
|
"""Pop and return the final element of the list."""
|
||||||
|
for node in self:
|
||||||
|
pass
|
||||||
|
|
||||||
|
del self[len(self) - 1]
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
def remove(self, value: T) -> LinkedList[T]:
|
||||||
|
for i, node in enumerate(self):
|
||||||
|
if node.data == value:
|
||||||
|
del self[i]
|
||||||
|
return self
|
||||||
|
|
||||||
|
raise ValueError("Value not found")
|
||||||
|
|
||||||
|
def copy(self) -> LinkedList[T]:
|
||||||
|
"""Returns a copy of the list."""
|
||||||
|
return LinkedList[T](iter(map(lambda x: x.data, self)))
|
||||||
|
|
||||||
|
def sort(self) -> LinkedList[T]:
|
||||||
|
n = len(self)
|
||||||
|
swapped = False
|
||||||
|
|
||||||
|
for i in range(n - 1):
|
||||||
|
for j in range(0, n - i - 1):
|
||||||
|
if self[j].data > self[j + 1].data:
|
||||||
|
swapped = True
|
||||||
|
self[j], self[j + 1] = self[j + 1].data, self[j].data
|
||||||
|
|
||||||
|
if not swapped:
|
||||||
|
break
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
out = "["
|
||||||
|
|
||||||
|
for i, node in enumerate(self):
|
||||||
|
value = node.data
|
||||||
|
|
||||||
|
out += f'"{value}"' if type(value) == str else value
|
||||||
|
|
||||||
|
if i != len(self) - 1:
|
||||||
|
out += ", "
|
||||||
|
|
||||||
|
return out + "]"
|
||||||
|
|
||||||
|
names = LinkedList[str](["Harold", "Janet"])
|
||||||
|
names.extend(["Alfred", "Sophie"]).insert(1, "John Snow")
|
||||||
|
names.remove("Alfred")
|
||||||
|
names += "Woody"
|
||||||
|
names.sort()
|
||||||
|
|
||||||
|
print(names)
|
Binary file not shown.
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
17,22,8,31,30,29,16,17,23,32
|
|
||||||
23,6,25,44,19,21,8,18,29,41
|
|
|
Loading…
Reference in a new issue