diff --git a/backtracking/minimax.py b/backtracking/minimax.py index 4eef90b75483..7e5e6330a5a8 100644 --- a/backtracking/minimax.py +++ b/backtracking/minimax.py @@ -57,6 +57,10 @@ def minimax( if len(scores) == 0: raise ValueError("Scores cannot be empty") + # Validate that scores length is a power of 2 + if len(scores) & (len(scores) - 1) != 0: + raise ValueError("Number of scores must be a power of 2") + # Base case: If the current depth equals the height of the tree, # return the score of the current node. if depth == height: diff --git a/graphs/page_rank.py b/graphs/page_rank.py index c0ce3a94c76b..2714b0b554b2 100644 --- a/graphs/page_rank.py +++ b/graphs/page_rank.py @@ -32,21 +32,45 @@ def __repr__(self): def page_rank(nodes, limit=3, d=0.85): + """ + Calculate PageRank for a directed graph. + + >>> nodes = [Node('A'), Node('B'), Node('C')] + >>> nodes[0].add_outbound('B') + >>> nodes[0].add_outbound('C') + >>> nodes[1].add_outbound('C') + >>> nodes[2].add_outbound('A') + >>> ranks = page_rank(nodes, limit=100) + >>> round(ranks['A'], 4) + 0.15 + >>> round(ranks['B'], 4) + 0.15 + >>> round(ranks['C'], 4) + 0.15 + """ + n = len(nodes) ranks = {} for node in nodes: - ranks[node.name] = 1 + ranks[node.name] = 1 / n # Initialize to 1/n, not 1 outbounds = {} for node in nodes: outbounds[node.name] = len(node.outbound) for i in range(limit): - print(f"======= Iteration {i + 1} =======") - for _, node in enumerate(nodes): - ranks[node.name] = (1 - d) + d * sum( - ranks[ib] / outbounds[ib] for ib in node.inbound - ) - print(ranks) + # Handle dangling nodes (nodes with no outbound links) + for node in nodes: + outbound_count = outbounds[node.name] + if outbound_count == 0: + ranks[node.name] = (1 - d) + d * sum( + ranks[ib] for ib in node.inbound + ) / n + else: + ranks[node.name] = (1 - d) + d * sum( + ranks[ib] / outbounds[ib] for ib in node.inbound + ) + + return ranks def main():