Last active
December 1, 2025 02:15
-
-
Save karansag/87fd712f8168dff444815160aef59b7a to your computer and use it in GitHub Desktop.
permutation 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Analyze permutations by counting elements in correct positions (fixed points). | |
| """ | |
| import argparse | |
| from itertools import permutations | |
| from collections import defaultdict | |
| from math import factorial | |
| def count_fixed_points(perm: tuple[int, ...]) -> int: | |
| """ | |
| Count how many elements are in their correct position (1-indexed). | |
| Args: | |
| perm: A permutation tuple (e.g., (1, 3, 2, 4)) | |
| Returns: | |
| Number of elements in correct position | |
| """ | |
| return sum(1 for i, val in enumerate(perm, start=1) if i == val) | |
| def analyze_permutations(n: int) -> dict[int, int]: | |
| """ | |
| Enumerate all permutations of integers 1 to n and count how many | |
| permutations have exactly k elements in correct positions. | |
| Args: | |
| n: The size of permutations to analyze | |
| Returns: | |
| Dictionary mapping number_of_fixed_points -> count | |
| """ | |
| counts = defaultdict(int) | |
| for perm in permutations(range(1, n + 1)): | |
| fixed = count_fixed_points(perm) | |
| counts[fixed] += 1 | |
| return dict(counts) | |
| def generate_table(m: int, include_percent: bool = False) -> None: | |
| """ | |
| Generate a table showing permutation fixed point statistics for n = 1 to m. | |
| Each row represents a value of n, and columns show how many permutations | |
| have exactly k elements in correct positions. | |
| Args: | |
| m: Maximum n value to analyze | |
| include_percent: If True, show percentages alongside counts | |
| """ | |
| # Collect all results | |
| results = {} | |
| max_cols = 0 | |
| for n in range(1, m + 1): | |
| results[n] = analyze_permutations(n) | |
| max_cols = max(max_cols, max(results[n].keys()) + 1) | |
| # Determine column width based on whether we're showing percentages | |
| col_width = 13 if include_percent else 6 | |
| # Print header | |
| header = "n |" + "".join(f" {k:>{col_width}}" for k in range(max_cols)) | |
| print(header) | |
| print("-" * len(header)) | |
| # Print rows | |
| for n in range(1, m + 1): | |
| row = f"{n} |" | |
| total = factorial(n) | |
| for k in range(max_cols): | |
| if k > n: | |
| # Invalid: can't have more fixed points than elements | |
| row += f" {'-':>{col_width}}" | |
| else: | |
| count = results[n].get(k, 0) | |
| if include_percent: | |
| pct = (count / total) * 100 | |
| row += f" {count:>6}({pct:>5.2f}%)" | |
| else: | |
| row += f" {count:>{col_width}}" | |
| print(row) | |
| def print_zero_fixed_table(m: int, include_percent: bool) -> None: | |
| """ | |
| Render a narrow table showing only the permutations with zero fixed points. | |
| """ | |
| zero_stats = [] | |
| max_count_width = 1 | |
| for n in range(1, m + 1): | |
| result = analyze_permutations(n) | |
| zero_count = result.get(0, 0) | |
| total = factorial(n) | |
| pct = (zero_count / total) * 100 | |
| zero_stats.append((n, zero_count, pct)) | |
| max_count_width = max(max_count_width, len(str(zero_count))) | |
| n_width = len(str(m)) | |
| pct_label = "percent" | |
| header = f"{'n':>{n_width}} | {'zero':>{max_count_width}}" | |
| if include_percent: | |
| header += f" | {pct_label}" | |
| print(header) | |
| print("-" * len(header)) | |
| for n, zero_count, pct in zero_stats: | |
| row = f"{n:>{n_width}} | {zero_count:>{max_count_width}}" | |
| if include_percent: | |
| row += f" | {pct:>7.2f}%" | |
| print(row) | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser( | |
| description="Analyze permutations by counting elements in correct positions" | |
| ) | |
| parser.add_argument( | |
| "--include-percent", | |
| action="store_true", | |
| help="Include percentages in the output table", | |
| ) | |
| parser.add_argument( | |
| "-m", | |
| "--max", | |
| type=int, | |
| default=8, | |
| help="Maximum value of n to analyze (default: 8)", | |
| ) | |
| parser.add_argument( | |
| "--example", | |
| type=int, | |
| help="Show detailed example for specific n value", | |
| ) | |
| parser.add_argument( | |
| "--zero-fixed-only", | |
| action="store_true", | |
| help="Only report how many permutations have zero fixed points for n = 1..m", | |
| ) | |
| args = parser.parse_args() | |
| print("Permutation Fixed Point Analysis") | |
| print("=" * 60) | |
| print() | |
| # Show example if requested | |
| if args.example: | |
| n = args.example | |
| print(f"Analysis for n={n}:") | |
| result = analyze_permutations(n) | |
| total = factorial(n) | |
| for fixed_points, count in sorted(result.items()): | |
| pct = (count / total) * 100 | |
| print( | |
| f" {fixed_points} elements in correct position: {count} permutations ({pct:.2f}%)" | |
| ) | |
| print() | |
| if args.zero_fixed_only: | |
| print(f"Zero fixed point permutations for n = 1 to {args.max}:") | |
| print() | |
| print_zero_fixed_table(args.max, args.include_percent) | |
| else: | |
| # Generate table | |
| print(f"Table for n = 1 to {args.max}:") | |
| if args.include_percent: | |
| print("(Each cell shows count(percentage) of permutations with k fixed points)") | |
| else: | |
| print("(Each cell shows count of permutations with k fixed points)") | |
| print() | |
| generate_table(args.max, args.include_percent) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment