3#################################################
# hw6.py
#
# Your name:
# Your andrew id:
#################################################

import math
import string

#################################################
# Functions (for you to write)
#################################################

#### nondestructiveRemoveRepeats ####

def nondestructiveRemoveRepeats(L):
    return []

#### destructiveRemoveRepeats ####

def destructiveRemoveRepeats(L):
    pass

#### lookAndSay ####

def lookAndSay(a):
    return []

#### inverseLookAndSay ####

def inverseLookAndSay(a):
    return []

#### maxProfit ####

def maxProfit(prices):
    return 42

#### bestScrabbleScore ####

def bestScrabbleScore(dictionary, letterScores, hand):
    return 42

#### isLegalSudoku ####


def isLegalSudoku(board):
    return False

def areLegalValues(a):
    return False

def isLegalRow(board, row):
    return False

def isLegalCol(board, col):
    return False

def isLegalBlock(board, block):
    return False


#################################################
# Test Functions
#################################################


#### nondestructiveRemoveRepeats ####

def testNondestructiveRemoveRepeats():
    print("Testing nondestructiveRemoveRepeats()...", end="")
    assert(nondestructiveRemoveRepeats([1,3,5,3,3,2,1,7,5]) == [1,3,5,2,7])
    assert(nondestructiveRemoveRepeats([1,2,3,-2]) == [1,2,3,-2])
    print("Passed.")

#### destructiveRemoveRepeats ####

def testDestructiveRemoveRepeats():
    print("Testing destructiveRemoveRepeats()...", end="")
    a = [1,3,5,3,3,2,1,7,5]
    assert(destructiveRemoveRepeats(a) == None)
    assert(a == [1,3,5,2,7])
    b = [1,2,3,-2]
    assert(destructiveRemoveRepeats(b) == None)
    assert(b == [1,2,3,-2])
    print("Passed.")

#### lookAndSay ####

import copy


def _verifyLookAndSayIsNondestructive():
    a = [1, 2, 3]
    b = copy.copy(a)
    lookAndSay(a)  # ignore result, just checking for destructiveness here
    return (a == b)


def testLookAndSay():
    print("Testing lookAndSay()...", end="")
    assert(_verifyLookAndSayIsNondestructive())
    assert(lookAndSay([]) == [])
    assert(lookAndSay([1, 1, 1]) == [(3, 1)])
    assert(lookAndSay([-1, 2, 7]) == [(1, -1), (1, 2), (1, 7)])
    assert(lookAndSay([3, 3, 8, -10, -10, -10]) == [(2, 3), (1, 8), (3, -10)])
    assert(lookAndSay([2] * 5 + [5] * 2) == [(5, 2), (2, 5)])
    assert(lookAndSay([5] * 2 + [2] * 5) == [(2, 5), (5, 2)])
    print("Passed!")


#### inverseLookAndSay ####

import copy


def _verifyInverseLookAndSayIsNondestructive():
    a = [(1, 2), (2, 3)]
    b = copy.copy(a)
    # ignore result, just checking for destructiveness here
    inverseLookAndSay(a)
    return (a == b)


def testInverseLookAndSay():
    print("Testing inverseLookAndSay()...", end="")
    assert(_verifyInverseLookAndSayIsNondestructive())
    assert(inverseLookAndSay([]) == [])
    assert(inverseLookAndSay([(3, 1)]) == [1, 1, 1])
    assert(inverseLookAndSay([(1, -1), (1, 2), (1, 7)]) == [-1, 2, 7])
    assert(inverseLookAndSay([(2, 3), (1, 8), (3, -10)])
           == [3, 3, 8, -10, -10, -10])
    assert(inverseLookAndSay([(5, 2), (2, 5)]) == [2] * 5 + [5] * 2)
    assert(inverseLookAndSay([(2, 5), (5, 2)]) == [5] * 2 + [2] * 5)
    print("Passed!")


#### maxProfit ####

def testMaxProfit():
    print("Testing maxProfit()...", end="")
    print('Failed. This testcode needs to be written by you.')


#### bestScrabbleScore ####

def testBestScrabbleScore():
    print("Testing bestScrabbleScore()...", end="")
    def dictionary1(): return ["a", "b", "c"]
    def letterScores1(): return [1] * 26
    def dictionary2(): return ["xyz", "zxy", "zzy", "yy", "yx", "wow"]
    def letterScores2(): return [1 + (i % 5) for i in range(26)]
    assert(bestScrabbleScore(
            dictionary1(),
            letterScores1(),
            ["a", "c", "e"]) == (["a", "c"], 1))
    assert(bestScrabbleScore(
           dictionary1(),
           letterScores1(),
           ["b"]) == ("b", 1))
    assert(
        bestScrabbleScore(
            dictionary1(),
            letterScores1(),
            ["z"]) is None)
    assert(bestScrabbleScore(
            dictionary2(),
            letterScores2(),
            ["x", "y", "z"]) == (["xyz", "zxy"], 10))
    assert(bestScrabbleScore(
            dictionary2(),
            letterScores2(),
            ["x", "y", "z", "y"]) == (["xyz", "zxy", "yy"], 10))
    assert(bestScrabbleScore(
            dictionary2(),
            letterScores2(),
            ["x", "y", "q"]) == ("yx", 9))
    assert(bestScrabbleScore(
            dictionary2(),
            letterScores2(),
            ["y", "z", "z"]) == ("zzy", 7))
    assert(
        bestScrabbleScore(
            dictionary2(),
            letterScores2(),
            ["w", "x", "z"]) is None)
    print("Passed!")

