<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def pad_repeat_border(data, padwidth):
 """ Similar to `pad`, except the border value from ``data`` is used to pad. Parameters data : ndarray Numpy array of any dimension and type. padwidth : int or tuple If int, it will pad using this amount at the beginning and end of all dimensions. If it is a tuple (of same length as `ndim`), then the padding amount will be specified per axis. Examples -------- Pad an array by repeating its borders: array([[ 0, 0, 0, 1, 2, 3, 3, 3], [ 0, 0, 0, 1, 2, 3, 3, 3], [ 0, 0, 0, 1, 2, 3, 3, 3], [ 4, 4, 4, 5, 6, 7, 7, 7], [ 8, 8, 8, 9, 10, 11, 11, 11], [ 8, 8, 8, 9, 10, 11, 11, 11], [ 8, 8, 8, 9, 10, 11, 11, 11]]) """


    data = np.asarray(data)
    shape = data.shape
    if isinstance(padwidth, int):
        padwidth = (padwidth,)*len(shape)

    padded_shape = tuple(map(lambda ix: ix[1]+padwidth[ix[0]]*2,
                             enumerate(shape)))
    new_data = np.empty(padded_shape, dtype=data.dtype)
    new_data[[slice(w, -w) if w > 0 else slice(None) for w in padwidth]] = data

    for i, pw in enumerate(padwidth):
        if pw > 0:
            selection = [slice(None)] * data.ndim
            selection2 = [slice(None)] * data.ndim

            # Lower boundary
            selection[i] = slice(0, pw)
            selection2[i] = slice(pw, pw+1)
            new_data[tuple(selection)] = new_data[tuple(selection2)]

            # Upper boundary
            selection[i] = slice(-pw, None)
            selection2[i] = slice(-pw-1, -pw)
            new_data[tuple(selection)] = new_data[tuple(selection2)]

    return new_data