Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Please use PYTHON only and follow all the following instructions carefully. Than

ID: 3607096 • Letter: P

Question

Please use PYTHON only and follow all the following instructions carefully. Thank you

Requirements

Background info (for your reference):

Problem statements:

For your reference:

Please make sure that it can pass all the test cases as follows:   https://repl.it/N7up/1

Also, the csv files mentioned are as follows:

Restrictions no modules may be imported. (this definitely includes the csv module - do the work directly!) Allowed * all basic expressions and statements file reading: open(), close(), read(), readline), readlines (), with syntax dictionaries: len, get, clear, copy, keys, values, items, pop, popitem, update all sets and set operations; all exception handling blocks/raises. functions: len(), range(), min), max), enumerate(), int), and any functions you write list methods: remove(), insert(), append(), extend), pop(), index() string methods: split), endswith), startswith), join(), insert, index) more: sorted(), sort(), reversed(), reverse() calling other functions of the project (and your own defined helper functions). Please do this! ) Hint In our solution, we only used range, len, int, open, close, readlines, .get(), .items, .remove)., .append), .split(), .sort().

Explanation / Answer

def read_file(filename):
  
   #Creates empty dictionary.
   database = {}
   #Creates empty dictionary.
   dict_pop = {}
   #Creates empty tuple.
   name_tup = ()
   #Creates empty list.
   data_split = []

   #Opens file.
   data_file = open(filename, 'r')
   #Reads lines of the file and creates a list of them.
   data_list = data_file.readlines()
   #Closes file.
   data_file.close()
   #Removes the first element in the list of lines.
   data_list.pop(0)

   #Iterates over the elements in data_list.
   for i in data_list:
       #Removes any new line in the sring.
       i = i.replace(' ', '')
       #Removes any quotation marks in the sring.
       i = i.replace('"', '')
       #Splits the string at commas and creates a new list.
       new_split = i.split(',')
       #Checks if the new_split has any elements that are supposed to have
       #commas in them. If there are then it adds the commas. It then appends
       #the new_split to the list data_split.
       if len(new_split) > 4:
           new_split[2] = new_split[2] + new_split[3]
           new_split.remove(new_split[3])
           new_split[2] = new_split[2].replace(' ',', ')
           data_split.append(new_split)
       else:
           data_split.append(new_split)

   #Iterates over the elements in data_split.
   for i in data_split:
       #Creates key for database dictionary.
       name_tup = (i[2],i[1])
       #Creates value for database dictionary.
       dict_pop = {int(i[0]):(int(i[3]), None)}
       #Checks if the key is already in the dictionary. If it is then it
       #updates its value. If its not then it creates it.
       if name_tup in database:
           database[name_tup].update(dict_pop)
       else:
           database[name_tup] = dict_pop
   return database

def add_name(db, name, gender, year, count):
       #Creates empty dictionary.
   dict_pop = {}
   #Creates tuple with name and gender as elements.
   name_tup = (name,gender)
   #Checks if the key is already in the dictionary and adds to it.
   if name_tup in db:
        db[name_tup][year] = (count, None)
   #Creates a new key in the dictionary.
   else:
        dict_pop[year] = (count, None)
        db[name_tup] = dict_pop
   return

def find_all_years(db):
   '''
   This function accepts an existing database db, finds all years included in
   it anywhere and return a list of years in ascending order.
   '''
   #Creates empty list.
   year_list = []
   #Iterates over the values in db.
   for i in db.values():
       #Iterates over the dictionary i.
        for j in i:
           #Checks it key is not in list and then appends it.
            if j not in year_list:
                year_list.append(j)
                year_list.sort()
   return year_list

def new_names(db, gender, old_year, new_year):
   #Creates empty list.
   name_list = []
   #Iterates over the dictionary db.
   for i in db:
       #Checks if old_year and new year are in the nested dictionary.
        if (old_year not in db[i]) and (new_year in db[i]):
           #Checks if a name is in the name_list. If not, it appends it.
              if i[0] not in name_list:
                  name_list.append(i[0])
                  name_list.sort()
   return name_list

def rank_names_for_one_year(db, year):
       #Creates empty list.
   male_list = []
   #Creates empty list.
   female_list = []
   #Iterates over the dictionary db.
   for i in db:
        gender = i[1]
        #Checks the gender of the name and appends its count to the
        #appropriate gender list.
        if (gender == 'MALE') and (year in db[i]):
            male_list.append(db[i][year][0])
        elif (gender == 'FEMALE') and (year in db[i]):
            female_list.append(db[i][year][0])
  
   #Reverses both gender lists and inserts a 0 in their first indexes.
   male_list.sort(reverse=True)
   male_list.insert(0,0)
   female_list.sort(reverse=True)
   female_list.insert(0,0)
  
   #Iterates over the dictionary db.
   for i in db:
        gender = i[1]
        #Checks the gender of the name and updates the value of the year key
        #with a count and rank tuple.
        if (gender == 'MALE') and (year in db[i]):
            db[i][year] = (db[i][year][0],male_list.index(db[i][year][0]))
        elif (gender == 'FEMALE') and (year in db[i]):
            db[i][year] = (db[i][year][0],female_list.index(db[i][year][0]))
   return

def rank_names(db):
   '''
   This function accepts an existing database and ranks all names for all years
   of data present, making the database become ranked.
   '''
   #Iterates over the dictionary db.
   for i in db:
       #Iterates over the nested dictionary db[i].
       for j in db[i]:
           #Calls the rank_names_for_one_year() function and passes j as year.
           rank_names_for_one_year(db,j)
   return

