def user_user_recs(user_id, user_item, df, m=10):
    "\n    INPUT:\n    user_id - (int) a user id\n    m - (int) the number of recommendations you want for the user\n    \n    OUTPUT:\n    recs - (list) a list of recommendations for the user by article id\n    rec_names - (list) a list of recommendations for the user by article title\n    \n    Description:\n    Loops through the users based on closeness to the input user_id\n    For each user - finds articles the user hasn't seen before and provides them as recs\n    Does this until m recommendations are found\n    \n    Notes:\n    * Choose the users that have the most total article interactions \n    before choosing those with fewer article interactions.\n\n    * Choose articles with the articles with the most total interactions \n    before choosing those with fewer total interactions. \n   \n    "

    def get_user_articles_names_ids(user_id):
        '\n        INPUT:\n        user_id\n\n\n        OUTPUT:\n        article_ids - (list) a list of the article ids seen by the user\n        article_names - (list) a list of article names associated with the list of article ids \n                        (this is identified by the doc_full_name column in df_content)\n        \n        Description:\n        Provides a list of the article_ids and article titles that have been seen by a user\n        '
        article_ids = user_item.loc[user_id][(user_item.loc[user_id] == 1)].index.tolist()
        article_names = []
        for i in article_ids:
            try:
                title = df[(df['article_id'] == i)]['title'].unique()[0]
            except IndexError:
                title = 'None'
            article_names.append(title)
        article_ids = list(map(str, article_ids))
        return (article_ids, article_names)

    def find_similar_users():
        '        \n        OUTPUT:\n        similar_users - (list) an ordered list where the closest users (largest dot product users)\n                        are listed first\n        \n        Description:\n        Computes the similarity of every pair of users based on the dot product\n        Returns an ordered\n        \n        '
        user_item_tmp = user_item.copy()
        user_item_tmp[(user_item_tmp.isna() == True)] = 0
        row = user_item_tmp.loc[user_id]
        result_dot = (row @ user_item_tmp.T)
        result_dot.drop(labels=[user_id], inplace=True)
        most_similar_users = result_dot.sort_values(ascending=False).index.tolist()
        return most_similar_users

    def get_top_sorted_users(most_similar_users):
        '\n        INPUT:\n        most_similar_users - (list) an ordered list where the closest users (largest dot product users)\n                        are listed first \n                \n        OUTPUT:\n        neighbors_df - (pandas dataframe) a dataframe with:\n                        neighbor_id - is a neighbor user_id\n                        similarity - measure of the similarity of each user to the provided user_id\n                        num_interactions - the number of articles viewed by the user - if a u\n                        \n        Other Details - sort the neighbors_df by the similarity and then by number of interactions where \n                        highest of each is higher in the dataframe\n        \n        '
        df_user_id_grouped = df.groupby('user_id')
        df_user_id_grouped['article_id'].count().sort_values(ascending=False)
        neighbors_df = pd.DataFrame()
        neighbors_df['neighbor_id'] = most_similar_users
        user_item_tmp = user_item.copy()
        user_item_tmp[(user_item_tmp.isna() == True)] = 0
        row = user_item_tmp.loc[user_id]
        result_dot = (row @ user_item_tmp.T)
        result_dot.drop(labels=[user_id], inplace=True)
        similarity = result_dot.sort_values(ascending=False).values.tolist()[0:10]
        neighbors_df['similarity'] = similarity
        num_interactions = []
        for i in neighbors_df['neighbor_id']:
            counted_interaction = df_user_id_grouped['article_id'].count().loc[i]
            num_interactions.append(counted_interaction)
        neighbors_df['num_interactions'] = num_interactions
        neighbors_df = neighbors_df.sort_values(by=['similarity', 'num_interactions'], ascending=False)
        return neighbors_df
    recs = []
    rec_names = []
    counter = 0
    (article_ids, article_names) = get_user_articles_names_ids(user_id)
    seen_ids_set = set(article_ids)
    most_similar_users = find_similar_users()[0:10]
    neighbors_df = get_top_sorted_users(most_similar_users)
    similar_users_list = neighbors_df['neighbor_id']
    for sim_user in similar_users_list:
        if (counter < m):
            (sim_article_ids, sim_article_names) = get_user_articles_names_ids(sim_user)
            sim_user_dict = dict(zip(sim_article_ids, sim_article_names))
            sim_seen_ids_set = set(sim_article_ids)
            unseen_ids_set = sim_seen_ids_set.difference(seen_ids_set)
            for i in unseen_ids_set:
                if (counter < m):
                    recs.append(i)
                    rec_names.append(sim_user_dict[i])
                    counter += 1
    return (recs, rec_names)
INPUT:
user_id - (int) a user id
m - (int) the number of recommendations you want for the user

OUTPUT:
recs - (list) a list of recommendations for the user by article id
rec_names - (list) a list of recommendations for the user by article title

