"""
Learning Goals:
 - Identify core parts of graphs, including nodes, edges, neighbors, weights, and directions.
 - Use graphs implemented as dictionaries when reading and writing simple algorithms in code
"""

unweightedGraph = {
      "A" : [ "B", "G" ],
      "B" : [ "A", "C" ],
      "C" : [ "B", "H" ],
      "D" : [ "F" ],
      "E" : [ "G", "H" ],
      "F" : [ "D" ],
      "G" : [ "A", "E", "H" ],
      "H" : [ "C", "E", "G" ]
     }

weightedGraph = {
      "A" : [ ["B", 5], ["G", 2] ],
      "B" : [ ["A", 5], ["C", 3] ],
      "C" : [ ["B", 3], ["H", 9] ],
      "D" : [ ["F", 4] ],
      "E" : [ ["G", 1], ["H", 7] ],
      "F" : [ ["D", 4] ],
      "G" : [ ["A", 2], ["E", 1], ["H", 2] ],
      "H" : [ ["C", 9], ["E", 7], ["G", 2] ]
     }

###

def printNodes(g):
    for node in g:
        print(node)

printNodes(unweightedGraph)
printNodes(weightedGraph)

###

def printEdges(g):
    for node in g:
        neighbors = g[node]
        for neighbor in neighbors:
            print(node + "-" + neighbor)

printEdges(unweightedGraph)

def printEdges(g):
    for node in g:
        neighbors = g[node]
        for neighbor in neighbors:
            print(node + "-" + neighbor[0], neighbor[1])

printEdges(weightedGraph)

###

def getNeighbors(g, node):
    return g[node]

print(getNeighbors(unweightedGraph, "A"))

def getNeighbors(g, node):
    result = []
    for neighbor in g[node]:
        result.append(neighbor[0])
    return result

print(getNeighbors(weightedGraph, "A"))

###

def getEdgeWeight(g, x, y):
    for neighbor in g[x]:
        if neighbor[0] == y:
            return neighbor[1]

print(getEdgeWeight(weightedGraph, "E", "G"))

###

g = { "Jon" : [ "Arya", "Tyrion" ],
      "Tyrion" : [ "Jaime", "Pod", "Jon" ],
      "Arya" : [ "Jon" ],
      "Jaime" : [ "Tyrion", "Brienne" ],
      "Brienne" : [ "Jaime", "Pod" ],
      "Pod" : [ "Tyrion", "Brienne", "Jaime" ],
      "Ramsay" : [ ]
    }

def mostPopularPerson(g):
    bestCount = 0
    bestName = None
    for person in g:
        numFriends = len(g[person])
        if numFriends > bestCount:
            bestCount = numFriends
            bestName = person
    return bestName

print(mostPopularPerson(g))

###

def makeInviteList(g, person):
    invite = []
    invite = invite + g[person]
    for friend in g[person]:
        for friendOfFriend in g[friend]:
            if friendOfFriend not in invite and friendOfFriend != person:
                invite.append(friendOfFriend)
    return invite

print(makeInviteList(g, "Tyrion"))
print(makeInviteList(g, "Arya"))

###

def friendsInCommon(g, p1, p2):
    common = []
    for friend in g[p1]:
        if friend in g[p2]:
            common.append(friend)
    return common

print(friendsInCommon(g, "Tyrion", "Jaime"))
print(friendsInCommon(g, "Pod", "Jaime"))