# 2021fa_code.py
# Questions by W. White/Fall 2021 staff
# This file by L. Lee, Apr 2022

import copy # test that originals not changed
import numpy

def shiftkeys(d):
    pass


def test_shiftkeys():
    
    tests = [
        [{1:'a',2:'b'},{2:'a',3:'b'}],
        [{-1: 14, 10: "hi"}, {0: 14, 11: "hi"}]
    ]

    for [theinput, expected] in tests:
        origcopy = copy.deepcopy(theinput)
        result = shiftkeys(theinput)

        # Test that original input was not changed
        assert theinput == origcopy, "Error: should not modify input dictionary. It was changed from " + repr(origcopy) + " to "+repr(theinput)

        assert result == expected, "Error: Expected "+repr(expected)+" but got "+repr(result)




def collapse(ragged):
    pass


def test_collapse():
    
    in1 = [[1.0,2.0],[3.2],[]]
    out1 = [1.5, 3.2, 0]
    in2 = [[], [-3, -6, 0]]
    out2 = [0, -3]
    tests = [[in1, out1],
             [in2, out2]]

    for [theinput, expected] in tests:
        result = collapse(theinput)
        assert result is None, "Error: collapse returned a value, but shouldn't"
        assert theinput == expected, "Error: Expected that input would become "+repr(expected)+" but it is instead "+repr(theinput)


def merge_recursive(a, b):
    pass

def merge_while(a, b):
    # In Spring 2022, we haven't gotten to while-loops yet,
    # but we provide this implementation for posterity.


    head = []  # fronts of a and b already "pulled off",
               # in sorted order.

    while a != [] and b!= []:
        # neither a nor b are empty
        if a[0] <= b[0]:
            head.append(a[0])
            a = a[1:]
        else:
            head.append(b[0])
            b = b[1:]

    # at least one of a and b is now empty
    return head + a + b

def merge(a, b):
    pass

def test_merge():
    
    tests = [
        # items are triples [a, b, expected]
        [[], [], list([])], # using list() to make totally sure these are different empty lists.
        [[], [1, 2], list([1, 2])],
        [[0, 3], [1, 3, 4], [0, 1, 3, 3, 4]]
    ]

    for [a, b, expected] in tests:
        print("testing merge("+repr(a)+", "+repr(b)+")")
        orig_a = copy.deepcopy(a)
        orig_b = copy.deepcopy(b)
        result = merge(a, b)
        assert a == orig_a, "1st arg should still be "+repr(orig_a)+" but now is "+repr(a)
        assert b == orig_b, "2nd arg should still be "+repr(orig_b)+" but now is "+repr(b)
        assert result == expected, "Error: Expected "+repr(expected)+" but got "+repr(result)

# Helper
def is_odd(num):
    """Returns True if num is odd, False o.w.
    Precondition: num is an int"""
    if num % 2 == 0:
        return False
    else:
        return True


def toevens(nums):
    pass


def test_toevens():
    tests = [
        [ [0, 1, 2, 3, 4], [0, 2, 2, 4, 4]],
        [[], []],
        [[2], [2]],
        [[3], [4]]
    ]

    for [theinput, expected] in tests:
        origcopy = copy.deepcopy(theinput)
        result = toevens(theinput)

        # Test that the input wasn't modified
        assert theinput == origcopy, "Error: should not modify input dictionary. It was changed from " + repr(origcopy) + " to "+repr(theinput)

        assert result == expected, "Error: Expected "+repr(expected)+" but got "+repr(result)




if __name__ == '__main__':

    # comment out any tests you want to skip
    testfns = [
     test_shiftkeys, 
     test_collapse, 
     test_merge,
     test_toevens,
     ]
    


    for fn in testfns:
        print("Testing function "+fn.__name__)
        fn()
        print("That test ran without crashing! Great!\n")