Description:
Loops through the users based on closeness to the input user_id
For each user - finds articles the user hasn't seen before and provides them as recs
Does this until m recommendations are found

Notes:
* Choose the users that have the most total article interactions 
before choosing those with fewer article interactions.

* Choose articles with the articles with the most total interactions 
before choosing those with fewer total interactions.
def user_user_recs(user_id, user_item, df, m=10):
    "\n    INPUT:\n    user_id - (int) a user id\n    m - (int) the number of recommendations you want for the user\n    \n    OUTPUT:\n    recs - (list) a list of recommendations for the user by article id\n    rec_names - (list) a list of recommendations for the user by article title\n    \n    Description:\n    Loops through the users based on closeness to the input user_id\n    For each user - finds articles the user hasn't seen before and provides them as recs\n    Does this until m recommendations are found\n    \n    Notes:\n    * Choose the users that have the most total article interactions \n    before choosing those with fewer article interactions.\n\n    * Choose articles with the articles with the most total interactions \n    before choosing those with fewer total interactions. \n   \n    "

    def get_user_articles_names_ids(user_id):
        '\n        INPUT:\n        user_id\n\n\n        OUTPUT:\n        article_ids - (list) a list of the article ids seen by the user\n        article_names - (list) a list of article names associated with the list of article ids \n                        (this is identified by the doc_full_name column in df_content)\n        \n        Description:\n        Provides a list of the article_ids and article titles that have been seen by a user\n        '
        article_ids = user_item.loc[user_id][(user_item.loc[user_id] == 1)].index.tolist()
        article_names = []
        for i in article_ids:
            try:
                title = df[(df['article_id'] == i)]['title'].unique()[0]
            except IndexError:
                title = 'None'
            article_names.append(title)
        article_ids = list(map(str, article_ids))
        return (article_ids, article_names)

    def find_similar_users():
        '        \n        OUTPUT:\n        similar_users - (list) an ordered list where the closest users (largest dot product users)\n                        are listed first\n        \n        Description:\n        Computes the similarity of every pair of users based on the dot product\n        Returns an ordered\n        \n        '
        user_item_tmp = user_item.copy()
        user_item_tmp[(user_item_tmp.isna() == True)] = 0
        row = user_item_tmp.loc[user_id]
        result_dot = (row @ user_item_tmp.T)
        result_dot.drop(labels=[user_id], inplace=True)
        most_similar_users = result_dot.sort_values(ascending=False).index.tolist()
        return most_similar_users

    def get_top_sorted_users(most_similar_users):
        '\n        INPUT:\n        most_similar_users - (list) an ordered list where the closest users (largest dot product users)\n                        are listed first \n                \n        OUTPUT:\n        neighbors_df - (pandas dataframe) a dataframe with:\n                        neighbor_id - is a neighbor user_id\n                        similarity - measure of the similarity of each user to the provided user_id\n                        num_interactions - the number of articles viewed by the user - if a u\n                        \n        Other Details - sort the neighbors_df by the similarity and then by number of interactions where \n                        highest of each is higher in the dataframe\n        \n        '
        df_user_id_grouped = df.groupby('user_id')
        df_user_id_grouped['article_id'].count().sort_values(ascending=False)
        neighbors_df = pd.DataFrame()
        neighbors_df['neighbor_id'] = most_similar_users
        user_item_tmp = user_item.copy()
        user_item_tmp[(user_item_tmp.isna() == True)] = 0
        row = user_item_tmp.loc[user_id]
        result_dot = (row @ user_item_tmp.T)
        result_dot.drop(labels=[user_id], inplace=True)
        similarity = result_dot.sort_values(ascending=False).values.tolist()[0:10]
        neighbors_df['similarity'] = similarity
        num_interactions = []
        for i in neighbors_df['neighbor_id']:
            counted_interaction = df_user_id_grouped['article_id'].count().loc[i]
            num_interactions.append(counted_interaction)
        neighbors_df['num_interactions'] = num_interactions
        neighbors_df = neighbors_df.sort_values(by=['similarity', 'num_interactions'], ascending=False)
        return neighbors_df
    recs = []
    rec_names = []
    counter = 0
    (article_ids, article_names) = get_user_articles_names_ids(user_id)
    seen_ids_set = set(article_ids)
    most_similar_users = find_similar_users()[0:10]
    neighbors_df = get_top_sorted_users(most_similar_users)
    similar_users_list = neighbors_df['neighbor_id']
    for sim_user in similar_users_list:
        if (counter < m):
            (sim_article_ids, sim_article_names) = get_user_articles_names_ids(sim_user)
            sim_user_dict = dict(zip(sim_article_ids, sim_article_names))
            sim_seen_ids_set = set(sim_article_ids)
            unseen_ids_set = sim_seen_ids_set.difference(seen_ids_set)
            for i in unseen_ids_set:
                if (counter < m):
                    recs.append(i)
                    rec_names.append(sim_user_dict[i])
                    counter += 1
    return (recs, rec_names)