split_word_to_int_list = lambda y: [int(w) for w in y]
split_line_to_int_list = lambda y: [int(w) for w in y.split(" ") if w]


def rotate(m, right=True):  # -90
    x = list(zip(*m[::-1]))
    if right:
        return x
    return [list(reversed(y)) for y in x]


def load_matrix_file(name, func=None):
    with open(name, "r") as f:
        my_file = []
        for line in f:
            my_file.append(line.rstrip())
    if func:
        return [func(x) for x in my_file]
    return [split_word_to_int_list(x) for x in my_file]


def get_neighbors(matrix, x, y):
    neighbors = []
    # left
    try:
        if x - 1 >= 0:
            neighbors.append([(x - 1, y), matrix[y][x - 1]])
    except IndexError:
        pass
    # right
    try:
        neighbors.append([(x + 1, y), matrix[y][x + 1]])
    except IndexError:
        pass

    # up
    try:
        if y - 1 >= 0:
            neighbors.append([(x, y - 1), matrix[y - 1][x]])
    except IndexError:
        pass

    # down
    try:
        neighbors.append([(x, y + 1), matrix[y + 1][x]])
    except IndexError:
        pass

    return neighbors


def get_neighbor_coords(matrix, c, r, diagonals=True):
    height = len(matrix)
    width = len(matrix[0])
    if diagonals:
        coords = (
            (-1, -1), (0, -1), (1, -1),
            (-1, 0), (1, 0),
            (-1, 1), (0, 1), (1, 1),
        )
    else:
        coords = (
            (0, -1),
            (-1, 0), (1, 0),
            (0, 1),
        )
    neighbors = []

    for _c, _r in coords:
        try:
            value = matrix[r + _r][c + _c]  # Try to get a value error
            if (r+_r>=0 and c+_c >= 0):
                neighbors.append(
                    [{"c": c + _c, "r": r + _r}, value]
                )  # woo, no error, this coord is valid
        except IndexError:
            pass  # okay we out of bounds boizzzz
    return neighbors


def get_column(matrix, col):
    pass


def matrix_of_size(width, height):
    return [[0] * width for x in range(height)]


def get_size(matrix):
    height = len(matrix)
    width = len(matrix[0])
    return height, width


def pmx(*matrices, _or='.', pad=True, space=True):
    if len(matrices) > 1:
        matrices = list(zip(*matrices))
        for row in matrices:
            r = []
            for col in row:
                r.append("".join([f"{int(x)or _or}".rjust(3) for x in col]))
            print(" ".join(r))
    else:
        for row in matrices:
            for c in row:
                if pad:
                    f = lambda x: f"{int(x)or _or}".rjust(2)
                    if space:
                        f = lambda x: f"{int(x)or _or}".rjust(3)
                else:
                    f = lambda x: f"{int(x)or _or}"
                    if space:
                        f = lambda x: f"{int(x)or _or} "
                print("".join([f(x) for x in c]))

def ppmx(*matrices, _or=".", pad=True, space=True):
    if len(matrices) > 1:
        matrices = list(zip(*matrices))
        for row in matrices:
            r = []
            for col in row:
                r.append("".join([f"{x or '.'}".rjust(3) for x in col]))
            print(" ".join(r))
    else:
        for row in matrices:
            for c in row:
                if pad:
                    f = lambda x: f"{x or '.'}".rjust(2)
                    if space:
                        f = lambda x: f"{x or '.'}".rjust(3)
                else:
                    f = lambda x: f"{x or '.'}"
                    if space:
                        f = lambda x: f"{x or '.'} "
                print("".join([f(x) for x in c]))

def p(*matrices):
    pmx(*matrices, _or=" ", pad=False, space=False)
