def combine(nums, k):
    """
    :param nums: values to select from
    :param k: number of values to pick
    :return: combinations with k values from nums

    >>> print(combine([1, 2, 3], 2))
    [[1, 2], [1, 3], [2, 3]]
    >>> print(combine([1, 2, 3, 3], 2))
    [[1, 2], [1, 3], [1, 3], [2, 3], [2, 3], [3, 3]]
    """
    output, cur = [], []

    def backtrack(start):
        if len(cur) == k:
            output.append(cur[:])
            return
        for i in range(start, len(nums) + 1 - k + len(cur)):
            cur.append(nums[i])
            backtrack(i + 1)
            cur.pop()

    backtrack(0)
    return output


def combineUnique(nums, k):
    """

    :param nums: values to select from, may have duplicate
    :param k: number of values to pick
    :return: combinations with k values from nums

    >>> print(combineUnique([1, 2, 3, 3], 2))
    [[3, 3], [2, 3], [1, 3], [1, 2]]
    """
    from collections import Counter
    ct = Counter(nums)

    output, cur = [], []

    items = list(ct.items())

    def backtrack(idx):
        if idx == len(items):
            return
        num, v = items[idx]
        for i in range(min(v + 1, k - len(cur) + 1)):
            cur.extend([num] * i)

            if len(cur) == k:
                output.append(cur[:])

            if len(cur) < k:
                backtrack(idx + 1)

            for _ in range(i):
                cur.pop()

    backtrack(0)
    return output


def combineWithRepetition(nums, k):
    """

    :param nums: values to select from
    :param k: number of values to pick
    :return: combinations with k values from nums. Each value can be selected any number of times

    >>> print(combineWithRepetition([1, 2, 3], 2))
    [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]
    """
    output, cur = [], []

    def backtrack(start):
        if len(cur) == k:
            output.append(cur[:])
            return
        for i in range(start, len(nums)):
            cur.append(nums[i])
            backtrack(i)
            cur.pop()

    backtrack(0)
    return output