feat: add my hmwk grind from today

This commit is contained in:
newt 2024-10-09 18:02:48 +01:00
parent 090fd7caf4
commit 0d691fba04
36 changed files with 449 additions and 412 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1,17 +0,0 @@
from typing import Dict
import re
def letterFrequency(text: str) -> Dict[str, int]:
output = {}
text = re.sub('[^a-zA-Z]+', '', text)
for letter in text:
if letter in output:
output[letter] += 1
else:
output[letter] = 1
return output
frequency = letterFrequency('I wish I wish with all my heart to fly with dragons in a land apart')
print(frequency)

View file

@ -1,92 +0,0 @@
from time import sleep
# :eyes:
def clearTerminal():
print('\n' * 25)
def findPrimes(upperBound: int):
"""
Implementation of the Sieve of Eratosthenes.
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
"""
mask = [True for _ in range(upperBound)]
primes = []
mask[0] = False
mask[1] = False
for i in range(2, upperBound):
if mask[i]:
primes.append(i)
j = 2 * i
while j < upperBound:
mask[j] = False
j += i
return primes
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 = []
def getPrime(primeList):
while True:
try:
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:
raise ValueError('Please ensure you enter an integer at most 6 digits long!')
elif value not in POSSIBLE_PRIMES:
raise ValueError('That is not a prime number! Please try again.')
elif value in primeList:
raise ValueError('You have already inputted that prime number! Please enter a different one.')
# Mutate the prime list and return it back to the caller
primeList.append(value)
return primeList
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"):
print('Please enter a valid integer!')
else:
print(e)
if __name__ == "__main__":
while True:
print("""Welcome to the prime checker!
What would you like to do?
1) Add a number to the list
2) View the list of inputted primes
3) Exit
""")
while True:
try:
choice = int(input("Please enter your choice: "))
if choice not in [1, 2, 3]:
raise ValueError
break
except ValueError:
print("Please enter a valid option from the list (1-3)")
clearTerminal()
if choice == 1:
inputtedPrimes = getPrime(inputtedPrimes)
elif choice == 2:
# 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)
elif choice == 3:
exit()
clearTerminal()

View file

@ -1,18 +0,0 @@
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()

View file

@ -1,190 +0,0 @@
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)

View file

