# @param {Integer[]} nums1
# @param {Integer} m
# @param {Integer[]} nums2
# @param {Integer} n
# @return {Void} Do not return anything, modify nums1 in-place instead.
def merge(nums1, m, nums2, n)
    # shift numbers to right
    i, k = m - 1, nums1.size - 1
    while i >= 0 do
        nums1[k] = nums1[i]
        i -= 1
        k -= 1
    end

    # merge them
    i, j, k = nums1.size - m, 0, 0
    while i < nums1.size && j < n do
        if nums1[i] < nums2[j] then
            nums1[k] = nums1[i]
            i += 1
        else
            nums1[k] = nums2[j]
            j += 1
        end
        k += 1
    end

    while j < n do
        nums1[k] = nums2[j]
        j += 1
        k += 1
    end
end

RSpec.describe "merge" do
    it "nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 ~> [1,2,2,3,5,6]" do
        nums1, m = [1,2,3,0,0,0], 3
        nums2, n = [2,5,6], 3

        merge(nums1, m, nums2, n)
        expect(nums1).to eq([1,2,2,3,5,6])
    end

    it "nums1 = [0], m = 0, nums2 = [1], n = 1 ~> [1]" do
        nums1, m = [1], 1
        nums2, n = [], 0

        merge(nums1, m, nums2, n)
        expect(nums1).to eq([1])
    end

    it "[3, 3] for 6 is [0, 1]" do
        nums1, m = [0], 0
        nums2, n = [1], 1

        merge(nums1, m, nums2, n)
        expect(nums1).to eq([1])
    end
end