<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _get_codes_for_values(values, categories):
 """ utility routine to turn values into codes given the specified categories """

    from pandas.core.algorithms import _get_data_algo, _hashtables
    dtype_equal = is_dtype_equal(values.dtype, categories.dtype)

    if dtype_equal:
        # To prevent erroneous dtype coercion in _get_data_algo, retrieve
        # the underlying numpy array. gh-22702
        values = getattr(values, '_ndarray_values', values)
        categories = getattr(categories, '_ndarray_values', categories)
    elif (is_extension_array_dtype(categories.dtype) and
          is_object_dtype(values)):
        # Support inferring the correct extension dtype from an array of
        # scalar objects. e.g.
        # Categorical(array[Period, Period], categories=PeriodIndex(...))
        try:
            values = (
                categories.dtype.construct_array_type()._from_sequence(values)
            )
        except Exception:
            # but that may fail for any reason, so fall back to object
            values = ensure_object(values)
            categories = ensure_object(categories)
    else:
        values = ensure_object(values)
        categories = ensure_object(categories)

    (hash_klass, vec_klass), vals = _get_data_algo(values, _hashtables)
    (_, _), cats = _get_data_algo(categories, _hashtables)
    t = hash_klass(len(cats))
    t.map_locations(cats)
    return coerce_indexer_dtype(t.lookup(vals), cats)