Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from itertools import permutations | |
| # ========================================== | |
| # 1. SOLVER LOGIC | |
| # ========================================== | |
| # (Standard logic, same as before) | |
| def apply_op(a, op, b): | |
| if op == '+': return a + b | |
| if op == '-': return a - b | |
| if op == '×': return a * b | |
| if op == '÷': | |
| if b == 0 or a % b != 0: return None | |
| return a // b | |
| return None | |
| def evaluate_line(n1, op1, n2, op2, n3): | |
| high_precedence = {'×', '÷'} | |
| if op2 in high_precedence and op1 not in high_precedence: | |
| right = apply_op(n2, op2, n3) | |
| if right is None: return None | |
| return apply_op(n1, op1, right) | |
| else: | |
| left = apply_op(n1, op1, n2) | |
| if left is None: return None | |
| return apply_op(left, op2, n3) | |
| def solve_puzzle(pool_str, *args): | |
| # args contains all the grid inputs in the specific order we passed them | |
| # Unpack based on the specific structure of the inputs list constructed below | |
| try: | |
| pool = [int(x.strip()) for x in pool_str.split(',')] | |
| if len(pool) != 9: return [""] * 9 | |
| except ValueError: return [""] * 9 | |
| # Unpack args. The order matches the 'inputs' list in the UI section | |
| # Rows: 1, 2, 3 | |
| r1 = [args[0], args[1], int(args[2])] | |
| r2 = [args[3], args[4], int(args[5])] | |
| r3 = [args[6], args[7], int(args[8])] | |
| # Cols: 1, 2, 3 (Top Ops) & 4, 5, 6 (Bottom Ops) & Targets | |
| c1 = [args[9], args[12], int(args[15])] | |
| c2 = [args[10], args[13], int(args[16])] | |
| c3 = [args[11], args[14], int(args[17])] | |
| row_ops = [[r1[0], r1[1]], [r2[0], r2[1]], [r3[0], r3[1]]] | |
| col_ops = [[c1[0], c1[1]], [c2[0], c2[1]], [c3[0], c3[1]]] | |
| row_targets = [r1[2], r2[2], r3[2]] | |
| col_targets = [c1[2], c2[2], c3[2]] | |
| for p in permutations(pool): | |
| # Checks | |
| if evaluate_line(p[0], row_ops[0][0], p[1], row_ops[0][1], p[2]) != row_targets[0]: continue | |
| if evaluate_line(p[3], row_ops[1][0], p[4], row_ops[1][1], p[5]) != row_targets[1]: continue | |
| if evaluate_line(p[6], row_ops[2][0], p[7], row_ops[2][1], p[8]) != row_targets[2]: continue | |
| if evaluate_line(p[0], col_ops[0][0], p[3], col_ops[0][1], p[6]) != col_targets[0]: continue | |
| if evaluate_line(p[1], col_ops[1][0], p[4], col_ops[1][1], p[7]) != col_targets[1]: continue | |
| if evaluate_line(p[2], col_ops[2][0], p[5], col_ops[2][1], p[8]) != col_targets[2]: continue | |
| return [str(x) for x in p] | |
| return ["?"] * 9 | |
| # ========================================== | |
| # 2. GRID CONFIGURATION | |
| # ========================================== | |
| # We define the grid semantically: | |
| # "SOL" = Solution Box (Non-editable output) | |
| # "OP" = Operator (Dropdown input) | |
| # "TGT" = Target (Editable input) | |
| # "EQ" = Equals Sign | |
| # "SPC" = Spacer (Empty) | |
| GRID_LAYOUT = [ | |
| ["SOL", "OP", "SOL", "OP", "SOL", "EQ", "TGT"], # Row 0 | |
| ["OP", "SPC", "OP", "SPC", "OP", "SPC", "SPC"], # Row 1 | |
| ["SOL", "OP", "SOL", "OP", "SOL", "EQ", "TGT"], # Row 2 | |
| ["OP", "SPC", "OP", "SPC", "OP", "SPC", "SPC"], # Row 3 | |
| ["SOL", "OP", "SOL", "OP", "SOL", "EQ", "TGT"], # Row 4 | |
| ["EQ", "SPC", "EQ", "SPC", "EQ", "SPC", "SPC"], # Row 5 | |
| ["TGT", "SPC", "TGT", "SPC", "TGT", "SPC", "SPC"] # Row 6 | |
| ] | |
| # CSS to make the grid look tight and clean | |
| css = """ | |
| .tight-row { gap: 5px !important; margin-bottom: 5px; } | |
| .sol-box textarea { | |
| background-color: #6366f1 !important; color: white !important; | |
| font-size: 20px !important; text-align: center !important; font-weight: bold; | |
| } | |
| .tgt-box textarea { | |
| border: 2px solid #6366f1 !important; font-size: 18px !important; | |
| text-align: center !important; font-weight: bold; | |
| } | |
| .center-html { | |
| display: flex; justify-content: center; align-items: center; | |
| font-size: 24px; font-weight: bold; height: 100%; color: #94a3b8; | |
| } | |
| """ | |
| with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("## 🧩 Programmatic Grid Solver") | |
| with gr.Row(): | |
| pool_input = gr.Textbox(label="Number Pool", value="7, 14, 4, 210, 70, 4, 49, 81, 13") | |
| solve_btn = gr.Button("🚀 Solve", variant="primary") | |
| # This list will store our generated component objects so we can access them later | |
| # to extract inputs or update outputs. | |
| grid_refs = [[None for _ in range(7)] for _ in range(7)] | |
| # We also keep a flat list of just the Solution boxes to easily map outputs | |
| solution_outputs = [] | |
| # --- THE BUILDER LOOP --- | |
| for r, row_config in enumerate(GRID_LAYOUT): | |
| with gr.Row(equal_height=True, elem_classes="tight-row"): | |
| for c, type_code in enumerate(row_config): | |
| # 1. Solution Box (Output) | |
| if type_code == "SOL": | |
| comp = gr.Textbox(interactive=False, show_label=False, elem_classes="sol-box", scale=1) | |
| solution_outputs.append(comp) # Store for output mapping | |
| grid_refs[r][c] = comp | |
| # 2. Operator (Input) | |
| elif type_code == "OP": | |
| comp = gr.Dropdown(["+", "-", "×", "÷"], value="+", container=False, scale=0.6, min_width=50) | |
| grid_refs[r][c] = comp | |
| # 3. Target (Input) | |
| elif type_code == "TGT": | |
| # Default values for demo purposes based on position | |
| def_val = "0" | |
| if r==0: def_val="227" | |
| elif r==2: def_val="20" | |
| elif r==4: def_val="74" | |
| elif r==6 and c==0: def_val="90" | |
| elif r==6 and c==2: def_val="147" | |
| elif r==6 and c==4: def_val="49" | |
| comp = gr.Textbox(value=def_val, show_label=False, container=False, elem_classes="tgt-box", scale=1) | |
| grid_refs[r][c] = comp | |
| # 4. Static Elements | |
| elif type_code == "EQ": | |
| gr.HTML('<div class="center-html">=</div>', scale=0.3) | |
| elif type_code == "SPC": | |
| gr.HTML('', scale=1) # Empty Spacer | |
| # --- WIRING THE INPUTS --- | |
| # Now we need to explicitly gather the inputs in the order the solver expects. | |
| # We access them using the grid_refs matrix we populated in the loop. | |
| solver_inputs = [pool_input] | |
| # Row 1 Inputs (Op1, Op2, Target) -> Grid Coords: (0,1), (0,3), (0,6) | |
| solver_inputs.extend([grid_refs[0][1], grid_refs[0][3], grid_refs[0][6]]) | |
| # Row 2 Inputs -> Grid Coords: (2,1), (2,3), (2,6) | |
| solver_inputs.extend([grid_refs[2][1], grid_refs[2][3], grid_refs[2][6]]) | |
| # Row 3 Inputs -> Grid Coords: (4,1), (4,3), (4,6) | |
| solver_inputs.extend([grid_refs[4][1], grid_refs[4][3], grid_refs[4][6]]) | |
| # Col Ops Top -> Grid Coords: (1,0), (1,2), (1,4) | |
| solver_inputs.extend([grid_refs[1][0], grid_refs[1][2], grid_refs[1][4]]) | |
| # Col Ops Bottom -> Grid Coords: (3,0), (3,2), (3,4) | |
| solver_inputs.extend([grid_refs[3][0], grid_refs[3][2], grid_refs[3][4]]) | |
| # Col Targets -> Grid Coords: (6,0), (6,2), (6,4) | |
| solver_inputs.extend([grid_refs[6][0], grid_refs[6][2], grid_refs[6][4]]) | |
| # Execute | |
| solve_btn.click(fn=solve_puzzle, inputs=solver_inputs, outputs=solution_outputs) | |
| if __name__ == "__main__": | |
| demo.launch() |