{}
run-icon
main.py
#!/usr/bin/env python3 import itertools def cycle_once(val): """ Cycle a cell one step according to the rule: 0 -> -1, -1 -> +1, +1 -> 0. """ if val == 0: return -1 elif val == -1: return 1 elif val == 1: return 0 else: raise ValueError("Invalid cell value; must be -1, 0, or 1.") def apply_cycles(val, n): """ Apply n one-cycle moves to a cell. (Since three moves return the cell to its original state, we use n mod 3.) """ for _ in range(n % 3): val = cycle_once(val) return val def apply_moves(grid, row_moves, col_moves): """ Given a grid and tuples for row_moves and col_moves (each move is 0, 1, or 2), return the new grid after applying the moves. Each cell (i,j) gets cycled (row_moves[i] + col_moves[j]) mod 3 times. """ new_grid = [] for i in range(4): new_row = [] for j in range(4): net_moves = (row_moves[i] + col_moves[j]) % 3 new_val = apply_cycles(grid[i][j], net_moves) new_row.append(new_val) new_grid.append(new_row) return new_grid def compute_score(grid): """Compute the total score (sum of all cell values).""" return sum(sum(row) for row in grid) def print_grid(grid): """Print the grid""" for row in grid: print(" ".join(f"{x:2d}" for x in row)) def input_grid(): grid = [] print("\nEnter your 4×4 grid (one row per line) with no spaces:") print("Use '-' for -1, '0' for 0, and '1' for +1.") for i in range(4): while True: row_input = input(f"Row {i+1} (4 characters): ").strip() if len(row_input) != 4: print("Please enter exactly 4 characters (no spaces).") continue try: row = [] for char in row_input: if char == '-': row.append(-1) elif char == '0': row.append(0) elif char == '1': row.append(1) else: raise ValueError grid.append(row) break except ValueError: print("Invalid input. Use '-' for -1, '0' for 0, and '1' for +1.") return grid def print_moves(row_moves, col_moves): """ Prints the optimal move notation in clean format. For example, if the row moves are (2, 0, 1, 0) and the column moves are (0, 1, 2, 0), the moves list would be: ["R1", "R1", "R3", "C2", "C3", "C3"] and the printed output would be: R1 - R1 - R3 - C2 C3 - C3 """ moves = [] for i, m in enumerate(row_moves): for _ in range(m): # add "R{i+1}" m times moves.append(f"R{i+1}") for j, m in enumerate(col_moves): for _ in range(m): moves.append(f"C{j+1}") if moves: print("Optimal move notation:") # Wrap every 4 moves per line. for i in range(0, len(moves), 4): group = moves[i:i+4] print(" - ".join(group)) else: print("No moves needed; the puzzle is already optimal.") def solve_puzzle(): grid = input_grid() print("\nInitial grid:") print_grid(grid) initial_score = compute_score(grid) print("Initial score:", initial_score) best_score = -float('inf') best_row_moves = None best_col_moves = None best_grid = None # There are 3^8 = 6561 possible combinations of moves. for row_moves in itertools.product(range(3), repeat=4): for col_moves in itertools.product(range(3), repeat=4): new_grid = apply_moves(grid, row_moves, col_moves) score = compute_score(new_grid) if score > best_score: best_score = score best_row_moves = row_moves best_col_moves = col_moves best_grid = new_grid print("\nOptimal final grid:") print_grid(best_grid) print("Best score:", best_score) print() print_moves(best_row_moves, best_col_moves) print() def main(): while True: solve_puzzle() # Ask the user whether to quit or solve a new puzzle. choice = input("Enter 'N' for a new puzzle or 'Q' to quit: ").strip().upper() while choice not in ('N', 'Q'): choice = input("Invalid input. Please enter 'N' for new or 'Q' to quit: ").strip().upper() if choice == 'Q': print("Goodbye!") break if __name__ == "__main__": main()
Output