def q1(infoDict, listOfLists):
    result = []
    for l in listOfLists:
        color = classifyList(l,infoDict)
        sl = sorted(l)
        if color == "red":
            result.append(sl[-1])
        elif color == "blue":
            result.append(sl[0])
        else:
            result.append(mostCommon(sl))
    return result

def classifyItem(item, infoDict):
    if item in infoDict:
        if infoDict[item] == 'red':
            return 'red'
        elif infoDict[item] == 'blue':
            return 'blue'
    return 'green'

def classifyList(l, infoDict):
    numRed = 0
    numBlue = 0
    numGreen = 0
    for item in l:
        color = classifyItem(item, infoDict)
        if color == 'red':
            numRed += 1
        elif color == 'blue':
            numBlue += 1
        else:
            numGreen += 1
    if (numRed > numBlue) and (numRed > numGreen):
        return "red"
    elif (numBlue > numRed) and (numBlue > numGreen):
        return "blue"
    else:
        return "green"

# presumes l is sorted from min to max
def mostCommon(l):
    mostCommon = None
    currCount = 0
    prevItem = None
    maxCount = 0
    maxItem = None
    for item in l:
        if (prevItem == None) or (prevItem == item):
            currCount += 1
            if currCount > maxCount:
                maxCount = currCount
                maxItem = item
        else:
            currCount = 1
        prevItem = item
    return maxItem


def testQ1():
    testCase(1, [4, 2, 1, 17], q1, {1:"purple", 2:"red", 3:"blue", 25:"red"}, [[4], [2,3,3], [1,2,3], [17]])
    testCase(2, [], q1, {1:"purple", 2:"red", 3:"blue", 25:"red"}, [])
    testCase(3, [None], q1, {1:"purple", 2:"red", 3:"blue", 25:"red"}, [[]])
    testCase(4, [None], q1, {}, [[]])
    testCase(5, [None, 1, None], q1, {}, [[],[2,2,2,1,1,1],[]])
    testCase(6, [None, 1, None], q1, {2:"red"}, [[],[2,2,2,1,1,1],[]])
    testCase(7, [None, 1, None], q1, {2:"red"}, [[],[2,2,2,1,1,1,0.9],[]])
    testCase(8, [None, 2, None], q1, {2:"red"}, [[],[2,2,2,2,2,1,1,1,0.9],[]])
    testCase(9, [None, 0.9, None], q1, {2:"blue"}, [[],[2,2,2,2,2,1,1,1,0.9],[]])
    testCase(10, [1, 2, 2], q1, {2:"purple"}, [[2,1],[2,2,2,2,2,1,1,1,0.9],[2,3]])
    testCase(11, [0.5, 4.9, 3], q1, {1:"blue", 4: "green", 3:"red", 2:"purple"}, [[3,1,1,0.5],[2,1,4.9,3,3,3,3,3.5],[4,4,3,3,5,6,7]])
    testCase(12, [1], q1, {}, [[2,2,2,1,1,1]])
    testCase(13, [1], q1, {2:"blue"}, [[2,2,2,1,1,1]])
    testCase(14, [1], q1, {2:"blue"}, [[2,2,2,1,1,1,0.9]])
    testCase(15, [0.9], q1, {2:"blue"}, [[2,2,2,2,2,1,1,1,0.9]])
    testCase(16, [2], q1, {}, [[2,2,2,2,2,1,1,1,0.9]])
    testCase(17, [2], q1, {}, [[5,5, 2,2,4,4]])
    testCase(18, [2, 3, 1], q1, {1:"purple", 2:"blue", 3:"red", 25:"red"}, [[2,2,2,2,2], [2,3,3], [1,2,3]])


def testCase(i, expectedResult, fn, *args, sortResults=False):
    try:
        res = fn(*args)
        if sortResults == True:
            res = sorted(res)
        if res == expectedResult:
            print("Test {} okay".format(i))
        else:
            print("Test {} FAILED. Result: {} Expected Result: {}".format(i, res, expectedResult))
    except Exception as errMsg:
        print("{} Run-time error when testing input: {}.".format(i, args))
        print("Message: ", errMsg)
