Python幻方暴力破解代码报错求助:索引越界问题排查
Let's break down the issues in your code step by step, starting with the error you're seeing:
1. The Root Cause of IndexError
When x reaches 8 (the last index of your 9-element array a), your code calls m(x+1) which is m(9). Since a only has indices from 0 to 8, accessing a[9] triggers the IndexError. This is a logical mistake—once you've filled the last position, you shouldn't recurse further; you just need to check if the current array is a valid magic square.
2. Critical Bugs in the test() Function
Your function to check for duplicate elements is broken for two key reasons:
b = acreates a reference to the original array, not a copy. So when you runb.pop(i), you're modifying the actualaarray, which ruins the state you're trying to test. Useb = a.copy()orb = a[:]to create a separate copy instead.- Your loop runs
for i in range(len(a)-1), which skips checking the last element for duplicates. Change this torange(len(a))to cover all elements.
Also, a simpler way to check for duplicates (once you're using 1-9 values) is len(set(a)) == len(a)—but we need to handle the initial 0 values properly too.
3. Incorrect Value Range for Magic Square
A standard 3x3 magic square uses unique numbers from 1 to 9. Your code allows values up to 99, which is unnecessary and will waste massive amounts of computation time. We should restrict each position to 1-9.
4. Missing Backtracking Logic
Your recursive approach doesn't reset values when a position reaches the maximum (9). After trying all values for position x, you need to set a[x] back to 0 and return to the previous position (x-1) to increment its value—this is the core of backtracking for brute-force problems.
Fixed Code
Here's a revised version of your code that addresses all these issues:
a = [0, 0, 0, 0, 0, 0, 0, 0, 0] def test(): # Check for duplicates and ensure all values are 1-9 unique_values = set(a) if len(unique_values) != len(a) or 0 in unique_values: return 0 return 1 def win(): target_sum = 15 # Standard 3x3 magic square sum # Check all rows, columns, and diagonals return (sum(a[0:3]) == target_sum and sum(a[3:6]) == target_sum and sum(a[6:]) == target_sum and a[0] + a[4] + a[8] == target_sum and a[2] + a[4] + a[6] == target_sum and a[0] + a[3] + a[6] == target_sum and a[1] + a[4] + a[7] == target_sum and a[2] + a[5] + a[8] == target_sum) def m(x): global a # Try values from 1 to 9 for current position for num in range(1, 10): a[x] = num if test() == 1: if x == 8: if win(): print(f"{a[:3]}\n{a[3:6]}\n{a[6:]}") return True else: # Recurse to next position if m(x + 1): return True # Reset current position when all values are tried (backtrack) a[x] = 0 return False print(m(0))
Key Changes Explained:
- Replaced the
whileloop with aforloop over 1-9 to limit valid values. - Fixed the
test()function to check for duplicates and ensure no zeros remain. - Added backtracking by resetting
a[x]to 0 after exhausting all values for that position. - Removed the invalid recursive call to
m(x+1)whenx == 8. - Hardcoded the target sum (15) for efficiency, since we know it's the standard sum for 3x3 magic squares.
内容的提问来源于stack exchange,提问作者Bjamse

