Advertisement
Guest User

Untitled

a guest
May 7th, 2014
382
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 20.81 KB | None | 0 0
  1. # -------------------------------- #
  2. # Intro to CS Final Project        #
  3. # Gaming Social Network [Option 1] #
  4. # -------------------------------- #
  5. #
  6. # For students who have paid for the full course experience:
  7. # please check submission instructions in the Instructor Note below.
  8. # -----------------------------------------------------------------------------
  9.  
  10. # Background
  11. # ==========
  12. # You and your friend have decided to start a company that hosts a gaming
  13. # social network site. Your friend will handle the website creation (they know
  14. # what they are doing, having taken our web development class). However, it is
  15. # up to you to create a data structure that manages the game-network information
  16. # and to define several procedures that operate on the network.
  17. #
  18. # In a website, the data is stored in a database. In our case, however, all the
  19. # information comes in a big string of text. Each pair of sentences in the text
  20. # is formatted as follows:
  21. #
  22. # <username> is connected to <name1>, <name2>,...,<nameN>.
  23. # <username> likes to play <game1>,...,<gameN>.
  24. #
  25. # Your friend records the information in that string based on user activity on
  26. # the website and gives it to you to manage. You can think of every pair of
  27. # sentences as defining a gamer profile. For example:
  28. #
  29. # John is connected to Bryant, Debra, Walter.
  30. # John likes to play The Movie: The Game, The Legend of Corgi, Dinosaur Diner.
  31. #
  32. # Consider the data structures that we have used in class - lists, dictionaries,
  33. # and combinations of the two - (e.g. lists of dictionaries). Pick one which
  34. # will allow you to manage the data above and implement the procedures below.
  35. #
  36. # You can assume that <username> is a unique identifier for a user. In other
  37. # words, there is only one John in the network. Furthermore, connections are not
  38. # symmetric - if John is connected with Alice, it does not mean that Alice is
  39. # connected with John.
  40. #
  41. # Project Description
  42. # ====================
  43. # Your task is to complete the procedures according to the specifications below
  44. # as well as to implement a Make-Your-Own procedure (MYOP). You are encouraged
  45. # to define any additional helper procedures that can assist you in accomplishing
  46. # a task. You are encouraged to test your code by using print statements and the
  47. # Test Run button.
  48. # -----------------------------------------------------------------------------
  49.  
  50. # Example string input. Use it to test your code.
  51. # Some details:  Each sentence will be separated from one another with only
  52. # a period (there will not be whitespace or new lines between sentences)
  53. example_input="John is connected to Bryant, Debra, Walter.\
  54. John likes to play The Movie: The Game, The Legend of Corgi, Dinosaur Diner.\
  55. Bryant is connected to Olive, Ollie, Freda, Mercedes.\
  56. Bryant likes to play City Comptroller: The Fiscal Dilemma, Super Mushroom Man.\
  57. Mercedes is connected to Walter, Robin, Bryant.\
  58. Mercedes likes to play The Legend of Corgi, Pirates in Java Island, Seahorse Adventures.\
  59. Olive is connected to John, Ollie.\
  60. Olive likes to play The Legend of Corgi, Starfleet Commander.\
  61. Debra is connected to Walter, Levi, Jennie, Robin.\
  62. Debra likes to play Seven Schemers, Pirates in Java Island, Dwarves and Swords.\
  63. Walter is connected to John, Levi, Bryant.\
  64. Walter likes to play Seahorse Adventures, Ninja Hamsters, Super Mushroom Man.\
  65. Levi is connected to Ollie, John, Walter.\
  66. Levi likes to play The Legend of Corgi, Seven Schemers, City Comptroller: The Fiscal Dilemma.\
  67. Ollie is connected to Mercedes, Freda, Bryant.\
  68. Ollie likes to play Call of Arms, Dwarves and Swords, The Movie: The Game.\
  69. Jennie is connected to Levi, John, Freda, Robin.\
  70. Jennie likes to play Super Mushroom Man, Dinosaur Diner, Call of Arms.\
  71. Robin is connected to Ollie.\
  72. Robin likes to play Call of Arms, Dwarves and Swords.\
  73. Freda is connected to Olive, John, Debra.\
  74. Freda likes to play Starfleet Commander, Ninja Hamsters, Seahorse Adventures."
  75.  
  76. example_input_alternate="""John is connected to Bryant, Debra, Walter. John likes to play The Movie: The Game, The Legend of Corgi, Dinosaur Diner. Bryant is connected to Olive, Ollie, Freda, Mercedes. Bryant likes to play City Comptroller: The Fiscal Dilemma, Super Mushroom Man. Mercedes is connected to Walter, Robin, Bryant. Mercedes likes to play The Legend of Corgi, Pirates in Java Island, Seahorse Adventures. Olive is connected to John, Ollie. Olive likes to play The Legend of Corgi, Starfleet Commander. Debra is connected to Walter, Levi, Jennie, Robin. Debra likes to play Seven Schemers, Pirates in Java Island, Dwarves and Swords. Walter is connected to John, Levi, Bryant. Walter likes to play Seahorse Adventures, Ninja Hamsters, Super Mushroom Man. Levi is connected to Ollie, John, Walter. Levi likes to play The Legend of Corgi, Seven Schemers, City Comptroller: The Fiscal Dilemma. Ollie is connected to Mercedes, Freda, Bryant. Ollie likes to play Call of Arms, Dwarves and Swords, The Movie: The Game. Jennie is connected to Levi, John, Freda, Robin. Jennie likes to play Super Mushroom Man, Dinosaur Diner, Call of Arms. Robin is connected to Ollie. Robin likes to play Call of Arms, Dwarves and Swords. Freda is connected to Olive, John, Debra. Freda likes to play Starfleet Commander, Ninja Hamsters, Seahorse Adventures."""
  77.  
  78. # -----------------------------------------------------------------------------
  79. # create_data_structure(string_input):
  80. #   Parses a block of text (such as the one above) and stores relevant
  81. #   information into a data structure. You are free to choose and design any
  82. #   data structure you would like to use to manage the information.
  83. #
  84. # Arguments:
  85. #   string_input: block of text containing the network information
  86. #
  87. # Return:
  88. #   The new network data structure
  89. #################################
  90. ##       Helper Functions      ##
  91. ##  for create_data_structure  ##
  92. #################################
  93.  
  94. def find_each_sentence(string_input):
  95.     '''Separates a paragraph into a list of strings. Only works if only periods are separating sentences.'''
  96.     sentences, agg = [], ''
  97.     for c in string_input:
  98.         if c == '.':
  99.             sentences.append(agg.strip())
  100.             agg = ''
  101.         else:
  102.             agg += c
  103.     return sentences
  104.  
  105. def separate_into_connections_and_likes(list_of_strings):
  106.     '''Sorts sentences into a dictionary based on connections and games. Only uses specific phrases'''
  107.     dictionary = {}
  108.     dictionary['connections'] = []
  109.     dictionary['likes'] = []
  110.     for elem in list_of_strings:
  111.         if "connected" in elem:
  112.             dictionary["connections"].append(elem)
  113.         elif "likes to play" in elem:
  114.             dictionary['likes'].append(elem)
  115.     return dictionary
  116.  
  117. # I debated whether or not I should combine find_user and find_objects. I decided against it
  118. # as find_user returns a string and find_objects returns a list of strings.
  119.  
  120. def find_user(string):
  121.     '''Returns the user of a sentence. Only works with specific phrases'''
  122.     user = -1
  123.     if " is connected to" in string:
  124.         loc = string.find(" is connected to")
  125.     elif " likes to play" in string:
  126.         loc = string.find(" likes to play")
  127.     else:
  128.         print "Please see the docstring"
  129.     user = string[:loc]                       # Splices the string up to the verb
  130.     return user
  131.  
  132. def find_objects(string):
  133.     '''Returns the objects in the form of a list of strings. Only works with specific phrases.'''
  134.     list_of_objects = []
  135.     if " is connected to" in string:
  136.         loc = string.find(" is connected to")
  137.         objects = string[loc + len(" is connected to"):]
  138.     elif " likes to play" in string:
  139.         loc = string.find(" likes to play")
  140.         objects = string[loc + len(" likes to play"):]  
  141.     else:
  142.         print "Format of string is wrong"
  143.     for i in range(objects.count(",")):                    # This loop doesn't execute if there is only 1 object
  144.         loc_c = objects.find(',')
  145.         list_of_objects.append(objects[:loc_c].strip())
  146.         objects = objects[loc_c+1:].strip()
  147.     list_of_objects.append(objects.strip())                # This statement appends the last object (or the only object in the case of exactly one object)
  148.     return list_of_objects                    
  149.  
  150. def pull_arguments(list_of_strings):
  151.     '''Turns separated sentences into a dictionary on one type. Either connections OR likes - not both'''
  152.     user_dict = {}
  153.     user = ''
  154.     for elem in list_of_strings:
  155.         user = find_user(elem)
  156.         user_dict[user] = find_objects(list_of_strings[list_of_strings.index(elem)])
  157.     return user_dict
  158.  
  159. ###############################
  160. ##  End of Helper Functions  ##
  161. ###############################
  162.  
  163. def create_data_structure(string_input):
  164.     '''Combines two dictionaries created from pull_arguments. Returns the network.'''
  165.     network = {}
  166.     separated = separate_into_connections_and_likes(find_each_sentence(string_input))
  167.     connected = pull_arguments(separated['connections'])
  168.     liked = pull_arguments(separated['likes'])
  169.     for name in connected:
  170.         network[name] = {'Connections' : connected[name], 'Likes' : liked[name]}
  171.     return network
  172.  
  173. # ----------------------------------------------------------------------------- #
  174. # Note that the first argument to all procedures below is 'network' This is the #
  175. # data structure that you created with your create_data_structure procedure,    #
  176. # though it may be modified as you add new users or new connections. Each       #
  177. # procedure below will then modify or extract information from 'network'        #
  178. # ----------------------------------------------------------------------------- #
  179.  
  180. # -----------------------------------------------------------------------------
  181. # get_connections(network, user):
  182. #   Returns a list of all the connections a user has.
  183. #
  184. # Arguments:
  185. #   network: The network you created with create_data_structure.
  186. #   user:    String containing the name of the user.
  187. #
  188. # Return:
  189. #   A list of all connections the user has. If the user has no connections,
  190. #   return an empty list. If the user is not in network, return None.
  191.  
  192. def get_connections(network, user):
  193.     '''Returns forward connections for a user.'''
  194.     if user not in network:
  195.         return None
  196.     if len(network[user]['Connections']):   # Network was designed as a dictionary that could easily pull out connections and likes
  197.         return network[user]['Connections']
  198.     return []
  199.  
  200. # -----------------------------------------------------------------------------
  201. # add_connection(network, user_A, user_B):
  202. #   Adds a connection from user_A to user_B. Make sure to check that both users
  203. #   exist in network.
  204. #
  205. # Arguments:
  206. #   network: The network you created with create_data_structure.
  207. #   user_A:  String with the name of the user ("Gary")
  208. #   user_B:  String with the name of the user that will be the new connection.
  209. #
  210. # Return:
  211. #   The updated network with the new connection added (if necessary), or False
  212. #   if user_A or user_B do not exist in network.
  213.  
  214. def add_connection(network, user_A, user_B):
  215.     if user_A not in network or user_B not in network:
  216.         return False
  217.     if network[user_A]['Connections'] == ['']:
  218.         network[user_A]['Connections'] = user_B
  219.     else:
  220.         network[user_A]['Connections'] = network[user_A]['Connections'] + [user_B]
  221.     return network
  222.  
  223. # -----------------------------------------------------------------------------
  224. # add_new_user(network, user, games):
  225. #   Creates a new user profile and adds that user to the network, along with
  226. #   any game preferences specified in games. Assume that the user has no
  227. #   connections to begin with.
  228. #
  229. # Arguments:
  230. #   network: The network you created with create_data_structure.
  231. #   user:    String containing the users name to be added (e.g. "Dave")
  232. #   games:   List containing the user's favorite games, e.g.:
  233. #            ['Ninja Hamsters', 'Super Mushroom Man', 'Dinosaur Diner']
  234. #
  235. # Return:
  236. #   The updated network with the new user and game preferences added. If the
  237. #   user is already in the network, update their game preferences as necessary.
  238.  
  239. def add_new_user(network, user, games):
  240.     if user in network:
  241.         for game in games:
  242.             if game not in network[user]['Likes']:
  243.                 network[user]['Likes'].append(game)
  244.     else:
  245.         network[user] = {'Connections': [], 'Likes': games} # New users won't have any connections
  246.     return network
  247.  
  248. # -----------------------------------------------------------------------------
  249. # get_secondary_connections(network, user):
  250. #   Finds all the secondary connections, i.e. connections of connections, of a
  251. #   given user.
  252. #
  253. # Arguments:
  254. #   network: The network you created with create_data_structure.
  255. #   user:    String containing the name of a user.
  256. #
  257. # Return:
  258. #   A list containing the secondary connections (connections of connections).
  259. #   If the user is not in the network, return None. If a user has no primary
  260. #   connections to begin with, you should return an empty list.
  261. #
  262. # NOTE:
  263. #   It is OK if a user's list of secondary connections includes the user
  264. #   himself/herself. It is also OK if the list contains a user's primary
  265. #   connection that is a secondary connection as well.
  266.  
  267. def get_secondary_connections(network, user):
  268.     '''Returns a list of friends of friends of a user'''
  269.     if user not in network:
  270.         return None
  271.     agg = []
  272.     for primary in get_connections(network, user):        # Get friends
  273.         for second in get_connections(network, primary):  # Get friends of friends
  274.             if second not in agg:                         # Don't add the same friend more than once
  275.                 agg.append(second)
  276.     return agg
  277.  
  278. # -----------------------------------------------------------------------------    
  279. # connections_in_common(network, user_A, user_B):
  280. #   Finds the number of people that user_A and user_B have in common.
  281. #  
  282. # Arguments:
  283. #   network: The network you created with create_data_structure.
  284. #   user_A:    String containing the name of user_A.
  285. #   user_B:    String containing the name of user_B.
  286. #
  287. # Return:
  288. #   The number of connections in common (integer). Should return False if
  289. #   user_A or user_B are not in network.
  290.  
  291. def connections_in_common(network, user_A, user_B):
  292.     '''Returns an int of forward friends in common'''
  293.     if user_A not in network or user_B not in network:
  294.         return False
  295.     count = 0
  296.     A = get_connections(network, user_A)
  297.     B = get_connections(network, user_B)
  298.     for friend in A:                            # It doesn't matter which friendlist you use as long as you use the other in the next line
  299.         if friend in B:
  300.             count += 1
  301.     return count
  302.  
  303. # -----------------------------------------------------------------------------
  304. # path_to_friend(network, user, connection):
  305. #   Finds the connections path from user_A to user_B. It has to be an existing
  306. #   path but it DOES NOT have to be the shortest path.
  307. #                   Solve this problem using recursion.
  308. # Arguments:
  309. #   network: The network you created with create_data_structure.
  310. #   user_A:  String holding the starting username ("Abe")
  311. #   user_B:  String holding the ending username ("Zed")
  312. #
  313. # Return:
  314. #   A List showing the path from user_A to user_B. If such a path does not
  315. #   exist, return None
  316. #
  317. # Sample output:
  318. #   >>> print path_to_friend(network, "Abe", "Zed")
  319. #   >>> ['Abe', 'Gel', 'Sam', 'Zed']
  320. #   This implies that Abe is connected with Gel, who is connected with Sam,
  321. #   who is connected with Zed.
  322. #
  323. # NOTE:
  324. #   You must solve this problem using recursion!
  325. #
  326. # Hint:
  327. #   Be careful how you handle connection loops, for example, A is connected to B.
  328. #   B is connected to C. C is connected to B. Make sure your code terminates in
  329. #   that case.
  330.  
  331. # This is a depth first search
  332. def path_to_friend(network, user_A, user_B, connection=None, expanded=None):
  333.     if not expanded:                            # This statement will only ever be True on the first run of the code
  334.         connection, expanded = [], []
  335.         connection.append(user_A)
  336.         expanded.append(user_A)
  337.     #print connection                           # - ### - Try out this print statement using example below. You can see the stack (connections) growing and shrinking.
  338.     if connection:                              # If the stack isn't empty. Once the stack is empty, you know there are no possible connections
  339.         if user_B == connection[-1]:            # Base case
  340.             return connection
  341.         friends = get_connections(network, connection[-1]) # Get friends of the last person in the connection
  342.         # There are two "for friend in friends" statements. This is intentional. We want to check all of the friends two separate times
  343.         for friend in friends:                  # Check ALL possible current edges (friends) to see if we've reached the goal state
  344.             if friend == user_B:
  345.                 connection.append(user_B)
  346.                 return connection
  347.         for friend in friends:                   # If nothing is the goal state, check ALL the nodes to expand to try again
  348.             if friend not in expanded:
  349.                 connection.append(friend)
  350.                 expanded.append(friend)
  351.                 return path_to_friend(network, user_A, user_B, connection, expanded)
  352.         connection.pop()                         # This only evaluates if the stack has reached a dead end, in which case it takes a step back
  353.         return path_to_friend(network, user_A, user_B, connection, expanded)        
  354.     return None                                  # return None if no connection is found
  355.  
  356. # Make-Your-Own-Procedure (MYOP)
  357. # -----------------------------------------------------------------------------
  358. # Your MYOP should either perform some manipulation of your network data
  359. # structure (like add_new_user) or it should perform some valuable analysis of
  360. # your network (like path_to_friend). Don't forget to comment your MYOP. You
  361. # may give this procedure any name you want.
  362.  
  363. # Replace this with your own procedure! You can also uncomment the lines below
  364. # to see how your code behaves. Have fun!
  365.  
  366. # This will find the shortest path from user_A to user_B.
  367. # My first programming class was Intro to Artificial Intelligence where I learned about DFS, BFS, stacks, and queues.
  368. # This is especially different from path_to_friend because it holds a long list of lists of strings - path_to_friend only carries one list of strings
  369.  
  370. def breadth_first_search(network, user_A, user_B):
  371.     connection = [user_A]
  372.     queue = [connection]                                   # queue will be a list of lists
  373.     while queue:
  374.         connection = queue.pop(0)                          # Dequeuing (popping the first element instead of the last) a list
  375.         last_node = connection[-1]                         # Analyzing that list for the goal state
  376.         #print "Connection is " + str(connection)
  377.         if last_node == user_B:
  378.             return connection
  379.         for friend in get_connections(network, last_node): # Adds lists to the queue
  380.             if friend not in connection:
  381.                 agg = []
  382.                 agg = connection + [friend]
  383.                 queue.append(agg)
  384.     return None
  385.  
  386. #network = create_data_structure(example_input_alternate)
  387. #print "BFS from Freda to Jennie is " + str(breadth_first_search(network, "Freda", "Jennie"))
  388.  
  389. #for key in network:
  390. #    for key2 in network:
  391. #        if key != key2:
  392. #            print "Path from " + str(key) + " to " + str(key2) + " is " + str(breadth_first_search(network, key, key2))
  393. #            print
  394.  
  395. def suggest_friends(network, user):
  396.     '''Returns a suggested friend based on shared likes and mutual friends.
  397.    The connection is always user --> mutual friend --> suggested friend.
  398.    It MIGHT OR MIGHT NOT be user --> mutual friend --> suggested friend --> mutual friend
  399.    '''
  400.     mutual, suggested, games = '', '', ''
  401.     friends_of_friends = get_secondary_connections(network, user)
  402.     for friend in friends_of_friends:
  403.         if friend not in get_connections(network, user) and friend != user: # If user is not already friends with suggested
  404.             for game in network[friend]['Likes']:
  405.                 if game in network[user]['Likes']:
  406.                     games = game
  407.             if len(games):
  408.                 suggested = friend
  409.                 mutual = breadth_first_search(network, user, suggested)[1] # This instance of BFS will always create a list of length 3
  410.                 return str(user) + "! You have a suggested friend, " + str(friend) + ". You both like to play " + str(games) + ". You have a mutual friend, " + str(mutual) + "."
  411.     return "Try again later, " + str(user) + ". There are no suggested friends for you at this time"
  412.  
  413. #for user in network:
  414. #    print suggest_friends(network, user)
  415. #    print
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement