import re,sys def toGrid(input,parser=None): grid = [] if parser: with open(input) as file: for line in file: grid.append(list2int(line.rstrip())) else: with open(input) as file: for line in file: grid.append(list(line.rstrip())) return grid def swap(a:int,b:int,lst:list): """ Swaps two numbers in a list based on their indices. Parameters: lst (list): The list of numbers. index1 (int): The index of the first number. index2 (int): The index of the second number. Returns: list: The list after swapping the two numbers. """ if a < 0 or b < 0 or a >= len(lst) or b >= len(lst): raise IndexError("Index out of range.") lst[a], lst[b] = lst[b], lst[a] return lst def addTuples(x:tuple,y:tuple): return (x[0]+y[0],x[1]+y[1]) def findDupes(input:list): # Returns the indicies of duplicate values in list return [item for item in set(input) if input.count(item) > 1] def lprint(x:str,log:bool): if log: print(x) def expand_grid(grid): num_rows = len(grid) num_cols = len(grid[0]) expanded_grid = [] expanded_grid.append(['.'] * (num_cols + 2)) for row in grid: expanded_grid.append(['.'] + row + ['.']) expanded_grid.append(['.'] * (num_cols + 2)) return expanded_grid def getCenter(grid): return (int(len(grid)/2),int(len(grid[0])/2)) def nprint(grid,cur:set=None,sign:str=None): for idx,i in enumerate(grid): for jdx,j in enumerate(i): if (idx,jdx) == cur: if len(sign) > 1: print(sign[0]+grid[idx][jdx]+sign[1],end='') else: print(sign,end=' ') else: print(grid[idx][jdx],end=' ') print() def list2int(x): return list(map(int, x)) def grid_valid(x,y,grid): rows = len(grid) cols = len(grid[0]) return 0 <= x < rows and 0 <= y < cols def get_re(pattern,str): match = re.match(pattern, str) if match: return match return None def ppprint(x): for idx,i in enumerate(x): for jdx,j in enumerate(i): print(x[idx][jdx],end='') print() 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. If no direction is provided, returns the value at the current position. Parameters: 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. direction (str, optional): The direction to check. 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. Returns: list: A list of values in the grid for the specified direction and length. Returns an empty list if any position is out of bounds. """ # Ensure the position is a set of two integers 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).") x, y = position offsets = { 'up': (-1, 0), 'down': (1, 0), 'left': (0, -1), 'right': (0, 1), 'up-left': (-1, -1), 'up-right': (-1, 1), 'down-left': (1, -1), 'down-right': (1, 1) } # If no direction is given, return the value at the current position if direction is None: if 0 <= x < len(grid) and 0 <= y < len(grid[x]): return grid[x][y] else: return None # Validate direction if direction not in offsets: raise ValueError(f"Invalid direction: {direction}. Choose from {list(offsets.keys())}") dx, dy = offsets[direction] new_x, new_y = x + dx, y + dy values = [] if length == 1: # Check for out-of-bounds, considering varying row lengths if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]): return grid[new_x][new_y] else: return None else: for step in range(length): print(step) new_x, new_y = x + step * dx, y + step * dy # Check for out-of-bounds, considering varying row lengths if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]): values.append(grid[new_x][new_y]) else: return [] # Return empty list if any position is out of bounds if type == 'list': return values elif type == 'str': return ''.join(values) else: return values