@ -1,79 +0,0 @@
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}""")

View file

@ -0,0 +1,93 @@
from typing import List
import os.path
class Class:
def __init__(self, name: str, marks: List[int] = []):
self.__name = name
self.__marks = marks
self.__marks.sort()
def __add__(self, marks: int | List[int]):
if type(marks) == int:
self.__marks.append(marks)
elif type(marks) == list:
self.__marks.extend(marks)
self.__marks.sort()
return self
def __iadd__(self, marks: int | List[int]):
return self.__add__(marks)
def __len__(self) -> int:
return len(self.__marks)
def __str__(self) -> str:
return self.__name
def mean(self) -> int:
return sum(self.__marks) / len(self.__marks)
def median(self) -> int:
return self.__marks[len(self.__marks) // 2]
def above_median(self) -> int:
return len([mark for mark in self.__marks if mark > self.median()])
def below_median(self) -> int:
return len([mark for mark in self.__marks if mark < self.median()])
def mode(self) -> int:
return max(set(self.__marks), key=self.__marks.count)
def save(self):
name = self.__name.replace("/", "")
with open(f"{name}.csv", "w") as file:
file.write(",".join([str(mark) for mark in self.__marks]))
def get_class(name: str):
sanitized_name = name.replace("/", "")
marks = []
if os.path.exists(f"{sanitized_name}.csv"):
with open(f"{sanitized_name}.csv", "r") as file:
marks += [int(mark) for mark in file.read().split(",")]
else:
while True:
try:
marks = [int(x) for x in input(f"Please enter a comma separated list of the marks for class {name}: ").split(",") if x != ""]
break
except ValueError:
print("Please enter a valid list of marks.")
pass
_class = Class(name, marks)
_class.save()
return _class
cs1 = get_class("12/CS1")
cs2 = get_class("12/CS2")
highest_mean = "12/CS1" if cs1.mean() > cs2.mean() else "12/CS2"
print(f"""
12/CS1
-------
Mean: {cs1.mean()}
Median: {cs1.median()}
Mode: {cs1.mode()}
Above Median: {cs1.above_median()}
Below Median: {cs1.below_median()}
12/CS2
-------
Mean: {cs2.mean()}
Median: {cs2.median()}
Mode: {cs2.mode()}
Above Median: {cs2.above_median()}
Below Median: {cs2.below_median()}
{highest_mean} has the highest mean.
""")

View file

@ -0,0 +1,157 @@
from typing import List, Dict, TypedDict
from enum import IntEnum
from random import choice
import pickle
import bcrypt
import os
class Permissions(IntEnum):
Read = 1
Write = 2
class AccountType(TypedDict):
username: str
password: str
permissions: Dict[str, int]
class Account:
def __init__(self, permissions: Dict[str, int]):
self.__permissions = permissions
def __has_permission(self, filename: str, permission: Permissions) -> bool:
if filename in self.__permissions:
return self.__permissions[filename] & (1 << (permission - 1)) == permission
return False
def open_file(self, filename: str) -> str:
if self.__has_permission(filename, Permissions.Read):
with open(filename, "r") as file:
return file.read()
return None
def write_file(self, filename: str, content: str) -> str:
if self.__has_permission(filename, Permissions.Write):
with open(filename, "w") as file:
return file.write(content)
return None
class AuthManager:
def __init__(self, filename: str = "accounts.pickle"):
self.__filename = filename
if os.path.exists(filename):
with open(filename, "rb") as file:
self.__accounts: List[AccountType] = pickle.load(file)
dead_files = []
for i, account in enumerate(self.__accounts):
for file in account["permissions"]:
if not os.path.exists(file):
dead_files.append((i, file))
for i, file in dead_files:
del self.__accounts[i]["permissions"][file]
else:
self.__accounts = []
def __save(self):
with open(self.__filename, "wb") as file:
pickle.dump(self.__accounts, file)
def register(self, username: str, password: str):
for account in self.__accounts:
if account["username"] == username:
return
bytes = password.encode("utf-8")
salt = bcrypt.gensalt()
hash = bcrypt.hashpw(bytes, salt)
self.__accounts.append({
"username": username,
"password": hash,
"permissions": {}
})
self.__save()
def login(self, username: str, password: str) -> Account:
hash = None
permissions = None
for account in self.__accounts:
if account["username"] == username:
hash = account["password"]
permissions = account["permissions"]
if hash is None:
return None
elif bcrypt.checkpw(password.encode("utf-8"), hash):
return Account(permissions)
else:
return None
def add_permission(self, username: str, filename: str, permission: Permissions) -> bool:
if not os.path.exists(filename):
return False
foundAccount = False
for i, account in enumerate(self.__accounts):
if account["username"] == username:
foundAccount = True
break
if not foundAccount:
return False
else:
if filename in self.__accounts[i]["permissions"]:
if self.__accounts[i]["permissions"][filename] & (1 << (permission - 1)) == permission:
return False
self.__accounts[i]["permissions"][filename] += permission
else:
self.__accounts[i]["permissions"][filename] = int(permission)
self.__save()
return True
def remove_permission(self, username: str, filename: str, permission: Permissions) -> bool:
foundAccount = False
for i, account in enumerate(self.__accounts):
if account["username"] == username:
foundAccount = True
break
if not foundAccount:
return False
else:
if not filename in self.__accounts[i]["permissions"]:
return False
elif self.__accounts[i]["permissions"][filename] & (1 << (permission - 1)) != permission:
return False
self.__accounts[i]["permissions"][filename] -= permission
self.__save()
return True
auth = AuthManager()
# auth.register("test", "password")
# auth.add_permission("test", "test.txt", Permissions.Read)
# auth.register("test2", "password")
# auth.register("test3", "password")
# auth.add_permission("test3", "test.txt", Permissions.Write)
acc = auth.login("test", "password") # has permission to read
acc2 = auth.login("test2", "password") # does not have any permissions
acc3 = auth.login("test3", "password") # has permission to write
acc3.write_file("test.txt", choice([f"test{i}" for i in range(20)]))
assert acc.open_file("test.txt") is not None
assert acc2.open_file("test.txt") is None

View file

@ -0,0 +1 @@
bcrypt==4.0.1

View file

@ -0,0 +1 @@
test1

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -0,0 +1,20 @@
from typing import List, TypeVar
T = TypeVar('T')
def binary_search(arr: List[T], target: T) -> int:
n = len(arr)
l = 0
r = n - 1
while l <= r:
m = (l + r) // 2
if arr[m] < target:
l = m + 1
elif arr[m] > target:
r = m - 1
else:
return m
return -1

View file

@ -0,0 +1,16 @@
from typing import List, TypeVar
T = TypeVar('T')
# optimised implementation of bubble sort, psuedocode from https://en.wikipedia.org/wiki/Bubble_sort
def bubble_sort(arr: List[T], asc: bool = True) -> List[T]:
n = len(arr)
swapped = False
while not swapped:
for i in range(1, n):
if arr[i - 1] > arr[i]:
arr[i - 1], arr[i] = arr[i], arr[i - 1]
swapped = True
return arr if asc else arr[::-1]

View file

@ -0,0 +1,20 @@
from typing import List, TypeVar
T = TypeVar('T')
# optimised implementation of insertion sort, psuedocode from https://en.wikipedia.org/wiki/Insertion_sort
def insertion_sort(arr: List[T], asc: bool = True) -> List[T]:
i = 1
while i < len(arr):
x = arr[i]
j = i - 1
while j >= 0 and arr[j] > x:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = x
i += 1
return arr if asc else arr[::-1]

View file

@ -0,0 +1,10 @@
from typing import List, TypeVar
T = TypeVar('T')
def linear_search(arr: List[T], target: T) -> int:
for i in range(len(arr)):
if arr[i] == target:
return i
return -1

View file

@ -0,0 +1,66 @@
from random import randint, choice
from timeit import timeit
from matplotlib import pyplot as plt
from copy import copy
import sys
sys.setrecursionlimit(1500) # this is required to run the recursive quicksort, but is usually not recommended
from linear import linear_search
from binary import binary_search
from bubble import bubble_sort
from insertion import insertion_sort
from quicksort import recursive_quick_sort, iterative_quick_sort
# config
LOW = 0
HIGH = 100
TRIAL_COUNT = 10
N_LIST = [50, 100, 1000]
times = {'Linear Search': [], 'Binary Search': [], 'Bubble Sort': [], 'Insertion Sort': [], 'Quicksort (Recursive)': [], 'Quicksort (Iterative)': []}
N_LIST.sort()
for n in N_LIST:
# generate the test data
data = [randint(LOW, HIGH) for _ in range(n)]
random_element = choice(data)
sorted_data = copy(data)
sorted_data.sort()
# perform all of the computations
linear_time = round(timeit(lambda: linear_search(data, random_element), number=TRIAL_COUNT) * 1000, 4)
binary_time = round(timeit(lambda: binary_search(sorted_data, random_element), number=TRIAL_COUNT) * 1000, 4)
bubble_time = round(timeit(lambda: bubble_sort(data), number=TRIAL_COUNT) * 1000, 4)
insertion_time = round(timeit(lambda: insertion_sort(data), number=TRIAL_COUNT) * 1000, 4)
quicksort_recursive_time = round(timeit(lambda: recursive_quick_sort(data), number=TRIAL_COUNT) * 1000, 4)
quicksort_iterative_time = round(timeit(lambda: iterative_quick_sort(data), number=TRIAL_COUNT) * 1000, 4)
print(f"""n = {n}
Linear Search: {linear_time}ms
Binary Search: {binary_time}ms
Bubble Sort: {bubble_time}ms
Insertion Sort: {insertion_time}ms
Recursive Quicksort: {quicksort_recursive_time}ms
Iterative Quicksort: {quicksort_iterative_time}ms
-------------------------------------""")
# store the times
times['Linear Search'].append(linear_time)
times['Binary Search'].append(binary_time)
times['Bubble Sort'].append(bubble_time)
times['Insertion Sort'].append(insertion_time)
times['Quicksort (Recursive)'].append(quicksort_recursive_time)
times['Quicksort (Iterative)'].append(quicksort_iterative_time)
# plot the times
plt.xlabel('n')
plt.ylabel('Time (ms)')
for key in times:
plt.clf()
plt.title(f"Time Complexity of {key}")
print(key, times[key])
plt.plot(N_LIST, times[key], linestyle='--', marker='o', color='b')
plt.savefig(f"{key}.png")

View file

@ -0,0 +1,65 @@
from typing import List, TypeVar
T = TypeVar('T')
def partition(arr: List[T], low: int, high: int) -> int:
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
# https://en.wikipedia.org/wiki/Quicksort
def recursive_quick_sort(arr: List[T], asc: bool = True, low: int = 0, high: int = None) -> List[T]:
if high is None or high > len(arr) - 1:
high = len(arr) - 1
if low < high:
p = partition(arr, low, high)
recursive_quick_sort(arr, asc, low, p - 1)
recursive_quick_sort(arr, asc, p + 1, high)
return arr if asc else arr[::-1]
def iterative_quick_sort(arr: List[T], asc: bool = True, low: int = 0, high: int = None) -> List[T]:
if high is None or high > len(arr) - 1:
high = len(arr) - 1
if low < high:
size = high - low + 1
stack = [0] * size
top = -1
top += 1
stack[top] = low
top += 1
stack[top] = high
while top >= 0:
high = stack[top]
top -= 1
low = stack[top]
top -= 1
p = partition(arr, low, high)
if p - 1 > low:
top += 1
stack[top] = low
top += 1
stack[top] = p - 1
if p + 1 < high:
top += 1
stack[top] = p + 1
top += 1
stack[top] = high
return arr if asc else arr[::-1]

View file

@ -1,16 +0,0 @@
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)