Skip to content

Instantly share code, notes, and snippets.

@karansag
Last active December 1, 2025 02:15
Show Gist options
  • Select an option

  • Save karansag/87fd712f8168dff444815160aef59b7a to your computer and use it in GitHub Desktop.

Select an option

Save karansag/87fd712f8168dff444815160aef59b7a to your computer and use it in GitHub Desktop.
permutation 2
"""
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