adding starter code
This commit is contained in:
248
hws/03_amazon_prime/main.cpp
Normal file
248
hws/03_amazon_prime/main.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
#include <sstream>
|
||||
#include "recommendation.h"
|
||||
|
||||
class Movie {
|
||||
public:
|
||||
int movieId;
|
||||
std::string title;
|
||||
};
|
||||
|
||||
class TVShow {
|
||||
public:
|
||||
int tvShowId;
|
||||
std::string title;
|
||||
};
|
||||
|
||||
// Oscar-winning movies
|
||||
Movie movies[] = {
|
||||
{0, "Elvis"},
|
||||
{1, "The Shawshank Redemption"},
|
||||
{2, "The Godfather"},
|
||||
{3, "Schindler's List"},
|
||||
{4, "The Lord of the Rings: The Return of the King"},
|
||||
{5, "Forrest Gump"},
|
||||
{6, "Titanic"},
|
||||
{7, "Gladiator"},
|
||||
{8, "The Departed"},
|
||||
{9, "12 Years a Slave"},
|
||||
{10, "Green Book"},
|
||||
{11, "The Silence of the Lambs"},
|
||||
{12, "The Sound of Music"},
|
||||
{13, "Amadeus"},
|
||||
{14, "The Shape of Water"},
|
||||
{15, "Braveheart"},
|
||||
{16, "The English Patient"},
|
||||
{17, "Moonlight"},
|
||||
{18, "Argo"},
|
||||
{19, "Birdman"},
|
||||
{20, "No Country for Old Men"},
|
||||
{21, "A Beautiful Mind"},
|
||||
{22, "Spotlight"},
|
||||
{23, "The King's Speech"},
|
||||
{24, "Platoon"},
|
||||
{25, "Dances with Wolves"},
|
||||
{26, "Gandhi"},
|
||||
{27, "The Green Mile"},
|
||||
{28, "The Pianist"},
|
||||
{29, "The Bridge on the River Kwai"},
|
||||
{30, "West Side Story"},
|
||||
{31, "The Godfather: Part II"},
|
||||
{32, "Crouching Tiger, Hidden Dragon"},
|
||||
{33, "The Hurt Locker"},
|
||||
{34, "Slumdog Millionaire"},
|
||||
{35, "Million Dollar Baby"},
|
||||
{36, "Rain Man"},
|
||||
{37, "Rocky"},
|
||||
{38, "Inception"},
|
||||
{39, "Chariots of Fire"},
|
||||
{40, "The Great Gatsby"},
|
||||
{41, "All About Eve"},
|
||||
{42, "One Flew Over the Cuckoo's Nest"},
|
||||
{43, "The Apartment"},
|
||||
{44, "The French Connection"},
|
||||
{45, "The Grand Budapest Hotel"},
|
||||
{46, "Rebecca"},
|
||||
{47, "Gone with the Wind"},
|
||||
{48, "Casablanca"},
|
||||
{49, "Ben-Hur"},
|
||||
{50, "Lawrence of Arabia"},
|
||||
{51, "The Phantom of the Opera"},
|
||||
{52, "The Godfather: Part III"},
|
||||
{53, "Annie Hall"},
|
||||
{54, "Out of Africa"},
|
||||
{55, "My Fair Lady"},
|
||||
{56, "The Life of Emile Zola"},
|
||||
{57, "On the Waterfront"},
|
||||
{58, "The Best Years of Our Lives"},
|
||||
{59, "The Deer Hunter"},
|
||||
{60, "Midnight Cowboy"},
|
||||
{61, "American Beauty"},
|
||||
{62, "Gigi"},
|
||||
{63, "Going My Way"},
|
||||
{64, "Gentleman's Agreement"},
|
||||
{65, "From Here to Eternity"},
|
||||
{66, "Oliver!"},
|
||||
{67, "Patton"},
|
||||
{68, "The Artist"},
|
||||
{69, "The Family Plan"},
|
||||
{70, "A Man for All Seasons"},
|
||||
{71, "Lincoln"},
|
||||
{72, "The Greatest Show on Earth"},
|
||||
{73, "An American in Paris"},
|
||||
{74, "Kramer vs. Kramer"},
|
||||
{75, "The Descendants"},
|
||||
{76, "Driving Miss Daisy"},
|
||||
{77, "All Quiet on the Western Front"},
|
||||
{78, "The Greatest Showman"},
|
||||
{79, "Mutiny on the Bounty"},
|
||||
{80, "The Lost Weekend"},
|
||||
{81, "The Batman"},
|
||||
{82, "Aquaman and the Lost Kingdom"},
|
||||
{83, "Parasite"},
|
||||
{84, "Ordinary People"},
|
||||
{85, "Wonka"},
|
||||
{86, "Tom Jones"},
|
||||
{87, "The Last Emperor"},
|
||||
{88, "Don't Look Up"},
|
||||
{89, "Chicago"},
|
||||
{90, "The Revenant"},
|
||||
{91, "Darkest Hour"},
|
||||
{92, "Manchester by the Sea"},
|
||||
{93, "Hacksaw Ridge"},
|
||||
{94, "The Theory of Everything"},
|
||||
{95, "Midnight in Paris"},
|
||||
{96, "Coda"},
|
||||
{97, "Catch Me If You Can"},
|
||||
{98, "Nomadland"},
|
||||
{99, "The Graduate"},
|
||||
{100, "Pearl Harbor"},
|
||||
{101, "Dune"},
|
||||
{102, "King Richard"},
|
||||
{103, "Drive My Car"},
|
||||
{104, "The Fabelmans"},
|
||||
{105, "The Long Goodbye"},
|
||||
{106, "Nightmare Alley"},
|
||||
{107, "A Star is Born"},
|
||||
{108, "Top Gun: Maverick"},
|
||||
{109, "Everything Everywhere All at Once"},
|
||||
};
|
||||
|
||||
// Emmy Award-winning TV shows
|
||||
TVShow tvShows[] = {
|
||||
{0, "Little Women"},
|
||||
{1, "The West Wing"},
|
||||
{2, "The Sopranos"},
|
||||
{3, "Breaking Bad"},
|
||||
{4, "Game of Thrones"},
|
||||
{5, "The Twilight Zone"},
|
||||
{6, "The Simpsons"},
|
||||
{7, "Friends"},
|
||||
{8, "The Mary Tyler Moore Show"},
|
||||
{9, "M*A*S*H"},
|
||||
{10, "The Wire"},
|
||||
{11, "The Marvelous Mrs. Maisel"},
|
||||
{12, "The Crown"},
|
||||
{13, "Fleabag"},
|
||||
{14, "Stranger Things"},
|
||||
{15, "The Mandalorian"},
|
||||
{16, "Veep"},
|
||||
{17, "The Big Bang Theory"},
|
||||
{18, "Homeland"},
|
||||
{19, "The Handmaid's Tale"},
|
||||
{20, "The Office (U.S.)"},
|
||||
{21, "Cheers"},
|
||||
{22, "The Golden Girls"},
|
||||
{23, "I Love Lucy"},
|
||||
{24, "The Americans"},
|
||||
{25, "Sherlock"},
|
||||
{26, "Fargo"},
|
||||
{27, "The People v. O.J. Simpson: American Crime Story"},
|
||||
{28, "Black Mirror"},
|
||||
{29, "Westworld"},
|
||||
{30, "Mad Men"},
|
||||
{31, "The Boys"},
|
||||
{32, "Better Call Saul"},
|
||||
{33, "Hand of God"},
|
||||
{34, "The Good Place"},
|
||||
{35, "Atlanta"},
|
||||
{36, "Barry"},
|
||||
{37, "The Office (UK)"},
|
||||
{38, "Fawlty Towers"},
|
||||
{39, "Monty Python's Flying Circus"},
|
||||
{40, "The Daily Show with Jon Stewart"},
|
||||
{41, "Late Night with David Letterman"},
|
||||
{42, "The Tonight Show Starring Johnny Carson"},
|
||||
{43, "Saturday Night Live"},
|
||||
{44, "The X-Files"},
|
||||
{45, "Downton Abbey"},
|
||||
{46, "The Big C"},
|
||||
{47, "Six Feet Under"},
|
||||
{48, "Ray Donovan"},
|
||||
{49, "Curb Your Enthusiasm"},
|
||||
{50, "Keeping Up with the Kardashians"},
|
||||
{51, "The Twilight Zone (2002)"},
|
||||
{52, "Dexter"},
|
||||
{53, "House of Cards"},
|
||||
{54, "Boardwalk Empire"},
|
||||
{55, "The Newsroom"},
|
||||
{56, "Black-ish"},
|
||||
{57, "The Good Wife"},
|
||||
{58, "Parks and Recreation"},
|
||||
{59, "Pose"},
|
||||
{60, "This Is Us"},
|
||||
{61, "Watchmen"},
|
||||
{62, "The Office (U.K.)"},
|
||||
{63, "Vigil"},
|
||||
{64, "The Ellen DeGeneres Show"},
|
||||
{65, "True Detective"},
|
||||
{66, "The Cosby Show"},
|
||||
{67, "The Witcher"},
|
||||
{68, "Succession"},
|
||||
{69, "The Tonight Show Starring Jimmy Fallon"},
|
||||
{70, "Scrubs"},
|
||||
{71, "Mindhunter"},
|
||||
{72, "Euphoria"},
|
||||
{73, "The Umbrella Academy"},
|
||||
{74, "Arrested Development"},
|
||||
{75, "Jury Duty"},
|
||||
{76, "Seinfeld"},
|
||||
{77, "Great News"},
|
||||
{78, "Killers of the Flower Moon"},
|
||||
{79, "House"},
|
||||
{80, "Ted Lasso"},
|
||||
{81, "How I Met Your Mother"},
|
||||
{82, "Unbreakable Kimmy Schmidt"},
|
||||
{83, "All in the Family"},
|
||||
{84, "The Leftovers"},
|
||||
{85, "Wednesday"},
|
||||
{86, "Frasier"},
|
||||
{87, "Modern Family"},
|
||||
{88, "Better Things"},
|
||||
{89, "Brooklyn Nine-Nine"},
|
||||
{90, "Everybody Loves Raymond"},
|
||||
{91, "Taxi"},
|
||||
{92, "Late Night with Seth Meyers"},
|
||||
{93, "30 Rock"},
|
||||
{94, "Community"},
|
||||
{95, "Squid Game"},
|
||||
{96, "Will & Grace"},
|
||||
{97, "Schitt's Creek"},
|
||||
{98, "Get Smart"},
|
||||
{99, "The Monkees"},
|
||||
};
|
||||
|
||||
// this function reads the one line, and update row i of the matrix.
|
||||
void process_one_line(int** matrix, int i, std::string& line){
|
||||
std::istringstream iss(line);
|
||||
// process each (index, value) pair
|
||||
int index, value;
|
||||
char openParen, comma, closeParen;
|
||||
// when used with integers, it reads characters until it encounters a non-digit character or whitespace. However, when used with characters, it reads a single character.
|
||||
while (iss >> openParen >> index >> comma >> value >> closeParen) {
|
||||
matrix[i][index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
}
|
||||
161
hws/03_amazon_prime/recommendation.cpp
Normal file
161
hws/03_amazon_prime/recommendation.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#include "recommendation.h"
|
||||
#include <cmath>
|
||||
|
||||
// implement collaborative filtering to recommend movies to a user based on the ratings of similar users. The predicted ratings are used to identify movies that the target user might like, and the recommendations are filtered based on a threshold.
|
||||
// this function returns a list of movie IDs recommended for the user, in recommendedMovies; it assumes the caller would allocate memory for recommendedMovies.
|
||||
void RecommendationSystem::recommendMovies(int userId, int numRecommendations, int* recommendedMovies) const {
|
||||
|
||||
// to count how many movies are recommended.
|
||||
int index = 0;
|
||||
// check if the given userId is valid
|
||||
if (userId < 0 || userId >= numUsers) {
|
||||
// handle invalid userId
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate similarity scores between the target user (userId) and other users
|
||||
// compute the similarity between the target user and all other users based on their movie ratings using the cosine similarity measure. The resulting similarity scores are stored in the similarityScores array. This information can then be used to recommend movies to the target user based on the preferences of similar users.
|
||||
double similarityScores[numUsers];
|
||||
for(int i=0; i<numUsers; i++){
|
||||
// initialize every element in the array to 0.0.
|
||||
similarityScores[i] = 0.0;
|
||||
};
|
||||
|
||||
|
||||
for (int otherUserId = 0; otherUserId < numUsers; ++otherUserId) {
|
||||
if (otherUserId != userId) {
|
||||
// calculate similarity using a simple dot product
|
||||
double dotProduct = 0.0;
|
||||
double magnitudeA = 0.0;
|
||||
double magnitudeB = 0.0;
|
||||
|
||||
for (int movieId = 0; movieId < numMovies; ++movieId) {
|
||||
dotProduct += userMovieRatingsMatrix[userId][movieId] * userMovieRatingsMatrix[otherUserId][movieId];
|
||||
magnitudeA += userMovieRatingsMatrix[userId][movieId] * userMovieRatingsMatrix[userId][movieId];
|
||||
magnitudeB += userMovieRatingsMatrix[otherUserId][movieId] * userMovieRatingsMatrix[otherUserId][movieId];
|
||||
}
|
||||
|
||||
// std::cout << "dotProduct is " << dotProduct << " magnitudeA is " << magnitudeA << " magnitudeB is " << magnitudeB << " " << std::endl;
|
||||
// avoid division by zero
|
||||
// the similarity should be in the range of [0,1], with 1 being perfectly similar, and 0 being no similarity.
|
||||
double similarity = (magnitudeA > 0.0 && magnitudeB > 0.0) ? dotProduct / (sqrt(magnitudeA) * sqrt(magnitudeB)) : 0.0;
|
||||
// store the similarity score
|
||||
similarityScores[otherUserId] = similarity;
|
||||
}
|
||||
}
|
||||
|
||||
// identify users with high similarity and recommend movies they liked
|
||||
for (int movieId = 0; movieId < numMovies; ++movieId) {
|
||||
// user hasn't rated this movie: it's pointless to recommend a movie to the user if the user has already rated this movie.
|
||||
if (userMovieRatingsMatrix[userId][movieId] == 0) {
|
||||
|
||||
// use these two variables to calculate a weighted sum of ratings from similar users
|
||||
// and the total similarity across those users.
|
||||
double weightedSum = 0.0;
|
||||
double totalSimilarity = 0.0;
|
||||
|
||||
int count = 0;
|
||||
// calculate a weighted sum of ratings from similar users
|
||||
for (int otherUserId = 0; otherUserId < numUsers; ++otherUserId) {
|
||||
// userMovieRatings[otherUserId][movieId] > 0.0 means we only consider users who have rated this movie
|
||||
// users who have not rated this movie should not be contributing to the totalSimilarity.
|
||||
if (otherUserId != userId && userMovieRatingsMatrix[otherUserId][movieId] > 0) {
|
||||
// similar users therefore have a higher weight.
|
||||
// in other words, the ratings from similar users contribute more to predicting the target user's rating.
|
||||
weightedSum += similarityScores[otherUserId] * userMovieRatingsMatrix[otherUserId][movieId];
|
||||
totalSimilarity += std::abs(similarityScores[otherUserId]);
|
||||
count++;
|
||||
// std::cout << "weightedSum is " << weightedSum << " similarity is " << similarityScores[otherUserId] << " total similarity is " << totalSimilarity << " count is " << count << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// avoid division by zero
|
||||
double predictedRating = (totalSimilarity > 0.0) ? weightedSum / totalSimilarity : 0.0;
|
||||
|
||||
// for simplicity, consider recommending movies with predicted ratings greater than a threshold
|
||||
if (predictedRating > 3.0) {
|
||||
recommendedMovies[index] = movieId;
|
||||
index++;
|
||||
}
|
||||
|
||||
// stop when the desired number of recommendations is reached
|
||||
if (index >= numRecommendations) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// this function returns a list of tv show IDs recommended for the user, in recommendedShows; it assumes the caller would allocate memory for recommendedShows.
|
||||
void RecommendationSystem::recommendShows(int userId, int numRecommendations, int* recommendedShows) const {
|
||||
// to count how many movies are recommended.
|
||||
int index = 0;
|
||||
// check if the given userId is valid
|
||||
if (userId < 0 || userId >= numUsers) {
|
||||
// handle invalid userId
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate similarity scores between the target user (userId) and other users
|
||||
// compute the similarity between the target user and all other users based on their show ratings using the cosine similarity measure. The resulting similarity scores are stored in the similarityScores array. This information can then be used to recommend shows to the target user based on the preferences of similar users.
|
||||
double similarityScores[numUsers];
|
||||
for(int i=0; i<numUsers; i++){
|
||||
// initialize every element in the array to 0.0.
|
||||
similarityScores[i] = 0.0;
|
||||
};
|
||||
|
||||
for (int otherUserId = 0; otherUserId < numUsers; ++otherUserId) {
|
||||
if (otherUserId != userId) {
|
||||
// Calculate similarity using a simple dot product
|
||||
double dotProduct = 0.0;
|
||||
double magnitudeA = 0.0;
|
||||
double magnitudeB = 0.0;
|
||||
|
||||
for (int showId = 0; showId < numShows; ++showId) {
|
||||
dotProduct += userShowRatingsMatrix[userId][showId] * userShowRatingsMatrix[otherUserId][showId];
|
||||
magnitudeA += userShowRatingsMatrix[userId][showId] * userShowRatingsMatrix[userId][showId];
|
||||
magnitudeB += userShowRatingsMatrix[otherUserId][showId] * userShowRatingsMatrix[otherUserId][showId];
|
||||
}
|
||||
|
||||
// avoid division by zero
|
||||
double similarity = (magnitudeA > 0.0 && magnitudeB > 0.0) ? dotProduct / (sqrt(magnitudeA) * sqrt(magnitudeB)) : 0.0;
|
||||
|
||||
// store the similarity score
|
||||
similarityScores[otherUserId] = similarity;
|
||||
}
|
||||
}
|
||||
|
||||
// identify users with high similarity and recommend shows they liked
|
||||
for (int showId = 0; showId < numShows; ++showId) {
|
||||
if (userShowRatingsMatrix[userId][showId] == 0) { // User hasn't rated this show
|
||||
double weightedSum = 0.0;
|
||||
double totalSimilarity = 0.0;
|
||||
|
||||
// calculate a weighted sum of ratings from similar users
|
||||
for (int otherUserId = 0; otherUserId < numUsers; ++otherUserId) {
|
||||
if (otherUserId != userId && userShowRatingsMatrix[otherUserId][showId] > 0) {
|
||||
weightedSum += similarityScores[otherUserId] * userShowRatingsMatrix[otherUserId][showId];
|
||||
totalSimilarity += std::abs(similarityScores[otherUserId]);
|
||||
}
|
||||
}
|
||||
|
||||
// avoid division by zero
|
||||
double predictedRating = (totalSimilarity > 0.0) ? weightedSum / totalSimilarity : 0.0;
|
||||
|
||||
// for simplicity, consider recommending shows with predicted ratings greater than a threshold
|
||||
if (predictedRating > 3.0) {
|
||||
recommendedShows[index] = showId;
|
||||
index++;
|
||||
}
|
||||
|
||||
// stop when the desired number of recommendations is reached
|
||||
if (index >= numRecommendations) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user