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