#!/usr/bin/env python3 """ Script to read and parse Powerball numbers from a CSV file with advanced pattern detection. """ import csv from datetime import datetime, timedelta from pathlib import Path from typing import List, Dict, Tuple, Optional, Set from collections import Counter, defaultdict from itertools import combinations def read_powerball_csv(filepath: str) -> List[Dict]: """ Read a CSV file containing Powerball numbers. Expected CSV format: Draw Date,Winning Numbers,Multiplier 09/26/2020,11 21 27 36 62 24,3 Args: filepath: Path to the CSV file Returns: List of dictionaries containing parsed powerball data """ powerball_data = [] try: with open(filepath, 'r', encoding='utf-8') as csvfile: reader = csv.DictReader(csvfile) for row_num, row in enumerate(reader, start=2): # start=2 because row 1 is header try: # Skip empty rows if not any(row.values()): continue # Parse the row draw_date = datetime.strptime(row['Draw Date'].strip(), '%m/%d/%Y') # Parse winning numbers - filter out empty strings numbers_str = row['Winning Numbers'].strip() winning_numbers = [int(n) for n in numbers_str.split() if n.strip()] multiplier = int(row['Multiplier'].strip()) powerball_data.append({ 'draw_date': draw_date, 'date_str': draw_date.strftime('%Y-%m-%d'), 'winning_numbers': winning_numbers, 'multiplier': multiplier }) except ValueError as e: print(f"Warning: Skipping row {row_num} due to error: {e}") print(f" Row data: {row}") continue except FileNotFoundError: print(f"Error: File '{filepath}' not found.") return [] except Exception as e: print(f"Error: Failed to read CSV file - {e}") return [] return powerball_data def display_powerball_data(data: List[Dict]) -> None: """ Display powerball data in a formatted table. Args: data: List of powerball data dictionaries """ if not data: print("No data to display.") return print(f"{'Draw Date':<12} {'Winning Numbers':<30} {'Multiplier':<10}") print("-" * 52) for entry in data: numbers_str = ' '.join(map(str, entry['winning_numbers'])) print(f"{entry['date_str']:<12} {numbers_str:<30} {entry['multiplier']:<10}") def _get_unweighted_top_numbers(draws: List[Dict]) -> Tuple[List[int], Optional[int]]: """Return top 5 white balls and top Powerball from a draw list.""" if not draws: return [], None white_counter = Counter() powerball_counter = Counter() for entry in draws: numbers = entry['winning_numbers'] for number in numbers[:5]: white_counter[number] += 1 if len(numbers) >= 6: powerball_counter[numbers[5]] += 1 top_white = [number for number, _ in white_counter.most_common(5)] top_powerball = powerball_counter.most_common(1)[0][0] if powerball_counter else None return top_white, top_powerball def _get_recency_weighted_top_numbers(draws: List[Dict]) -> Tuple[List[int], Optional[int]]: """Return top numbers weighted so newer draws contribute more.""" if not draws: return [], None sorted_draws = sorted(draws, key=lambda x: x['draw_date']) total_draws = len(sorted_draws) white_scores: Dict[int, float] = defaultdict(float) powerball_scores: Dict[int, float] = defaultdict(float) for index, entry in enumerate(sorted_draws, start=1): weight = index / total_draws numbers = entry['winning_numbers'] for number in numbers[:5]: white_scores[number] += weight if len(numbers) >= 6: powerball_scores[numbers[5]] += weight top_white = [number for number, _ in sorted(white_scores.items(), key=lambda x: x[1], reverse=True)[:5]] top_powerball = max(powerball_scores.items(), key=lambda x: x[1])[0] if powerball_scores else None return top_white, top_powerball def _get_aggressive_recency_weighted_top_numbers(draws: List[Dict]) -> Tuple[List[int], Optional[int]]: """Return top numbers with an aggressive recency curve (cubic weighting).""" if not draws: return [], None sorted_draws = sorted(draws, key=lambda x: x['draw_date']) total_draws = len(sorted_draws) white_scores: Dict[int, float] = defaultdict(float) powerball_scores: Dict[int, float] = defaultdict(float) for index, entry in enumerate(sorted_draws, start=1): normalized_position = index / total_draws weight = normalized_position ** 3 numbers = entry['winning_numbers'] for number in numbers[:5]: white_scores[number] += weight if len(numbers) >= 6: powerball_scores[numbers[5]] += weight top_white = [number for number, _ in sorted(white_scores.items(), key=lambda x: x[1], reverse=True)[:5]] top_powerball = max(powerball_scores.items(), key=lambda x: x[1])[0] if powerball_scores else None return top_white, top_powerball def analyze_most_frequent_numbers(data: List[Dict]) -> Dict: """ Analyze and display the most frequent number in each slot position. Args: data: List of powerball data dictionaries """ if not data: print("No data to analyze.") return {} # Initialize lists to hold numbers for each position num_positions = len(data[0]['winning_numbers']) position_numbers = [[] for _ in range(num_positions)] # Collect all numbers for each position for entry in data: for position, number in enumerate(entry['winning_numbers']): position_numbers[position].append(number) # Find most common number in each position print("\n" + "=" * 60) print("Most Frequent Numbers by Slot Position") print("=" * 60) most_frequent = [] for position, numbers in enumerate(position_numbers, start=1): counter = Counter(numbers) most_common_num, frequency = counter.most_common(1)[0] most_frequent.append(most_common_num) percentage = (frequency / len(numbers)) * 100 print(f"Position {position}: {most_common_num:<3} (appears {frequency} times, {percentage:.1f}%)") print("-" * 60) print(f"Most frequent numbers combined: {' '.join(map(str, most_frequent))}") # Analyze most frequent number across first 5 positions combined print("\n" + "=" * 60) print("Additional Analysis") print("=" * 60) # Combine all numbers from positions 1-5 first_five_combined = [] for i in range(min(5, num_positions)): first_five_combined.extend(position_numbers[i]) top_five_numbers = [] top_ten_numbers = [] if first_five_combined: counter_first_five = Counter(first_five_combined) top_five_numbers = counter_first_five.most_common(5) top_ten_numbers = counter_first_five.most_common(10) print("Top 5 most drawn numbers in first 5 positions combined:") for rank, (number, frequency) in enumerate(top_five_numbers, start=1): percentage = (frequency / len(first_five_combined)) * 100 print(f" {rank}. {number:<3} (appears {frequency} times, {percentage:.1f}%)") # Analyze the sixth position (Powerball) powerball_ranked = [] most_common_sixth = None if num_positions >= 6: sixth_position_numbers = position_numbers[5] counter_sixth = Counter(sixth_position_numbers) powerball_ranked = counter_sixth.most_common(5) most_common_sixth, freq_sixth = counter_sixth.most_common(1)[0] percentage_sixth = (freq_sixth / len(sixth_position_numbers)) * 100 print(f"\nMost drawn number in position 6 (Powerball): {most_common_sixth} (appears {freq_sixth} times, {percentage_sixth:.1f}%)") # Third strategy: most frequent numbers from the most recent 104 draws sorted_by_date = sorted(data, key=lambda x: x['draw_date']) recent_104_draws = sorted_by_date[-104:] recent_104_top_five, recent_104_powerball = _get_unweighted_top_numbers(recent_104_draws) # Fourth strategy: weighted-by-recency across all draws weighted_top_five, weighted_powerball = _get_recency_weighted_top_numbers(data) # Fifth strategy: aggressive weighted-by-recency across all draws aggressive_weighted_top_five, aggressive_weighted_powerball = _get_aggressive_recency_weighted_top_numbers(data) # Return statistics for prediction return { 'top_five_combined': [num for num, freq in top_five_numbers] if first_five_combined else [], 'top_ten_combined': [num for num, freq in top_ten_numbers], 'most_common_powerball': most_common_sixth, 'powerball_ranked': [num for num, freq in powerball_ranked], 'recent_104_top_five': recent_104_top_five, 'recent_104_powerball': recent_104_powerball, 'weighted_top_five': weighted_top_five, 'weighted_powerball': weighted_powerball, 'aggressive_weighted_top_five': aggressive_weighted_top_five, 'aggressive_weighted_powerball': aggressive_weighted_powerball } def generate_suggested_combination(stats: dict) -> None: """ Generate a suggested combination based on statistical analysis. Args: stats: Dictionary containing statistical analysis results """ print("\n" + "=" * 60) print("Suggested Combination Based on Statistical Analysis") print("=" * 60) print("\n*** DISCLAIMER: This is purely statistical analysis.") print("Past results do NOT predict future outcomes.") print("Each draw is random and independent.\n") top_five = stats['top_five_combined'] top_ten = stats.get('top_ten_combined', []) powerball = stats['most_common_powerball'] ranked_powerballs = stats.get('powerball_ranked', []) recent_104_top_five = stats.get('recent_104_top_five', []) recent_104_powerball = stats.get('recent_104_powerball') weighted_top_five = stats.get('weighted_top_five', []) weighted_powerball = stats.get('weighted_powerball') aggressive_weighted_top_five = stats.get('aggressive_weighted_top_five', []) aggressive_weighted_powerball = stats.get('aggressive_weighted_powerball') if len(top_five) >= 5 and powerball: # Use the top 5 most frequent numbers from positions 1-5 primary_numbers = sorted(top_five[:5]) primary_powerball = powerball # Build a secondary set from the next-most-frequent historical numbers. secondary_pool = top_ten[5:10] if len(secondary_pool) < 5: secondary_pool = top_ten[:5] secondary_numbers = sorted(secondary_pool[:5]) secondary_powerball = ranked_powerballs[1] if len(ranked_powerballs) > 1 else primary_powerball third_numbers = sorted(recent_104_top_five[:5]) if len(recent_104_top_five) >= 5 else [] third_powerball = recent_104_powerball fourth_numbers = sorted(weighted_top_five[:5]) if len(weighted_top_five) >= 5 else [] fourth_powerball = weighted_powerball fifth_numbers = sorted(aggressive_weighted_top_five[:5]) if len(aggressive_weighted_top_five) >= 5 else [] fifth_powerball = aggressive_weighted_powerball print("Primary set (most frequent):") print(f" White balls: {' '.join(map(str, primary_numbers))}") print(f" Powerball: {primary_powerball}") print("\nSecondary set (next-most frequent):") print(f" White balls: {' '.join(map(str, secondary_numbers))}") print(f" Powerball: {secondary_powerball}") if third_numbers and third_powerball: print("\nThird set (most frequent in recent 104 draws):") print(f" White balls: {' '.join(map(str, third_numbers))}") print(f" Powerball: {third_powerball}") if fourth_numbers and fourth_powerball: print("\nFourth set (weighted by recency):") print(f" White balls: {' '.join(map(str, fourth_numbers))}") print(f" Powerball: {fourth_powerball}") if fifth_numbers and fifth_powerball: print("\nFifth set (aggressive recency weighting):") print(f" White balls: {' '.join(map(str, fifth_numbers))}") print(f" Powerball: {fifth_powerball}") print() print(f"Primary combination: {' '.join(map(str, primary_numbers))} + {primary_powerball}") print(f"Secondary combination: {' '.join(map(str, secondary_numbers))} + {secondary_powerball}") if third_numbers and third_powerball: print(f"Third combination: {' '.join(map(str, third_numbers))} + {third_powerball}") if fourth_numbers and fourth_powerball: print(f"Fourth combination: {' '.join(map(str, fourth_numbers))} + {fourth_powerball}") if fifth_numbers and fifth_powerball: print(f"Fifth combination: {' '.join(map(str, fifth_numbers))} + {fifth_powerball}") print() print("These combinations are based on:") print(" • The 5 most frequently drawn numbers across all white ball positions") print(f" • The most frequently drawn Powerball number ({primary_powerball})") print(" • A secondary set from the next-most-frequent white ball and Powerball values") print(" • Recent-window frequency (last 104 draws)") print(" • Recency-weighted scoring where newer draws count more") print(" • Aggressive recency weighting using a cubic curve") else: print("Insufficient data to generate a suggestion.") def detect_consecutive_patterns(data: List[Dict]) -> Dict: """ Analyze frequency of consecutive numbers in draws. Args: data: List of powerball data dictionaries Returns: Dictionary with consecutive number statistics """ consecutive_counts = Counter() total_draws = len(data) draws_with_consecutives = 0 consecutive_pairs = [] for entry in data: white_balls = sorted(entry['winning_numbers'][:5]) has_consecutive = False for i in range(len(white_balls) - 1): if white_balls[i+1] - white_balls[i] == 1: consecutive_counts[f"{white_balls[i]}-{white_balls[i+1]}"] += 1 consecutive_pairs.append((white_balls[i], white_balls[i+1])) has_consecutive = True if has_consecutive: draws_with_consecutives += 1 print("\n" + "=" * 60) print("PATTERN: Consecutive Numbers Analysis") print("=" * 60) percentage = (draws_with_consecutives / total_draws) * 100 if total_draws > 0 else 0 print(f"Draws with consecutive numbers: {draws_with_consecutives}/{total_draws} ({percentage:.1f}%)") if consecutive_counts: print("\nMost common consecutive pairs:") for pair, count in consecutive_counts.most_common(10): pair_pct = (count / total_draws) * 100 print(f" {pair}: {count} times ({pair_pct:.1f}%)") return { 'draws_with_consecutives': draws_with_consecutives, 'percentage': percentage, 'common_pairs': dict(consecutive_counts.most_common(10)) } def detect_odd_even_patterns(data: List[Dict]) -> Dict: """ Analyze odd/even distribution patterns. Args: data: List of powerball data dictionaries Returns: Dictionary with odd/even distribution statistics """ distribution = Counter() for entry in data: white_balls = entry['winning_numbers'][:5] odd_count = sum(1 for num in white_balls if num % 2 == 1) even_count = 5 - odd_count distribution[f"{odd_count}odd-{even_count}even"] += 1 print("\n" + "=" * 60) print("PATTERN: Odd/Even Distribution") print("=" * 60) print("Distribution of odd vs even numbers:") total = sum(distribution.values()) for pattern, count in sorted(distribution.items(), key=lambda x: x[1], reverse=True): percentage = (count / total) * 100 print(f" {pattern}: {count} times ({percentage:.1f}%)") return {'distribution': dict(distribution)} def detect_high_low_patterns(data: List[Dict]) -> Dict: """ Analyze high/low number distribution (1-35 = low, 36-69 = high). Args: data: List of powerball data dictionaries Returns: Dictionary with high/low distribution statistics """ distribution = Counter() SPLIT_POINT = 35 for entry in data: white_balls = entry['winning_numbers'][:5] low_count = sum(1 for num in white_balls if num <= SPLIT_POINT) high_count = 5 - low_count distribution[f"{low_count}low-{high_count}high"] += 1 print("\n" + "=" * 60) print(f"PATTERN: High/Low Distribution (Low: 1-{SPLIT_POINT}, High: {SPLIT_POINT+1}-69)") print("=" * 60) print("Distribution of low vs high numbers:") total = sum(distribution.values()) for pattern, count in sorted(distribution.items(), key=lambda x: x[1], reverse=True): percentage = (count / total) * 100 print(f" {pattern}: {count} times ({percentage:.1f}%)") return {'distribution': dict(distribution)} def detect_sum_patterns(data: List[Dict]) -> Dict: """ Analyze the sum of winning numbers. Args: data: List of powerball data dictionaries Returns: Dictionary with sum statistics """ sums = [] for entry in data: white_balls = entry['winning_numbers'][:5] total = sum(white_balls) sums.append(total) print("\n" + "=" * 60) print("PATTERN: Sum of Winning Numbers") print("=" * 60) avg_sum = sum(sums) / len(sums) if sums else 0 min_sum = min(sums) if sums else 0 max_sum = max(sums) if sums else 0 print(f"Average sum: {avg_sum:.1f}") print(f"Range: {min_sum} - {max_sum}") # Create buckets for sum ranges buckets = Counter() for s in sums: bucket = (s // 25) * 25 # Group into 25-number ranges buckets[f"{bucket}-{bucket+24}"] += 1 print("\nSum distribution by range:") for range_str, count in sorted(buckets.items(), key=lambda x: int(x[0].split('-')[0])): percentage = (count / len(sums)) * 100 print(f" {range_str}: {count} times ({percentage:.1f}%)") return { 'average': avg_sum, 'min': min_sum, 'max': max_sum, 'buckets': dict(buckets) } def detect_gap_patterns(data: List[Dict]) -> Dict: """ Analyze gaps (spacing) between consecutive numbers when sorted. Args: data: List of powerball data dictionaries Returns: Dictionary with gap statistics """ all_gaps = [] for entry in data: white_balls = sorted(entry['winning_numbers'][:5]) gaps = [white_balls[i+1] - white_balls[i] for i in range(len(white_balls) - 1)] all_gaps.extend(gaps) print("\n" + "=" * 60) print("PATTERN: Gap Analysis (spacing between sorted numbers)") print("=" * 60) avg_gap = sum(all_gaps) / len(all_gaps) if all_gaps else 0 gap_counter = Counter(all_gaps) print(f"Average gap: {avg_gap:.1f}") print("\nMost common gap sizes:") for gap, count in gap_counter.most_common(10): percentage = (count / len(all_gaps)) * 100 print(f" Gap of {gap}: {count} times ({percentage:.1f}%)") return { 'average_gap': avg_gap, 'gap_distribution': dict(gap_counter.most_common(15)) } def detect_hot_cold_numbers(data: List[Dict], recent_draws: int = 20) -> Dict: """ Identify hot (frequently appearing) and cold (rarely appearing) numbers in recent draws. Args: data: List of powerball data dictionaries recent_draws: Number of recent draws to analyze Returns: Dictionary with hot/cold number analysis """ sorted_data = sorted(data, key=lambda x: x['draw_date']) recent = sorted_data[-recent_draws:] if len(sorted_data) >= recent_draws else sorted_data white_counter = Counter() powerball_counter = Counter() for entry in recent: for num in entry['winning_numbers'][:5]: white_counter[num] += 1 if len(entry['winning_numbers']) >= 6: powerball_counter[entry['winning_numbers'][5]] += 1 print("\n" + "=" * 60) print(f"PATTERN: Hot & Cold Numbers (Last {len(recent)} draws)") print("=" * 60) print(f"\nHottest white balls (appeared most in last {len(recent)} draws):") for num, count in white_counter.most_common(10): print(f" {num}: {count} times") print(f"\nHottest Powerballs:") for num, count in powerball_counter.most_common(5): print(f" {num}: {count} times") # Cold numbers - all possible white ball numbers (1-69) that appeared least all_white_numbers = set(range(1, 70)) appeared = set(white_counter.keys()) not_appeared = all_white_numbers - appeared print(f"\nColdest white balls (appeared least or not at all):") cold_numbers = sorted( [(num, white_counter.get(num, 0)) for num in all_white_numbers], key=lambda x: (x[1], x[0]) )[:10] for num, count in cold_numbers: if count == 0: print(f" {num}: 0 times (not appeared)") else: print(f" {num}: {count} times") return { 'hot_white': dict(white_counter.most_common(10)), 'hot_powerball': dict(powerball_counter.most_common(5)), 'cold_white': dict(cold_numbers[:10]) } def detect_overdue_numbers(data: List[Dict]) -> Dict: """ Identify numbers that haven't appeared in the longest time. Args: data: List of powerball data dictionaries Returns: Dictionary with overdue number analysis """ sorted_data = sorted(data, key=lambda x: x['draw_date']) # Track last appearance of each number last_seen_white = {} last_seen_powerball = {} for entry in sorted_data: draw_date = entry['draw_date'] for num in entry['winning_numbers'][:5]: last_seen_white[num] = draw_date if len(entry['winning_numbers']) >= 6: last_seen_powerball[entry['winning_numbers'][5]] = draw_date most_recent_draw = sorted_data[-1]['draw_date'] # Calculate days since last appearance overdue_white = {} for num in range(1, 70): # White balls are 1-69 if num in last_seen_white: days_overdue = (most_recent_draw - last_seen_white[num]).days overdue_white[num] = days_overdue else: overdue_white[num] = float('inf') # Never appeared overdue_powerball = {} for num in range(1, 27): # Powerballs are 1-26 if num in last_seen_powerball: days_overdue = (most_recent_draw - last_seen_powerball[num]).days overdue_powerball[num] = days_overdue else: overdue_powerball[num] = float('inf') print("\n" + "=" * 60) print("PATTERN: Overdue Numbers (longest time since last appearance)") print("=" * 60) print("\nMost overdue white balls:") sorted_overdue_white = sorted(overdue_white.items(), key=lambda x: x[1], reverse=True)[:10] for num, days in sorted_overdue_white: if days == float('inf'): print(f" {num}: Never appeared") else: print(f" {num}: {days} days ago") print("\nMost overdue Powerballs:") sorted_overdue_powerball = sorted(overdue_powerball.items(), key=lambda x: x[1], reverse=True)[:5] for num, days in sorted_overdue_powerball: if days == float('inf'): print(f" {num}: Never appeared") else: print(f" {num}: {days} days ago") return { 'overdue_white': dict(sorted_overdue_white), 'overdue_powerball': dict(sorted_overdue_powerball) } def detect_number_pairs(data: List[Dict], top_n: int = 10) -> Dict: """ Identify which number pairs appear together most frequently. Args: data: List of powerball data dictionaries top_n: Number of top pairs to display Returns: Dictionary with pair frequency analysis """ pair_counter = Counter() for entry in data: white_balls = entry['winning_numbers'][:5] # Get all pairs from this draw for pair in combinations(sorted(white_balls), 2): pair_counter[pair] += 1 print("\n" + "=" * 60) print("PATTERN: Number Pair Analysis") print("=" * 60) print(f"\nTop {top_n} most common number pairs:") for (num1, num2), count in pair_counter.most_common(top_n): percentage = (count / len(data)) * 100 print(f" ({num1}, {num2}): appeared together {count} times ({percentage:.1f}%)") return { 'top_pairs': dict(pair_counter.most_common(top_n)) } def detect_decade_distribution(data: List[Dict]) -> Dict: """ Analyze how numbers are distributed across decades (1-9, 10-19, 20-29, etc.). Args: data: List of powerball data dictionaries Returns: Dictionary with decade distribution statistics """ decade_counts = Counter() for entry in data: white_balls = entry['winning_numbers'][:5] for num in white_balls: decade = (num // 10) * 10 decade_label = f"{decade:02d}-{decade+9:02d}" if decade < 60 else "60-69" decade_counts[decade_label] += 1 print("\n" + "=" * 60) print("PATTERN: Decade Distribution") print("=" * 60) print("How often numbers from each range appear:") total = sum(decade_counts.values()) for decade in ["00-09", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69"]: count = decade_counts.get(decade, 0) percentage = (count / total) * 100 if total > 0 else 0 print(f" {decade}: {count} times ({percentage:.1f}%)") return {'decade_distribution': dict(decade_counts)} def run_all_pattern_analyses(data: List[Dict]) -> Dict: """ Run all pattern detection analyses. Args: data: List of powerball data dictionaries Returns: Dictionary containing all pattern analysis results """ print("\n" + "#" * 60) print("# ADVANCED PATTERN DETECTION ANALYSIS") print("#" * 60) results = {} results['consecutive'] = detect_consecutive_patterns(data) results['odd_even'] = detect_odd_even_patterns(data) results['high_low'] = detect_high_low_patterns(data) results['sum'] = detect_sum_patterns(data) results['gaps'] = detect_gap_patterns(data) results['hot_cold'] = detect_hot_cold_numbers(data, recent_draws=20) results['overdue'] = detect_overdue_numbers(data) results['pairs'] = detect_number_pairs(data, top_n=15) results['decades'] = detect_decade_distribution(data) return results def generate_pattern_based_combinations(data: List[Dict], pattern_results: Dict, num_combinations: int = 5) -> List[Dict]: """ Generate number combinations based on pattern analysis. Args: data: List of powerball data dictionaries pattern_results: Results from run_all_pattern_analyses num_combinations: Number of combinations to generate Returns: List of dictionaries containing combination details """ import random print("\n" + "=" * 60) print("PATTERN-BASED NUMBER COMBINATIONS") print("=" * 60) print("\n*** DISCLAIMER: These combinations are based on pattern analysis.") print("Lottery draws are random. Past patterns do NOT predict future results.") print("Play responsibly.\n") combinations = [] # Get pattern insights hot_white = list(pattern_results['hot_cold']['hot_white'].keys())[:15] cold_white = [num for num, _ in pattern_results['hot_cold']['cold_white'].items() if _ < 3][:10] overdue_white = [num for num, days in pattern_results['overdue']['overdue_white'].items() if days != float('inf')][:15] hot_powerball = list(pattern_results['hot_cold']['hot_powerball'].keys())[:3] overdue_powerball = [num for num, days in pattern_results['overdue']['overdue_powerball'].items() if days != float('inf')][:5] # Get most common distributions odd_even_dist = pattern_results['odd_even']['distribution'] most_common_oe = max(odd_even_dist.items(), key=lambda x: x[1])[0] target_odds = int(most_common_oe.split('odd')[0]) high_low_dist = pattern_results['high_low']['distribution'] most_common_hl = max(high_low_dist.items(), key=lambda x: x[1])[0] target_lows = int(most_common_hl.split('low')[0]) # Get average sum avg_sum = pattern_results['sum']['average'] sum_tolerance = 30 # Get top pairs top_pairs = list(pattern_results['pairs']['top_pairs'].keys())[:20] # Strategy descriptions strategies = [ ("Hot Numbers Focus", hot_white, "Uses frequently drawn recent numbers"), ("Balanced Hot + Overdue", hot_white[:8] + overdue_white[:12], "Mixes hot numbers with overdue picks"), ("Overdue Numbers Focus", overdue_white, "Focuses on numbers that haven't appeared recently"), ("Cold Numbers Gamble", cold_white + hot_white[:10], "Includes rarely drawn numbers"), ("Pair-Based Selection", [n for pair in top_pairs for n in pair], "Uses numbers from common pairs") ] for strategy_idx in range(min(num_combinations, len(strategies))): strategy_name, number_pool, strategy_desc = strategies[strategy_idx] # Ensure we have enough numbers in pool if len(number_pool) < 20: number_pool = list(set(number_pool + hot_white + list(range(1, 70)))) # Try to generate a combination that fits the patterns attempts = 0 max_attempts = 1000 selected = [] # Initialize to avoid unbound variable while attempts < max_attempts: # Select 5 random numbers from pool selected = random.sample(number_pool[:30], min(5, len(number_pool[:30]))) selected = sorted(selected) # Check odd/even distribution odds_count = sum(1 for n in selected if n % 2 == 1) if abs(odds_count - target_odds) > 1: attempts += 1 continue # Check high/low distribution lows_count = sum(1 for n in selected if n <= 35) if abs(lows_count - target_lows) > 1: attempts += 1 continue # Check sum is reasonable total = sum(selected) if abs(total - avg_sum) > sum_tolerance: attempts += 1 continue # Check gaps are reasonable (not too clustered or too spread) gaps = [selected[i+1] - selected[i] for i in range(4)] if min(gaps) < 2 or max(gaps) > 25: attempts += 1 continue # Good combination found break # If we didn't find a perfect match, selected still has the last attempt if not selected: selected = sorted(random.sample(range(1, 70), 5)) # Select powerball if strategy_idx % 2 == 0 and hot_powerball: powerball = random.choice(hot_powerball) elif overdue_powerball: powerball = random.choice(overdue_powerball[:5]) else: powerball = random.randint(1, 26) # Calculate combination stats odds = sum(1 for n in selected if n % 2 == 1) evens = 5 - odds lows = sum(1 for n in selected if n <= 35) highs = 5 - lows total = sum(selected) combinations.append({ 'strategy': strategy_name, 'description': strategy_desc, 'numbers': selected, 'powerball': powerball, 'odds': odds, 'evens': evens, 'lows': lows, 'highs': highs, 'sum': total, 'attempts': attempts }) # Display combinations for i, combo in enumerate(combinations, 1): print(f"\nCombination #{i}: {combo['strategy']}") print(f" Strategy: {combo['description']}") print(f" Numbers: {' '.join(map(str, combo['numbers']))} + Powerball: {combo['powerball']}") print(f" Stats: {combo['odds']}odd-{combo['evens']}even, {combo['lows']}low-{combo['highs']}high, Sum: {combo['sum']}") print("\n" + "=" * 60) print("Quick Pick Lines:") print("=" * 60) for i, combo in enumerate(combinations, 1): numbers_str = ' - '.join(f"{n:2d}" for n in combo['numbers']) print(f" Line {i}: {numbers_str} | PB: {combo['powerball']:2d}") return combinations def main(): """Main function.""" # Default to 'powerball_numbers.csv' in the same directory as the script script_dir = Path(__file__).parent csv_file = script_dir / 'powerball_numbers.csv' # You can also specify a different file path here # csv_file = Path('path/to/your/file.csv') print(f"Reading Powerball numbers from: {csv_file}\n") powerball_data = read_powerball_csv(str(csv_file)) if powerball_data: print(f"Successfully loaded {len(powerball_data)} records.\n") display_powerball_data(powerball_data) stats = analyze_most_frequent_numbers(powerball_data) generate_suggested_combination(stats) # Run advanced pattern detection pattern_results = run_all_pattern_analyses(powerball_data) # Generate pattern-based combinations pattern_combos = generate_pattern_based_combinations(powerball_data, pattern_results, num_combinations=5) else: print("Failed to load powerball data.") if __name__ == '__main__': main()