-
Notifications
You must be signed in to change notification settings - Fork 0
Hm3 #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Hm3 #6
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| def n_queens_bitmask(n): | ||
| """Самое быстрое решение с использованием битовых масок""" | ||
| if n < 1: | ||
| return 0 | ||
|
|
||
| def backtrack(row=0, columns=0, diagonals1=0, diagonals2=0): | ||
| if row == n: | ||
| return 1 | ||
|
|
||
| count = 0 | ||
| # Доступные позиции в текущей строке | ||
| available_positions = ((1 << n) - 1) & ~(columns | diagonals1 | diagonals2) | ||
|
|
||
| while available_positions: | ||
| # Берем самую правую доступную позицию | ||
| position = available_positions & -available_positions | ||
| # Убираем ее из доступных | ||
| available_positions -= position | ||
|
|
||
| count += backtrack( | ||
| row + 1, | ||
| columns | position, | ||
| (diagonals1 | position) << 1, | ||
| (diagonals2 | position) >> 1, | ||
| ) | ||
|
|
||
| return count | ||
|
|
||
| return backtrack() | ||
|
|
||
|
|
||
| def test_bitmask_basic(): | ||
| """Тест оптимизированного решения (bitmask)""" | ||
| print("ТЕСТИРОВАНИЕ BITMASK РЕШЕНИЯ") | ||
| print("=" * 50) | ||
|
|
||
| # Известные значения для N ферзей | ||
| test_cases = [ | ||
| (1, 1), # [0] | ||
| (2, 0), # нет решений | ||
| (3, 0), # нет решений | ||
| (4, 2), # 2 решения | ||
| (5, 10), # 10 решений | ||
| (6, 4), # 4 решения | ||
| (7, 40), # 40 решений | ||
| (8, 92), # 92 решения | ||
| (9, 352), # 352 решения | ||
| (10, 724), # 724 решения | ||
| ] | ||
|
|
||
| all_passed = True | ||
|
|
||
| for n, expected in test_cases: | ||
| result = n_queens_bitmask(n) | ||
|
|
||
| if result == expected: | ||
| print(f"✓ N={n}: {result} (ожидалось {expected})") | ||
| else: | ||
| print(f"✗ N={n}: {result} (ожидалось {expected})") | ||
| all_passed = False | ||
|
|
||
| print("=" * 50) | ||
| print(f"РЕЗУЛЬТАТ: {'Все тесты пройдены' if all_passed else 'Есть ошибки'}") | ||
|
|
||
| return all_passed | ||
|
Comment on lines
+32
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тесты в этом задании не предполагались, тем более тут они очень захардкожены через |
||
|
|
||
|
|
||
| # Запуск теста | ||
| if __name__ == "__main__": | ||
| test_bitmask_basic() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import itertools | ||
|
|
||
|
|
||
| def is_valid_placement(positions): | ||
| """Проверяет, является ли расстановка ферзей корректной""" | ||
| n = len(positions) | ||
| for i in range(n): | ||
| for j in range(i + 1, n): | ||
| # Проверка на одну строку (невозможно в нашей модели) | ||
| # Проверка на одну диагональ | ||
| if abs(positions[i] - positions[j]) == abs(i - j): | ||
| return False | ||
| return True | ||
|
|
||
|
|
||
| def n_queens_placement(n): | ||
| """Перебор всех возможных расстановок""" | ||
| if n < 1 or n > 10: # Ограничение для перебора | ||
| return 0 | ||
|
|
||
| count = 0 | ||
| # Генерируем все перестановки (каждый ферзь в своем столбце) | ||
| for permutation in itertools.permutations(range(n)): | ||
| if is_valid_placement(permutation): | ||
| count += 1 | ||
| return count | ||
|
|
||
|
|
||
| def test_placement_small(): | ||
| """Тестирование для маленьких N где перебор работает быстро""" | ||
| test_cases = { | ||
| 1: 1, # [0] | ||
| 2: 0, # нет решений | ||
| 3: 0, # нет решений | ||
| 4: 2, # [1,3,0,2] и [2,0,3,1] | ||
| 5: 10, # известное значение | ||
| 6: 4, # известное значение | ||
| } | ||
|
|
||
| print("Тестирование переборного решения:") | ||
| print("N\tОжидаемо\tПолучено\tСтатус") | ||
| print("-" * 40) | ||
|
|
||
| for n, expected in test_cases.items(): | ||
| if n <= 6: # Ограничиваем для скорости | ||
| result = n_queens_placement(n) | ||
| status = "✓" if result == expected else "✗" | ||
| print(f"{n}\t{expected}\t\t{result}\t\t{status}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| test_placement_small() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| def is_valid_recursive(board, row, col): | ||
| """Проверяет, можно ли поставить ферзя на позицию (row, col)""" | ||
| # Проверяем все предыдущие строки | ||
| for i in range(row): | ||
| # Проверка по вертикали и диагоналям | ||
| if board[i] == col or abs(board[i] - col) == abs(i - row): | ||
| return False | ||
| return True | ||
|
|
||
|
|
||
| def solve_n_queens_recursive(n, row=0, board=None, count=None): | ||
| """Рекурсивное решение с backtracking""" | ||
| if board is None: | ||
| board = [-1] * n | ||
| if count is None: | ||
| count = [0] | ||
|
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачем тут передавать список |
||
|
|
||
| if row == n: | ||
| # Найдена корректная расстановка | ||
| count[0] += 1 | ||
| return | ||
|
|
||
| for col in range(n): | ||
| if is_valid_recursive(board, row, col): | ||
| board[row] = col | ||
| solve_n_queens_recursive(n, row + 1, board, count) | ||
| # Backtrack - не нужно явно сбрасывать, так как перезаписываем | ||
|
|
||
| return count[0] | ||
|
|
||
|
|
||
| def n_queens_recursive(n): | ||
| """Обертка для рекурсивного решения""" | ||
| if n < 1: | ||
| return 0 | ||
| return solve_n_queens_recursive(n) | ||
|
|
||
|
|
||
| def test_n_queens_recursive_basic(): | ||
| """Тест рекурсивного решения на известных значениях""" | ||
| print("ТЕСТИРОВАНИЕ РЕКУРСИВНОГО РЕШЕНИЯ") | ||
| print("=" * 40) | ||
|
|
||
| # Известные значения для N ферзей | ||
| test_cases = [ | ||
| (1, 1), # [0] | ||
| (2, 0), # нет решений | ||
| (3, 0), # нет решений | ||
| (4, 2), # 2 решения | ||
| (5, 10), # 10 решений | ||
| (6, 4), # 4 решения | ||
| (7, 40), # 40 решений | ||
| (8, 92), # 92 решения | ||
| ] | ||
|
|
||
| all_passed = True | ||
|
|
||
| for n, expected in test_cases: | ||
| result = n_queens_recursive(n) | ||
|
|
||
| if result == expected: | ||
| print(f"✓ N={n}: {result} (ожидалось {expected})") | ||
| else: | ||
| print(f"✗ N={n}: {result} (ожидалось {expected})") | ||
| all_passed = False | ||
|
|
||
| print("=" * 40) | ||
| print(f"РЕЗУЛЬТАТ: {'Все тесты пройдены' if all_passed else 'Есть ошибки'}") | ||
|
|
||
| return all_passed | ||
|
|
||
|
|
||
| # Запуск теста | ||
| if __name__ == "__main__": | ||
| test_n_queens_recursive_basic() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Всю эту логику стоит пояснить подробнее.
Например, что происходит в этих строчках?
Вернувшись к ним через время вы уже и не сможете точно вспомнить.