def dfs(domain, trace, dontBother, depth):
    if depth <= 0:
        return None
    if domain == None:
        return None
    found = 0
    for successor in get_successors(domain):
        if successor in dontBother:
            continue
        ns = copy_dict(domain)
        ns[successor[0]] = [successor[1]]
        solved = ac3_enhanced.solve(ns)
        if solved == None:
            # print "Didn't find solution"
            dontBother.append(successor)
            continue
        else:
            # print "Solvable for %s,%d" % successor
            found += 1
            if is_solved(solved):
                return solved
            tr = trace[:]
            tr.append(successor)
            return dfs(solved, tr, dontBother, depth)
    return False
def run(puzzle, debug=False):
    domain = ac3_enhanced.ac3_basic.generate_domain(puzzle)
    base = ac3_enhanced.solve(domain)
    if base == None:
        return None
    if is_solved(domain):
        return ac3_enhanced.domain_to_puzzle(base, puzzle)
    # now we do IDDFS
    dontBother = []  # optimize so we dont check bad choices repeatedly
    depth = 1
    while 1:
        if debug:
            print "Iterating at depth %d" % depth
        sol = dfs(domain, [], dontBother, depth)
        if depth == 4:
            exit()
        if sol == None:
            depth += 1
        elif sol == False:
            return None
        else:
            return ac3_enhanced.domain_to_puzzle(sol, puzzle)