#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define food_count 4
#define load_user_database {{0, 5, 2, 8}, {1, 2, 0, 0}, {0, 0, 4, 9}, {1, 4, 0, 10}};
using namespace std;
class FooRe
{
private:
int **user_data;
int user_count;
double **similality;
int save_date;
int system_time;
int save_time;
int days[12];
double pearson(int, int);
double prediction(int, int);
int collaborative_filtering(int);
int cac_remain_food(int);
int evaluated_FoodRecommendation(int);
int evaluated_FoodRecommendation_function(int, int[], int);
int evaluate_can_exe(int);
int rand_recommend(int);
int check_data(int);
int reco_time(int);
int cac_system_time();
int cac_user_time();
int cac_time(int, int);
public:
FooRe();
~FooRe();
int FoodRecommendation(int);
int return_time(int, int);
};
FooRe::FooRe()
{
int user_database[][food_count] = load_user_database;
user_count = sizeof(user_database) / food_count / 4;
user_data = new int *[user_count];
days[0] = 31, days[1] = 28, days[2] = 31, days[3] = 30, days[4] = 31, days[5] = 30, days[6] = 31, days[7] = 31, days[8] = 30, days[9] = 31, days[10] = 30, days[11] = 31;
int current_time = time(NULL);
int day = current_time / 60 / 60 / 24;
int year = 1970;
int mon = 0;
while (day > 365)
{
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
day -= 366;
}
else
{
day -= 365;
}
year++;
}
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
for (int i = 0; day - days[i] > 1; i++)
{
day = day - days[i];
mon = i + 1;
}
day--;
}
else
{
for (int i = 0; day - days[i] - 1 > 0; i++)
{
day = day - days[i];
mon = i + 1;
}
}
day++;
mon++;
save_time = year % 100 * 1000000 + mon * 10000 + day * 100;
system_time = 0;
for (int j = year % 100; j > 0; j--)
{
if (j % 4 == 0)
{
system_time += 366;
}
else
{
system_time += 365;
}
}
if (year % 100 != 0)
{
for (int j = mon; j > 1; j--)
{
system_time += days[j - 2];
}
}
else if (year % 100 == 0 && mon > 2)
{
for (int j = mon; j > 1; j--)
{
system_time += days[j - 2];
}
system_time++;
}
system_time += day;
for (int i = 0; i < user_count; i++)
{
user_data[i] = new int[food_count];
}
for (int i = 0; i < user_count; i++)
for (int j = 0; j < food_count; j++)
{
user_data[i][j] = user_database[i][j];
}
similality = new double *[user_count];
for (int i = 0; i < user_count; i++)
{
similality[i] = new double[user_count];
}
for (int i = 0; i < user_count; i++)
{
for (int j = 0; j < user_count; j++)
{
similality[i][j] = 0;
}
}
}
FooRe::~FooRe()
{
for (int i = 0; i < user_count; i++)
delete[] user_data[i];
delete[] user_data;
for (int i = 0; i < user_count; i++)
delete[] similality[i];
delete[] similality;
}
double FooRe::pearson(int user1, int user2)
{
double left_bot = 0, right_bot = 0, top = 0, result;
for (int i = 0; i < food_count; i++)
{
top += (user_data[user1][i] % 100) * (user_data[user2][i] % 100);
if ((user_data[user1][i] % 100) != 0 && (user_data[user2][i] % 100) != 0)
{
left_bot += pow(user_data[user1][i] % 100, 2);
right_bot += pow(user_data[user2][i] % 100, 2);
}
}
left_bot = sqrt(left_bot);
right_bot = sqrt(right_bot);
result = (double)top / (left_bot * right_bot);
if(left_bot*right_bot==0)
return 0;
return result;
}
double FooRe::prediction(int user, int food)
{
double top = 0, bot = 0, result = 0;
for (int i = 0; i < user_count; i++)
{
if(user_data[i][food]>0&&i!=user){
top += similality[user][i] * (user_data[i][food] % 100);
bot += similality[user][i];
}
}
result = top / bot;
return result;
}
int FooRe::collaborative_filtering(int user)
{
double expect_score[food_count] = {};
double top = 0, bot = 0, result = 0, max = 0;
int r_max = -1;
for (int i = 0; i < user_count; i++)
{
for (int j = 0; j < user_count; j++)
{
if (i == j)
{
similality[i][j] = 1;
}
else
{
similality[i][j] = pearson(i, j);
}
}
}
for (int i = 0; i < food_count; i++)
{
if (user_data[user][i] % 100 == 0)
{
expect_score[i] = prediction(user, i);
}
}
for (int i = 0; i < food_count; i++)
{
if (expect_score[i] > max)
{
max = expect_score[i];
r_max = i;
}
}
return r_max;
}
int FooRe::cac_remain_food(int user)
{
srand((unsigned int)time(NULL));
int rand_num = 0;
int evaluation = 0;
for (int i = 0; i < food_count; i++)
if ((user_data[user][i] % 100) != 0)
evaluation++;
rand_num = rand() % food_count + 1;
if (rand_num <= evaluation)
{
return 1;
}
else
{
return 0;
}
}
int FooRe::evaluated_FoodRecommendation_function(int user, int re_food_arr[], int num)
{
srand((unsigned int)time(NULL));
int total_score = 0, com_score = 0;
int rand_num;
for (int i = 0; i < num; i++)
total_score += (user_data[user][re_food_arr[i]] % 100);
rand_num = rand() % total_score + 1;
for (int i = 0; i < num; i++)
{
com_score += (user_data[user][re_food_arr[i]] % 100);
if (rand_num <= com_score)
return re_food_arr[i];
}
return 0;
}
int FooRe::evaluate_can_exe(int user)
{
int same_data_exist, not_same_data_exist;
for (int i = 0; i < user_count; i++)
{
same_data_exist = 0, not_same_data_exist = 0;
for (int j = 0; j < food_count; j++)
{
if ((user_data[user][j] % 100) != 0 && (user_data[i][j] % 100) != 0)
same_data_exist = 1;
if ((user_data[user][j] % 100) == 0 && (user_data[i][j] % 100) != 0)
not_same_data_exist = 1;
}
if (same_data_exist + not_same_data_exist == 2)
return 1;
}
return 0;
}
int FooRe::rand_recommend(int user)
{
srand((unsigned int)time(NULL));
int rand_num;
int zero_arr[food_count] = {}, zero_arr_count = 0;
for (int i = 0; i < food_count; i++)
{
if ((user_data[user][i] % 100) == 0)
{
zero_arr[zero_arr_count++] = i;
}
}
rand_num = rand() % zero_arr_count;
return zero_arr[rand_num];
}
int FooRe::FoodRecommendation(int user)
{
if (check_data(user))
{
if (cac_remain_food(user))
{
return evaluated_FoodRecommendation(user);
}
else
{
if (evaluate_can_exe(user))
{
return collaborative_filtering(user);
}
else
{
return rand_recommend(user);
}
}
}
else
{
return -1;
}
}
int FooRe::check_data(int user)
{
if (user < user_count)
{
for (int i = 0; i < user_count; i++)
for (int j = 0; j < food_count; j++)
if (user_data[i][j] / 10 < 0 || user_data[i][j] % 100 / 10 > 10)
{
cout << "ERROR: DATA BASE" << endl;
return 0;
}
return 1;
}
else
{
cout << "ERROR: USER NUMBER" << endl;
}
return 0;
}
int FooRe::cac_time(int user, int item)
{
int user_time;
user_time = 0;
for (int j = user_data[user][item] / 1000000; j > 0; j--)
{
if (j % 4 == 0)
{
user_time += 366;
}
else
{
user_time += 365;
}
}
if (user_data[user][item] / 1000000 % 4 != 0)
{
for (int j = user_data[user][item] % 1000000 / 10000; j > 1; j--)
{
user_time += days[j - 2];
}
}
else if (user_data[user][item] / 1000000 % 4 == 0 && user_data[user][item] % 1000000 / 10000 > 2)
{
for (int j = user_data[user][item] % 1000000 / 10000; j > 1; j--)
{
user_time += days[j - 2];
}
user_time++;
}
user_time += user_data[user][item] % 10000 / 100;
return system_time - user_time;
}
int FooRe::evaluated_FoodRecommendation(int user)
{
int recommended_food[food_count] = {};
int count_num = 0, zero_count = 0;
int *user_data_copy = new int[food_count];
for (int i = 0; i < food_count; i++)
user_data_copy[i] = i;
for (int i = 0; i < food_count; i++)
if (cac_time(user, i) >= 7 && user_data[user][i] % 100 != 0)
recommended_food[count_num++] = i;
if (count_num != 0)
{
return evaluated_FoodRecommendation_function(user, recommended_food, count_num);
}
else
{
for (int i = 0; i < food_count; i++)
if (user_data[user][i] % 100 == 0)
zero_count++;
if (zero_count != 0)
{
if (evaluate_can_exe(user))
{
return collaborative_filtering(user);
}
else
{
return rand_recommend(user);
}
}
else
{
return evaluated_FoodRecommendation_function(user, user_data_copy, food_count);
}
}
}
int FooRe::return_time(int food, int user)
{
return save_time+user_data[user][food];
}
int main(void)
{
FooRe test;
int rf;
int save_database;
if ((rf = test.FoodRecommendation(1)) != -1)
{
cout << "recommended food is : " << rf << endl;
save_database = test.return_time(rf, 1);
}
else
{
cout << "failed to recommend food" << endl;
}
cout << save_database;
return 0;
}