def popularity_by_name(rdb, name, gender):
   '''
   This function accepts a ranked database, name, and gender. It finds the
   popularity counts for all years included in the database for name, assembles
   them in a list of tuples (year, rank), and returns the list.
   '''
   #Creates empty list.
   tup_list = []
   #Creates empty tuple.
   rank_tup = ()
   #Iterates over the dictionary rdb.
   for i in rdb:
       #Checks if the key in the dictionary matches the given name and gender.
       if i == (name, gender):
            #Iterates over the nested dictionary rdb[i].
           for j in rdb[i]:
               #Appends tup_list with a tuple that includes the year and rank.
               rank_tup = (j, rdb[i][j][1])
               tup_list.append(rank_tup)
   return tup_list

def popularity_by_year(rdb, gender, year, top=10):
   '''
   This function accepts a ranked database, gender, year, and top. For the
   specified year, it finds the top popular names and returns them in a sorted
   list of tuples (rank, name).
   '''
   #Creates empty list.
   tup_list = []
   #Creates empty tuple.
   rank_tup = ()
   #Iterates over the dictionary rdb.
   for i in rdb:
       #Checks if the gender of the key matches the given gender and if the
       #rank is less than or equal to the given top.
       if (i[1] == gender) and (rdb[i][year][1] <= top):
           #Appends tup_list with a tuple that includes the rank and name.
           rank_tup = (rdb[i][year][1], i[0])
           tup_list.append(rank_tup)
   #Sorts tup_list.
   tup_list.sort()
   return tup_list

def always_popular_names(rdb, gender, years=None, top=10):
   '''
   This function accepts a ranked database, gender, a list of years and a top
   threshold. It searches in the database for nmaes that are always ranked
   within (and including) top for all the years in the given list and returns
   them as a sorted list of strings.
   '''
   #Creates empty list.
   name_list = []
   #Creates empty list.
   year_list = []
   #Initializes ans variable.
   ans = 0
   #Checks if a list of years is provided.
   if years != None:
        #Iterates over the dictionary rdb.
        for i in rdb:
           #Iterates over the list years.
            for j in years:
               #Checks if the gender of the key matches the given gender, if
               #the given years are keys in the nested dictionary, and if the
               #name isn't already in the list names_list.
                if ((i[1] == gender) and (j in rdb[i]) and
                   (i[0] not in name_list)):
                   #Checks if the rank for the year is greater than top. If
                   #it is, then the ans is False and the loop is broken.
                    if (rdb[i][j][1] > top):
                        ans = False
                        break
                    else:
                        ans = True
            #Checks if the ans is true and adds the name to name_list.
            if ans == True:
                name_list.append(i[0])
   else:
       #Creates empty list.
       j_list = []
       #Iterates over the dictionary rdb.
       for i in rdb:
           #Iterates over the nested dictionary rdb[i].
           for j in rdb[i]:
               #Checks if j is not in year_list.
               if j not in year_list:
                   year_list.append(j)
        #Iterates over the dictionary rdb.
       for i in rdb:
           #Iterates over the nested dictionary rdb[i].
           for j in rdb[i]:
               #Checks if j is not in j_list.
               if j not in j_list:
                   j_list.append(j)
            #Checks if the gender of the key matches the given gender, if
            #the length of year_list and j_list are the same, and if the
            #name is already in the list names_list.
           if ((len(year_list) == len(j_list)) and (i[1] == gender) and
               (i[0] not in name_list)):
               if (rdb[i][j][1] > top):
                   ans = False
                   break
               else:
                   ans = True
           #Checks if the ans is true and adds the name to name_list. It then
           #resets j_list and ans.
           if ans == True:
               name_list.append(i[0])
               j_list = []
               ans = False
   #Sorts names_list.       
   name_list.sort()
   return name_list
  
def increasing_rank_names(rdb, gender, old_year, new_year):
   '''
   This function accepts a ranked database, gender, and two years. It searches
   in database for names whose rank gets promoted from old_year to new_year,
   and returns them as a sorted list of strings.
   '''
   #Creates empty list.
   name_list = []
   #Iterates over the dictionary rdb.
   for i in rdb:
       #Checks if the gender of the key matches the given gender and if the
       #given years are keys in the nested dictionary.
       if (i[1] == gender) and (old_year in rdb[i]) and (new_year in rdb[i]):
           #Checks if the rank for the new year is higher than the rank of the
           #old year and then appends name_list with a name.
            if (rdb[i][old_year][1] > rdb[i][new_year][1]):
                name_list.append(i[0])
   #Sorts name_list.
   name_list.sort()
   return name_list

def merge_databases(db1, db2):
   #Creates empty list.
   merged_database = {}
   #Iterates over the dictionary db1.
   for i in db1:
       #Iterates over the dictionary db2.
       for j in db2:
           #Checks if the keys of db1 and db2 are the same.
           if i == j:
               #Updates the values of the keys of db1 with those of db2.
                db1[i].update(db2[j])
                #Creates key in merged_database with value of key in db1.
                merged_database[i] = db1[i]
           else:
               #Creates key in merged_database with value of key in db1.
               merged_database[i] = db1[i]
               #Creates key in merged_database with value of key in db2.
               merged_database[j] = db2[j]
   #Calls the rank_names() function to rank merged_database.
   rank_names(merged_database)
   return merged_database