# Path: simpleai/search/csp.py
# def _call_constraint(assignment, neighbors, constraint):
#     variables, values = zip(*[(n, assignment[n])
#                               for n in neighbors])
#     return constraint(variables, values)


from operator import itemgetter
from simpleai.search.csp import _call_constraint
# coding: utf-8



# The first 3 functions are exported for testing purposes.
__all__ = ['all_arcs', 'revise', 'arc_consistency_3']

fst = itemgetter(0)


def revise(domains, arc, constraints):
    """
    Given the arc X, Y (variables), removes the values from X's domain that
    do not meet the constraint between X and Y.

    That is, given x1 in X's domain, x1 will be removed from the domain, if
    there is no value y in Y's domain that makes constraint(X,Y) True, for
    those constraints affecting X and Y.
    """
    x, y = arc
    related_constraints = [(neighbors, constraint)
                           for neighbors, constraint in constraints
                           if set(arc) == set(neighbors)]

    modified = False

    for neighbors, constraint in related_constraints:
        for x_value in domains[x]:

# Path: simpleai/search/csp.py
# def _call_constraint(assignment, neighbors, constraint):
#     variables, values = zip(*[(n, assignment[n])
#                               for n in neighbors])
#     return constraint(variables, values)


# Path: simpleai/search/arc.py
from operator import itemgetter
from simpleai.search.csp import _call_constraint

# coding: utf-8



# The first 3 functions are exported for testing purposes.
__all__ = ['all_arcs', 'revise', 'arc_consistency_3']

fst = itemgetter(0)


def revise(domains, arc, constraints):
    """
    Given the arc X, Y (variables), removes the values from X's domain that
    do not meet the constraint between X and Y.

    That is, given x1 in X's domain, x1 will be removed from the domain, if
    there is no value y in Y's domain that makes constraint(X,Y) True, for
    those constraints affecting X and Y.
    """
    x, y = arc
    related_constraints = [(neighbors, constraint)
                           for neighbors, constraint in constraints
                           if set(arc) == set(neighbors)]

    modified = False

    for neighbors, constraint in related_constraints:
        for x_value in domains[x]:

            constraint_results = (_call_constraint({x: x_value, y: y_value},