Pick: choose an option. Constraint: prune if invalid. Unpick: revert the choice before returning. The recursion walks a decision tree and prunes heavily. Memorize the skeleton; the rest is domain-specific.
def backtrack(state, choices): if is_goal(state): record; return; for c in choices(state): apply c; backtrack(state+c, next_choices(state)); undo c.
Permutations: state is the partial permutation; choices are the unused elements.
N-Queens: choices are columns; constraint prunes attacks; track row by row.
Sudoku: choices are digits 1-9 in each cell.
CHOOSE -> EXPLORE -> UNCHOOSE
(prune when constraints violated)
Three lines, infinite problems. Always keep the “un-pick” symmetric with “pick” or you’ll leak state.