Added comments and error handling to helper file
This commit is contained in:
parent
a8dbb6bd22
commit
658dd6bc14
@ -8,6 +8,7 @@
|
|||||||
|@..@'. ~ " ' ~ | |>O>o<@< \____ .'| 4 **
|
|@..@'. ~ " ' ~ | |>O>o<@< \____ .'| 4 **
|
||||||
|_.~._@'.. ~ ~ *| | _| |_ ..\_\_ ..'* | 5 **
|
|_.~._@'.. ~ ~ *| | _| |_ ..\_\_ ..'* | 5 **
|
||||||
| ||| @@ '''...| |... .' '.'''../..| 6 **
|
| ||| @@ '''...| |... .' '.'''../..| 6 **
|
||||||
|
|#~~~@@@@ @ | |/\ ''. | | -/ :| 7 **
|
||||||
|
|
||||||
## 2023
|
## 2023
|
||||||
|
|
||||||
|
279
fred.py
279
fred.py
@ -1,118 +1,316 @@
|
|||||||
import re,sys
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
def loadFile(input_f):
|
def loadFile(input_f):
|
||||||
|
"""
|
||||||
|
Loads a file and returns its lines as a list.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_f (str): The file path to read from.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of lines from the file, with each line stripped of trailing newlines.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: If the file cannot be found.
|
||||||
|
IOError: If there is an error reading the file.
|
||||||
|
"""
|
||||||
lines = []
|
lines = []
|
||||||
|
try:
|
||||||
with open(input_f) as file:
|
with open(input_f) as file:
|
||||||
for line in file:
|
for line in file:
|
||||||
lines.append(line.rstrip())
|
lines.append(line.rstrip()) # Removes trailing newline from each line
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise FileNotFoundError(f"The file '{input_f}' was not found.")
|
||||||
|
except IOError as e:
|
||||||
|
raise IOError(f"Error reading file '{input_f}': {e}")
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
def convert_list(input_list):
|
def convert_list(input_list):
|
||||||
"""
|
"""
|
||||||
Convert a list of strings to integers where possible, leaving others as strings.
|
Converts a list of strings to integers where possible, leaving others as strings.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
input_list (list): A list of strings to be converted.
|
input_list (list): A list of strings to be converted.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: A list with integers or strings based on the input.
|
list: A list with integers or strings based on the input.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If the input is not a list.
|
||||||
"""
|
"""
|
||||||
|
if not isinstance(input_list, list):
|
||||||
|
raise TypeError("Input must be a list.")
|
||||||
|
|
||||||
converted_list = []
|
converted_list = []
|
||||||
for item in input_list:
|
for item in input_list:
|
||||||
try:
|
try:
|
||||||
converted_list.append(int(item))
|
converted_list.append(int(item)) # Attempt to convert string to integer
|
||||||
except ValueError:
|
except ValueError:
|
||||||
converted_list.append(item)
|
converted_list.append(item) # Leave as string if conversion fails
|
||||||
return converted_list
|
return converted_list
|
||||||
|
|
||||||
|
|
||||||
def toGrid(input, parser=None):
|
def toGrid(input, parser=None):
|
||||||
|
"""
|
||||||
|
Converts input (file or data) into a grid (list of lists).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input (str): The file path or data to be converted into a grid.
|
||||||
|
parser (function, optional): A parser function to process each line before adding to the grid.
|
||||||
|
Defaults to None.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A 2D list (grid) representation of the input.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: If the file cannot be found (if input is a file path).
|
||||||
|
ValueError: If the parser function is invalid.
|
||||||
|
"""
|
||||||
|
if parser is not None and not callable(parser):
|
||||||
|
raise ValueError("The parser must be a callable function.")
|
||||||
|
|
||||||
grid = []
|
grid = []
|
||||||
if parser:
|
try:
|
||||||
with open(input) as file:
|
with open(input) as file:
|
||||||
for line in file:
|
for line in file:
|
||||||
grid.append(list2int(line.rstrip()))
|
grid.append(list2int(line.rstrip()) if parser else list(line.rstrip())) # Use parser or default processing
|
||||||
else:
|
except FileNotFoundError:
|
||||||
with open(input) as file:
|
raise FileNotFoundError(f"The file '{input}' was not found.")
|
||||||
for line in file:
|
except IOError as e:
|
||||||
grid.append(list(line.rstrip()))
|
raise IOError(f"Error reading file '{input}': {e}")
|
||||||
|
|
||||||
return grid
|
return grid
|
||||||
|
|
||||||
def swap(a: int, b: int, lst: list):
|
def swap(a: int, b: int, lst: list):
|
||||||
"""
|
"""
|
||||||
Swaps two numbers in a list based on their indices.
|
Swaps two elements in a list based on their indices.
|
||||||
|
|
||||||
Parameters:
|
Args:
|
||||||
lst (list): The list of numbers.
|
a (int): Index of the first element.
|
||||||
index1 (int): The index of the first number.
|
b (int): Index of the second element.
|
||||||
index2 (int): The index of the second number.
|
lst (list): The list in which to swap elements.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: The list after swapping the two numbers.
|
list: The list with swapped elements.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
IndexError: If any index is out of range.
|
||||||
|
TypeError: If lst is not a list.
|
||||||
"""
|
"""
|
||||||
|
if not isinstance(lst, list):
|
||||||
|
raise TypeError("The provided object is not a list.")
|
||||||
if a < 0 or b < 0 or a >= len(lst) or b >= len(lst):
|
if a < 0 or b < 0 or a >= len(lst) or b >= len(lst):
|
||||||
raise IndexError("Index out of range.")
|
raise IndexError("Index out of range.") # Ensure indices are valid
|
||||||
|
lst[a], lst[b] = lst[b], lst[a] # Swap the elements
|
||||||
lst[a], lst[b] = lst[b], lst[a]
|
|
||||||
return lst
|
return lst
|
||||||
|
|
||||||
def addTuples(x: tuple, y: tuple):
|
def addTuples(x: tuple, y: tuple):
|
||||||
|
"""
|
||||||
|
Adds two tuples element-wise.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (tuple): The first tuple.
|
||||||
|
y (tuple): The second tuple.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: A tuple with the sum of corresponding elements of x and y.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If x or y are not tuples.
|
||||||
|
"""
|
||||||
|
if not isinstance(x, tuple) or not isinstance(y, tuple):
|
||||||
|
raise TypeError("Both inputs must be tuples.")
|
||||||
return (x[0] + y[0], x[1] + y[1])
|
return (x[0] + y[0], x[1] + y[1])
|
||||||
|
|
||||||
def findDupes(input: list):
|
def findDupes(input: list):
|
||||||
# Returns the indicies of duplicate values in list
|
"""
|
||||||
|
Finds duplicate elements in a list and returns their values.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input (list): The list to check for duplicates.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of duplicate values in the input.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If the input is not a list.
|
||||||
|
"""
|
||||||
|
if not isinstance(input, list):
|
||||||
|
raise TypeError("Input must be a list.")
|
||||||
return [item for item in set(input) if input.count(item) > 1]
|
return [item for item in set(input) if input.count(item) > 1]
|
||||||
|
|
||||||
def lprint(x: str, log: bool):
|
def lprint(x: str, log: bool):
|
||||||
|
"""
|
||||||
|
Prints a string if logging is enabled.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (str): The string to print.
|
||||||
|
log (bool): A flag to control logging.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
if log:
|
if log:
|
||||||
print(x)
|
print(x)
|
||||||
|
|
||||||
def expand_grid(grid):
|
def expand_grid(grid):
|
||||||
|
"""
|
||||||
|
Expands the grid by adding a border of '.' characters around it.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
grid (list): A 2D grid to expand.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A new 2D grid with a border added.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If grid is not a list of lists.
|
||||||
|
"""
|
||||||
|
if not all(isinstance(row, list) for row in grid):
|
||||||
|
raise TypeError("Grid must be a list of lists.")
|
||||||
|
|
||||||
num_rows = len(grid)
|
num_rows = len(grid)
|
||||||
num_cols = len(grid[0])
|
num_cols = len(grid[0])
|
||||||
|
|
||||||
expanded_grid = []
|
expanded_grid = []
|
||||||
|
|
||||||
|
# Add top and bottom borders
|
||||||
expanded_grid.append(['.'] * (num_cols + 2))
|
expanded_grid.append(['.'] * (num_cols + 2))
|
||||||
|
|
||||||
|
# Add left and right borders for each row
|
||||||
for row in grid:
|
for row in grid:
|
||||||
expanded_grid.append(['.'] + row + ['.'])
|
expanded_grid.append(['.'] + row + ['.'])
|
||||||
|
|
||||||
expanded_grid.append(['.'] * (num_cols + 2))
|
expanded_grid.append(['.'] * (num_cols + 2)) # Bottom border
|
||||||
|
|
||||||
return expanded_grid
|
return expanded_grid
|
||||||
|
|
||||||
def getCenter(grid):
|
def getCenter(grid):
|
||||||
|
"""
|
||||||
|
Gets the center position of a grid (middle of the grid).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
grid (list): A 2D grid.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: A tuple containing the row and column index of the center.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If grid is not a list of lists.
|
||||||
|
"""
|
||||||
|
if not all(isinstance(row, list) for row in grid):
|
||||||
|
raise TypeError("Grid must be a list of lists.")
|
||||||
|
|
||||||
return (int(len(grid) / 2), int(len(grid[0]) / 2))
|
return (int(len(grid) / 2), int(len(grid[0]) / 2))
|
||||||
|
|
||||||
def nprint(grid, cur: set = None, sign: str = None):
|
def nprint(grid, cur: set = None, sign: str = None):
|
||||||
|
"""
|
||||||
|
Prints a grid, highlighting the current position if specified.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
grid (list): A 2D grid to print.
|
||||||
|
cur (set, optional): A set containing the (row, col) indices of the current position.
|
||||||
|
Defaults to None.
|
||||||
|
sign (str, optional): The sign to highlight the current position with. Defaults to None.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If cur is not a set or sign is not a string.
|
||||||
|
"""
|
||||||
|
if cur is not None and not isinstance(cur, tuple):
|
||||||
|
raise TypeError("Cur must be a tuple with (row, column) indices.")
|
||||||
|
if sign is not None and not isinstance(sign, str):
|
||||||
|
raise TypeError("Sign must be a string.")
|
||||||
|
|
||||||
for idx, i in enumerate(grid):
|
for idx, i in enumerate(grid):
|
||||||
for jdx, j in enumerate(i):
|
for jdx, j in enumerate(i):
|
||||||
if (idx, jdx) == cur:
|
if (idx, jdx) == cur:
|
||||||
if len(sign) > 1:
|
if len(sign) > 1:
|
||||||
print(sign[0]+grid[idx][jdx]+sign[1],end='')
|
print(sign[0] + grid[idx][jdx] + sign[1], end='') # Print with sign
|
||||||
else:
|
else:
|
||||||
print(sign,end=' ')
|
print(sign, end=' ') # Print sign
|
||||||
else:
|
else:
|
||||||
print(grid[idx][jdx],end=' ')
|
print(grid[idx][jdx], end=' ') # Regular grid element
|
||||||
print()
|
print()
|
||||||
|
|
||||||
def list2int(x):
|
def list2int(x):
|
||||||
|
"""
|
||||||
|
Converts a list of strings to a list of integers.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (list): A list of strings to convert.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of integers.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If x is not a list.
|
||||||
|
"""
|
||||||
|
if not isinstance(x, list):
|
||||||
|
raise TypeError("Input must be a list.")
|
||||||
return list(map(int, x))
|
return list(map(int, x))
|
||||||
|
|
||||||
def grid_valid(x, y, grid):
|
def grid_valid(x, y, grid):
|
||||||
|
"""
|
||||||
|
Checks if a grid position is valid (within bounds).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (int): The row index.
|
||||||
|
y (int): The column index.
|
||||||
|
grid (list): The 2D grid to check against.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the position is within bounds, False otherwise.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If grid is not a list of lists.
|
||||||
|
"""
|
||||||
|
if not all(isinstance(row, list) for row in grid):
|
||||||
|
raise TypeError("Grid must be a list of lists.")
|
||||||
|
|
||||||
rows = len(grid)
|
rows = len(grid)
|
||||||
cols = len(grid[0])
|
cols = len(grid[0])
|
||||||
return 0 <= x < rows and 0 <= y < cols
|
return 0 <= x < rows and 0 <= y < cols
|
||||||
|
|
||||||
def get_re(pattern, str):
|
def get_re(pattern, str):
|
||||||
|
"""
|
||||||
|
Returns a match object if the pattern matches the string, else None.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pattern (str): The regular expression pattern to match.
|
||||||
|
str (str): The string to match against.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
match or None: A match object if a match is found, otherwise None.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If str is not a string.
|
||||||
|
"""
|
||||||
|
if not isinstance(str, str):
|
||||||
|
raise TypeError("Input string must be of type str.")
|
||||||
|
|
||||||
match = re.match(pattern, str)
|
match = re.match(pattern, str)
|
||||||
if match:
|
if match:
|
||||||
return match
|
return match
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def ppprint(x):
|
def ppprint(x):
|
||||||
|
"""
|
||||||
|
Pretty prints a 2D grid or matrix.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (list): A 2D grid to print.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If x is not a list of lists.
|
||||||
|
"""
|
||||||
|
if not all(isinstance(row, list) for row in x):
|
||||||
|
raise TypeError("Input must be a list of lists.")
|
||||||
|
|
||||||
for idx, i in enumerate(x):
|
for idx, i in enumerate(x):
|
||||||
for jdx, j in enumerate(i):
|
for jdx, j in enumerate(i):
|
||||||
print(x[idx][jdx], end='')
|
print(x[idx][jdx], end='')
|
||||||
@ -123,19 +321,24 @@ def get_value_in_direction(grid, position, direction=None,length=1,type:str=None
|
|||||||
Get the value(s) in a specified direction from a given position in a grid.
|
Get the value(s) in a specified direction from a given position in a grid.
|
||||||
If no direction is provided, returns the value at the current position.
|
If no direction is provided, returns the value at the current position.
|
||||||
|
|
||||||
Parameters:
|
Args:
|
||||||
grid (list of list of int/float/str): The 2D grid.
|
grid (list of list of int/float/str): The 2D grid.
|
||||||
position (set): A set containing x (row index) and y (column index) as integers.
|
position (set): A set containing x (row index) and y (column index) as integers.
|
||||||
direction (str, optional): The direction to check.
|
direction (str, optional): The direction to check. Defaults to None.
|
||||||
Options: 'up', 'down', 'left', 'right',
|
|
||||||
'up-left', 'up-right', 'down-left', 'down-right'.
|
|
||||||
length (int, optional): The number of steps to check in the given direction. Default is 1.
|
length (int, optional): The number of steps to check in the given direction. Default is 1.
|
||||||
|
type (str, optional): The type of result to return ('list' or 'str'). Defaults to None.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: A list of values in the grid for the specified direction and length.
|
list or str: A list or string of values in the specified direction, or a single value.
|
||||||
Returns an empty list if any position is out of bounds.
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If direction is invalid or position is not a set of two integers.
|
||||||
|
TypeError: If grid is not a list of lists.
|
||||||
"""
|
"""
|
||||||
# Ensure the position is a set of two integers
|
if not all(isinstance(row, list) for row in grid):
|
||||||
|
raise TypeError("Grid must be a list of lists.")
|
||||||
|
|
||||||
|
# Ensure position is a set of two integers
|
||||||
if len(position) != 2 or not all(isinstance(coord, int) for coord in position):
|
if len(position) != 2 or not all(isinstance(coord, int) for coord in position):
|
||||||
raise ValueError("Position must be a set containing two integers (x, y).")
|
raise ValueError("Position must be a set containing two integers (x, y).")
|
||||||
|
|
||||||
@ -168,16 +371,15 @@ def get_value_in_direction(grid, position, direction=None,length=1,type:str=None
|
|||||||
values = []
|
values = []
|
||||||
|
|
||||||
if length == 1:
|
if length == 1:
|
||||||
# Check for out-of-bounds, considering varying row lengths
|
# Check for out-of-bounds
|
||||||
if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]):
|
if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]):
|
||||||
return grid[new_x][new_y]
|
return grid[new_x][new_y]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
for step in range(length):
|
for step in range(length):
|
||||||
print(step)
|
|
||||||
new_x, new_y = x + step * dx, y + step * dy
|
new_x, new_y = x + step * dx, y + step * dy
|
||||||
# Check for out-of-bounds, considering varying row lengths
|
# Check for out-of-bounds
|
||||||
if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]):
|
if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]):
|
||||||
values.append(grid[new_x][new_y])
|
values.append(grid[new_x][new_y])
|
||||||
else:
|
else:
|
||||||
@ -188,4 +390,3 @@ def get_value_in_direction(grid, position, direction=None,length=1,type:str=None
|
|||||||
return ''.join(values)
|
return ''.join(values)
|
||||||
else:
|
else:
|
||||||
return values
|
return values
|
||||||
|
|
Loading…
Reference in New Issue
Block a user