import math


def re_stride(a, kernel, stride=None):
    """Returns a re-shaped and re-strided Rensor given a kernel (uses as_strided).

    Args:
        a (Tensor): The Tensor to re-stride.
        kernel (tuple or int): The size of the new dimension(s).
        stride (tuple or int, optional): Strides for viewing the expanded dimension(s) (default 1)
    """
    if isinstance(kernel, int):
        kernel = (kernel,)
    if stride is None:
        stride = tuple(1 for i in kernel)
    elif isinstance(stride, int):
        stride = (stride,)
    window_dim = len(kernel)
    new_shape = (
        a.size()[:-window_dim]
        + kernel
        + tuple(
            int(math.floor((s - kernel[i]) / stride[i]) + 1)
            for i, s in enumerate(a.size()[-window_dim:])
        )
    )
    new_stride = (
        a.stride()[:-window_dim]
        + a.stride()[-window_dim:]
        + tuple(s * k for s, k in zip(a.stride()[-window_dim:], stride))
    )
    return a.as_strided(new_shape, new_stride)