#### isLegalSudoku ####

def isNondestructive(f, L):  # Checks to make sure f(L) does not modify L
    import copy
    unmodifiedCopy = copy.deepcopy(L)
    b = f(L)
    return L == unmodifiedCopy

def testAreLegalValues():
    print("Testing areLegalValues...", end="")
    assert(areLegalValues([]) == False)
    assert(areLegalValues([0]) == True)
    assert(areLegalValues([1]) == True)
    assert(areLegalValues([2]) == False)
    assert(areLegalValues([0, 1]) == False)
    assert(areLegalValues([0, 1, 2, 3]) == True)
    assert(areLegalValues([4, 1, 2, 3]) == True)
    assert(areLegalValues([0, 0, 2, 4]) == True)
    assert(areLegalValues([2, 1, 0, 2]) == False)
    assert(isNondestructive(areLegalValues, [0, 1, 2, 3]))
    print("Passed!")


def testIsLegalRow():
    print("Testing IsLegalRow...", end="")
    board0 = [
        [0, 2, 3, 4],
        [3, 0, 3, 1],
        [2, 1, 0, 0],
        [0, 0, 0, 0]
    ]
    assert(isLegalRow(board0, 0) == True)
    assert(isLegalRow(board0, 1) == False)
    print("Passed!")


def testIsLegalCol():
    print("Testing IsLegalCol...", end="")
    board0 = [
        [0, 2, 3, 4],
        [3, 0, 3, 1],
        [2, 1, 0, 0],
        [0, 0, 0, 0]
    ]
    assert(isLegalCol(board0, 0) == True)
    assert(isLegalCol(board0, 2) == False)
    print("Passed!")


def testIsLegalBlock():
    print("Testing IsLegalBlock...", end="")
    board1 = [
        [0, 2, 3, 4],
        [3, 0, 3, 1],
        [2, 1, 0, 4],
        [0, 0, 4, 0]
    ]
    assert(isLegalBlock(board1, 0) == True)
    assert(isLegalBlock(board1, 1) == False)
    assert(isLegalBlock(board1, 3) == False)
    print("Passed!")


def testIsLegalSudoku():
    testAreLegalValues()
    testIsLegalRow()
    testIsLegalCol()
    testIsLegalBlock()
    print("Testing isLegalSudoku...")
    board0 = [
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ]
    assert(isLegalSudoku(board0) == True)
    board1 = [
        [1, 2, 3, 4],
        [4, 3, 2, 1],
        [2, 4, 1, 3],
        [3, 1, 4, 2]
    ]
    assert(isLegalSudoku(board1) == True)
    board2 = [
        [1, 2, 0, 4],
        [4, 0, 2, 0],
        [2, 0, 0, 3],
        [0, 1, 4, 0]
    ]
    assert(isLegalSudoku(board2) == True)
    board3 = [
        [1, 2, 1, 4],
        [4, 0, 2, 0],
        [2, 0, 0, 3],
        [0, 1, 4, 0]
    ]
    assert(isLegalSudoku(board3) == False)
    board4 = [
        [1, 2, 0, 4],
        [4, 0, 2, 3],
        [2, 0, 0, 3],
        [0, 1, 4, 0]
    ]
    assert(isLegalSudoku(board4) == False)
    board5 = [
        [1, 2, 0, 4],
        [4, 0, 2, 0],
        [2, 0, 0, 3],
        [0, 1, 3, 0]
    ]
    assert(isLegalSudoku(board5) == False)
    bigBoard = [
        [5, 3, 0, 0, 7, 0, 0, 0, 0],
        [6, 0, 0, 1, 9, 5, 0, 0, 0],
        [0, 9, 8, 0, 0, 0, 0, 6, 0],
        [8, 0, 0, 0, 6, 0, 0, 0, 3],
        [4, 0, 0, 8, 0, 3, 0, 0, 1],
        [7, 0, 0, 0, 2, 0, 0, 0, 6],
        [0, 6, 0, 0, 0, 0, 2, 8, 0],
        [0, 0, 0, 4, 1, 9, 0, 0, 5],
        [0, 0, 0, 0, 8, 0, 0, 7, 9]
    ]
    assert(isLegalSudoku(bigBoard) == True)
    print("Passed!")

#################################################
# testAll and main
#################################################

def testAll():
    # comment out the tests you do not wish to run!
    testNondestructiveRemoveRepeats()
    testDestructiveRemoveRepeats()
    testLookAndSay()
    testInverseLookAndSay()
    testMaxProfit()
    testBestScrabbleScore()
    testAreLegalValues()
    testIsLegalRow()
    testIsLegalCol()
    testIsLegalBlock()
    testIsLegalSudoku()

def main():
    testAll()

if __name__ == '__main__':
    main()
