def one_correct_in_correct_place(x, y): if len([(i,j) for i,j in zip(x, y) if i==j]) == 1: return True def one_correct_in_wrong_place(x, y): return n_correct_in_wrong_place(x, y, 1) def two_correct_in_wrong_place(x, y): return n_correct_in_wrong_place(x, y, 2) def n_correct_in_wrong_place(x, y, n): if any([(i==j) for i,j in zip(x, y)]): return if len([i for i,j in zip(x, y) if i in y]) == n: return True def none_of(x, y): if any([i for i in x if i in y]): return return True class Problem: def __init__(self, x): self.x = x self.constraints = [] def add_constraint(self, y, *args): self.constraints.append( (y, args) ) def get_solutions(self): solutions = self.x for constraint, args in self.constraints: solutions = [x for x in solutions if constraint(x, *args)] return solutions if __name__ == '__main__': problem = Problem([(x,y,z) for x in range(10) for y in range(10) for z in range(10)]) problem.add_constraint(one_correct_in_correct_place, (6, 8, 2)) problem.add_constraint(one_correct_in_wrong_place, (6, 4, 5)) problem.add_constraint(two_correct_in_wrong_place, (2, 0, 6)) problem.add_constraint(none_of, (7, 3, 8)) problem.add_constraint(one_correct_in_wrong_place, (7, 8, 0)) solutions = problem.get_solutions() print('found %d solution(s)' % len(solutions)) for solution in solutions: print("%d%d%d" % solution)