Rishabh12j's picture
Update app.py
acdd1bb verified
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()