def part_2(path: Path) -> int: mat = Mat(read_file_to_int_matrix(path)) # A mapping of cell (tuple row, col) to basin number cell_to_basin = {} # A mapping of basin number to a list of cells in that basin basin_dict = {} # Put each cell in it's own basin basin_count = 0 for row in range(mat.row_count): for col in range(mat.col_count): if mat.get_cell(row, col) == 9: continue cell_to_basin[(row, col)] = basin_count basin_dict[basin_count] = [(row, col)] basin_count += 1 def check_and_combine_basins(cell1, cell2): # If cell 1 and cell 2 are in different basins if cell2 in cell_to_basin and cell_to_basin[cell1] != cell_to_basin[ cell2]: cell1_basin_num = cell_to_basin[cell1] cell2_basin_num = cell_to_basin[cell2] # Add everything in basin 2 into basin 1 basin1 = basin_dict[cell1_basin_num] basin2 = basin_dict[cell2_basin_num] basin1.extend(basin2) # Update cell_to_basin that everything that was in basin 2 is now in basin 1 for cell_in_basin2 in basin2: cell_to_basin[cell_in_basin2] = cell1_basin_num # Remove basin 2 basin_dict.pop(cell2_basin_num) return True return False # Keep combining until there're no more to combine combined_some = True while combined_some: combined_some = False for row in range(mat.row_count): for col in range(mat.col_count): if mat.get_cell(row, col) == 9: continue for neighbor_row, neighbor_col in mat.cardinal_neighbors( row, col): combined_some = check_and_combine_basins( (row, col), (neighbor_row, neighbor_col)) or combined_some basins = list(basin_dict.values()) basins.sort(key=len, reverse=True) return len(basins[0]) * len(basins[1]) * len(basins[2])
def flash(octos: Mat, row: int, col: int, flashed: Set) -> None: flashed.add((row, col)) for neighbor_row, neighbor_col in octos.all_neighbors(row, col): new_val = octos.add(neighbor_row, neighbor_col, 1) if new_val == 10: flash(octos, neighbor_row, neighbor_col, flashed)
def part_2(path: Path) -> int: start = time.time() mat = read_file_to_int_matrix(path) mat = Mat(extend_mat(mat)) target = (mat.row_count - 1, mat.col_count - 1) answer = sum( mat.get_cell(*cell) for cell in dijkstra(mat, (0, 0), target)[1:]) print(time.time() - start) return answer
def process_step(octos: Mat) -> int: flashed = set() for row in range(octos.row_count): for col in range(octos.col_count): new_value = octos.add(row, col, 1) if new_value == 10: flash(octos, row, col, flashed) for row, col in flashed: octos.set_cell(row, col, 0) return len(flashed)
def dijkstra(mat: Mat, source: Tuple[int, int], target: Tuple[int, int]) -> List[Tuple[int, int]]: distances = {} prev = {} q = [] for row in range(mat.row_count): for col in range(mat.col_count): prev[(row, col)] = None if (row, col) != source: distances[(row, col)] = float('inf') q.append((float('inf'), (row, col))) else: distances[source] = 0 q.append((0, (row, col))) q.sort() seen = set() q_place = 0 while q_place != len(q): _, u = q[q_place] seen.add(u) q_place += 1 if u == target: break for v in mat.cardinal_neighbors(*u): if v in seen: continue alt = distances[u] + mat.get_cell(*v) if alt < distances[v]: distances[v] = alt prev[v] = u # Update v in q, maintaining sorted bisect.insort(q, (alt, v)) s = [] u = target if prev[u] or u == source: while u: s.append(u) u = prev[u] return s[::-1]
def part_1(path: Path) -> int: mat = Mat(read_file_to_int_matrix(path)) def is_low_point(): cell_val = mat.get_cell(row, col) for neighbor_row, neighbor_col in mat.cardinal_neighbors(row, col): if cell_val >= mat.get_cell(neighbor_row, neighbor_col): return False return True risk_total = 0 for row in range(mat.row_count): for col in range(mat.col_count): if is_low_point(): risk_total += mat.get_cell(row, col) + 1 return risk_total
def part_2(path: Path) -> int: octos = Mat(read_file_to_int_matrix(path)) total = octos.row_count * octos.col_count step_num = 1 while process_step(octos) != total: step_num += 1 return step_num
def load_zachary_karate_club(): edges = [] with open("../data/KarateClub.csv", 'r') as csvFile: for row in csvFile: edges.append(tuple(map(int, row.strip().split(";")))) vertices = [] [[vertices.append(x) for x in edge if x not in vertices] for edge in edges] matrixValues = [[is_edge_between(edges, v, rId) for v in range(1, len(vertices) + 1)] for rId in range(1, len(vertices) + 1)] matrix = Mat(matrixValues) return matrix
def main(): edges = [] with open("../data/KarateClub.csv", 'r') as csvFile: for row in csvFile: edges.append(tuple(map(int, row.strip().split(";")))) #print(edges) vertices = [] [[vertices.append(x) for x in edge if x not in vertices] for edge in edges] matrixValues = [[ is_edge_between(edges, v, rId) for v in range(1, len(vertices) + 1) ] for rId in range(1, len(vertices) + 1)] matrix = Mat(matrixValues) matrix = matrix.set_inf_where_no_edge() distanceMatrix = matrix.get_floyd_distance_matrix() # print(matrix) closenessCentralityVector = distanceMatrix.closeness_centrality_for_vertices( ) print(closenessCentralityVector)
def generate_random_network(vertexCount, edgeProbability): population = [0, 1] weights = [(1 - edgeProbability), edgeProbability] matrixValues = [[inf for c in range(vertexCount)] for r in range(vertexCount)] for r in range(vertexCount): for c in range(r, vertexCount): if r == c: matrixValues[r][c] = 0 elif matrixValues[r][c] == inf: edgeVal = choices(population, weights)[0] matrixValues[r][c] = edgeVal matrixValues[c][r] = edgeVal result = Mat(matrixValues) return result
def load_bipartite(): lines = [] # with open("D:/gitrepos/dataAnalysisCourse/data/actorsAndMovies.txt") as dataset: with open("../data/actorsAndMovies.txt") as dataset: lines = dataset.readlines() labels = {} edges = [] maxVertex = 0 readingEdges = False for line in lines: line = line.strip() if line == "EDGES": readingEdges = True continue lineValues = line.split(";") if readingEdges: a = int(lineValues[0]) - 1 b = int(lineValues[1]) - 1 if a > maxVertex: maxVertex = a if b > maxVertex: maxVertex = b edges.append((a, b)) else: labels[int(lineValues[0])] = lineValues[1].replace('"', "") rowCount = 10 values = [[0 for c in range(len(labels))] for r in range(rowCount)] for edge in edges: (a, b) = edge values[a][b] = 1 bm = Mat(values, tuple(labels.values())) return bm
def generate_small_world_network(startingSize, m, t): startingSize = 3 resultSize = 3 + t currentSize = startingSize initial = Mat([[0, 1, 1], [1, 0, 1], [1, 1, 0]]) vertexList = [0, 0, 1, 1, 2, 2] resultMatrix = Mat([[0 for c in range(resultSize)] for r in range(resultSize)]) resultMatrix.insert(initial) for step in range(t): newVertexIndex = startingSize + step vertexListSize = float(len(vertexList)) population = range(currentSize) weights = [(float(vertexList.count(v)) / vertexListSize) for v in population] neighbours = [] for mStep in range(m): neighbour = choices(population, weights)[0] while neighbour in neighbours: neighbour = choices(population, weights)[0] neighbours.append(neighbour) assert len(neighbours) == m vertexList.append(newVertexIndex) vertexList.append(newVertexIndex) for n in neighbours: vertexList.append(n) resultMatrix.values[newVertexIndex][n] = 1 resultMatrix.values[n][newVertexIndex] = 1 currentSize += 1 #print("Current size: " + str(currentSize)) return resultMatrix
def part_1(path: Path) -> int: mat = Mat(read_file_to_int_matrix(path)) target = (mat.row_count - 1, mat.col_count - 1) return sum( mat.get_cell(*cell) for cell in dijkstra(mat, (0, 0), target)[1:])
def part_1(path: Path) -> int: octos = Mat(read_file_to_int_matrix(path)) return sum(process_step(octos) for _ in range(100))