Problem Statement | |||||||||||||
In most states, gamblers can choose from a wide variety of different lottery games. The rules of a lottery are defined by two integers (choices and blanks) and two boolean variables (sorted and unique). choices represents the highest valid number that you may use on your lottery ticket. (All integers between 1 and choices, inclusive, are valid and can appear on your ticket.) blanks represents the number of spots on your ticket where numbers can be written. The sorted and unique variables indicate restrictions on the tickets you can create. If sorted is set to true, then the numbers on your ticket must be written in non-descending order. If sorted is set to false, then the numbers may be written in any order. Likewise, if unique is set to true, then each number you write on your ticket must be distinct. If unique is set to false, then repeats are allowed. Here are some example lottery tickets, where choices = 15 and blanks = 4:
Given a list of lotteries and their corresponding rules, return a list of lottery names sorted by how easy they are to win. The probability that you will win a lottery is equal to (1 / (number of valid lottery tickets for that game)). The easiest lottery to win should appear at the front of the list. Ties should be broken alphabetically (see example 1). | |||||||||||||
Definition | |||||||||||||
| |||||||||||||
Constraints | |||||||||||||
- | rules will contain between 0 and 50 elements, inclusive. | ||||||||||||
- | Each element of rules will contain between 11 and 50 characters, inclusive. | ||||||||||||
- | Each element of rules will be in the format "<NAME>:_<CHOICES>_<BLANKS>_<SORTED>_<UNIQUE>" (quotes for clarity). The underscore character represents exactly one space. The string will have no leading or trailing spaces. | ||||||||||||
- | <NAME> will contain between 1 and 40 characters, inclusive, and will consist of only uppercase letters ('A'-'Z') and spaces (' '), with no leading or trailing spaces. | ||||||||||||
- | <CHOICES> will be an integer between 10 and 100, inclusive, with no leading zeroes. | ||||||||||||
- | <BLANKS> will be an integer between 1 and 8, inclusive, with no leading zeroes. | ||||||||||||
- | <SORTED> will be either 'T' (true) or 'F' (false). | ||||||||||||
- | <UNIQUE> will be either 'T' (true) or 'F' (false). | ||||||||||||
- | No two elements in rules will have the same name. | ||||||||||||
Examples | |||||||||||||
0) | |||||||||||||
| |||||||||||||
1) | |||||||||||||
| |||||||||||||
2) | |||||||||||||
|
This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.
#include <string>
#include <vector>
#include <math.h>
#include <algorithm>
#include <exception>
#include <iostream>
using namespace std;
struct LotteryInfo
{
string Name;
int Chocies;
int Blanks;
bool Sorted;
bool Unique;
string Odds;
};
class Lottery
{
private:
string Sum(string str1, string str2)
{
size_t found;
found = str1.find_first_not_of('0');
if (found != string::npos)
{
str1 = str1.substr(found, str1.length()-found);
}
found = str2.find_first_not_of('0');
if (found != string::npos)
{
str2 = str2.substr(found, str2.length()-found);
}
string a, b, c = "";
if (str1.length() >= str2.length())//a is bigger than b
{
a = str1;
b = str2;
}
else
{
a = str2;
b = str1;
}
c.assign(a.length()+1, '0');
for (size_t i = 0; i < a.length(); i++)
{
if (i >= b.length())
{
c.at(c.length()-1-i) += (a.at(a.length()-1-i)-'0');
continue;
}
else
{
c.at(c.length()-1-i) += ((a.at(a.length()-1-i)-'0') + (b.at(b.length()-1-i)-'0'));
}
}
for (int i = c.length()-1; i >= 0; i--)
{
int n = i;
while (c.at(n) > '9')
{
c.at(n) -= 10;
c.at(n-1) += 1;
}
}
found = c.find_first_not_of('0');
if (found != string::npos)
{
c = c.substr(found, c.length()-found);
}
return c;
}
string Sub(string str1, string str2)//assume str1 is bigger than str2
{
size_t found;
found = str1.find_first_not_of('0');
if (found != string::npos)
{
str1 = str1.substr(found, str1.length()-found);
}
found = str2.find_first_not_of('0');
if (found != string::npos)
{
str2 = str2.substr(found, str2.length()-found);
}
if (str1.length() < str2.length())
{
return "";
}
else if (str1.length() == str2.length())
{
if (str1.compare(str2) < 0)
{
return "";
}
else if (str1.compare(str2) == 0)
{
return "0";
}
}
string result;
result.assign(str1.length(), '0');
for (size_t i = 0; i< str1.length(); i++)
{
if (i >= str2.length())//assume str1 is bigger than str2
{
result.at(result.length()-1-i) = str1.at(str1.length()-1-i);
continue;
}
result.at(result.length()-1-i) += (str1.at(str1.length()-1-i) - str2.at(str2.length()-1-i));
if (result.at(result.length()-1-i) < '0')
{
int n = str1.length()-1-i-1;
str1.at(n)--;
while (str1.at(n) < '0')
{
str1.at(n) = '9';
n--;
if (n < 0)
{
return "";
}
str1.at(n)--;
}
result.at(result.length()-1-i) += 10;
}
}
found = result.find_first_not_of('0');
if (found != string::npos)
result = result.substr(found, result.length()-found);
return result;
}
string Mult(string str1, string str2)
{
size_t found;
found = str1.find_first_not_of('0');
if (found != string::npos)
{
str1 = str1.substr(found, str1.length()-found);
}
found = str2.find_first_not_of('0');
if (found != string::npos)
{
str2 = str2.substr(found, str2.length()-found);
}
string a, b, c = "";
if (str1.length() >= str2.length())
{
a = str1;
b = str2;
}
else
{
a = str2;
b = str1;
}
c.assign(a.length()+b.length(), '0');
size_t a_length = a.length();
size_t b_length = b.length();
for (size_t i = 0; i < b_length; i++)
{
for (size_t j = 0; j < a_length; j++)
{
int mul = (b.at(b_length-1-i)-'0') * (a.at(a_length-1-j)-'0');
c.at(c.length()-1-i-j) += mul%10;
c.at(c.length()-1-i-j-1) += mul/10;
if (c.at(c.length()-1-i-j) > '9')
{
int n = c.length()-1-i-j;
while (c.at(n) > '9')
{
int h_bit = (c.at(n)-'0')/10;
c.at(n) -= h_bit*10;
n--;
c.at(n) += h_bit;
}
}
}
}
found = c.find_first_not_of('0');
if (found != string::npos)
c = c.substr(found, c.length()-found);
return c;
}
string Division(string str1, string str2)//assume str1 is bigger than str2
{
size_t found;
found = str1.find_first_not_of('0');
if (found != string::npos)
str1 = str1.substr(found, str1.length()-found);
else
{
if (str1.length() > 1)
{
found = str1.find_first_of('0');
if (found != string::npos)
{
return "0";
}
}
}
found = str2.find_first_not_of('0');
if (found != string::npos)
str2 = str2.substr(found, str2.length()-found);
if (str1.length() < str2.length())
{
return "";
}
else if (str1.length() == str2.length())
{
if (str1.compare(str2) < 0)
{
return "";
}
else if (str1.compare(str2) == 0)
{
return "1";
}
}
string result;
size_t str1_length = str1.length();
size_t str2_length = str2.length();
// for (size_t i = str2_length; i <= str1_length; i++)
// {
// string temp, temp_pre;
// temp = Sub(str1.substr(0, i), str2);
// if (temp.empty())
// {
// continue;
// }
// int cnt = 0;
// while (!temp.empty())
// {
// cnt++;
// temp_pre = temp;
// temp = Sub(temp, str2);
// }
// str1.replace(0, i, temp_pre);
// string str_temp = "1";
// for (int r_bit = 0; r_bit < str1_length-i; r_bit++)
// {
// str_temp = Mult(str_temp, "10");
// }
// char chr_temp[32];
// sprintf_s(chr_temp, 32, "%d", cnt);
// str_temp = Mult(str_temp, chr_temp);
// result = Sum(result, str_temp);
// }
//
string temp, temp_pre;
size_t delta = 0;
for (; delta <= str1_length - str2_length; delta++)
{
temp = Sub(str1.substr(0, str2_length+delta), str2);
if (!temp.empty())
{
break;
}
}
int cnt = 0;
while (!temp.empty())
{
cnt++;
temp_pre = temp;
temp = Sub(temp, str2);
}
str1.replace(0, str2_length+delta, temp_pre);
string str_temp = "1";
for (size_t r_bit = 0; r_bit < str1_length-str2_length-delta; r_bit++)
{
str_temp = Mult(str_temp, "10");
}
char chr_temp[32];
sprintf(chr_temp, "%d", cnt);
str_temp = Mult(str_temp, chr_temp);
result = Sum(Division(str1, str2), str_temp);
//
found = result.find_first_not_of('0');
if (found != string::npos)
result = result.substr(found, result.length()-found);
else
{
if (result.length() > 1)
{
found = result.find_first_of('0');
if (found != string::npos)
{
result = "0";
}
}
}
return result;
}
static bool Ascending(LotteryInfo a, LotteryInfo b)
{
string a_odds = a.Odds;
string b_odds = b.Odds;
if (a_odds.length() < b_odds.length())
{
return true;
}
else if (a_odds.length() > b_odds.length())
{
return false;
}
else
{
if (a_odds.compare(b_odds) < 0)
{
return true;
}
else if (a_odds.compare(b_odds) == 0)
{
string a_name = a.Name;
string b_name = b.Name;
if (a.Name.compare(b_name) < 0)
{
return true;
}
else
return false;
}
else
{
return false;
}
}
}
LotteryInfo getLotteryInfo(string rule)
{
LotteryInfo lottery;
size_t found1, found2;
found1 = rule.find_first_of(":");
if (found1 != string::npos)
lottery.Name = rule.substr(0, found1);
found1 += 2;
found2 = rule.find(" ", found1);
if (found1 != string::npos && found2 != string::npos)
{
lottery.Chocies = atoi(rule.substr(found1, found2-found1).c_str());
}
found1 = found2+1;
found2 = rule.find(" ", found1);
if (found1 != string::npos && found2 != string::npos)
{
lottery.Blanks = atoi(rule.substr(found1, found2-found1).c_str());
}
found1 = found2+1;
found2 = rule.find(" ", found1);
if (found1 != string::npos && found2 != string::npos)
{
if (rule.substr(found1, found2-found1) == "T")
{
lottery.Sorted = true;
}
else
{
lottery.Sorted = false;
}
}
found1 = found2+1;
if (found1 != string::npos)
{
if (rule.substr(found1, 1) == "T")
{
lottery.Unique = true;
}
else
{
lottery.Unique = false;
}
}
return lottery;
}
// unsigned long Factorial(int n)
// {
// unsigned long factorial = 1;
// while (n != 1)
// {
// factorial *= n;
// n--;
// }
// return factorial;
// }
string Factorial(int n)
{
if (n <= 1)
{
return "1";
}
char temp[32];
sprintf(temp, "%d", n);
string str_n(temp);
return Mult(str_n, Factorial(n-1));
}
string Combination(int n, int m)
{
//return Factorial(n) / (Factorial(n-m)*Factorial(m)); //it may overflow
//return Arrangement(n, m) / Factorial(m);
string str1 = Arrangement(n, m);
string str2 = Factorial(m);
return Division(str1, str2);
}
string Arrangement(int n, int m)
{
//return Factorial(n) / Factorial(n-m); it may overflow
string result = "1";
char temp[32];
for (int i = 0; i < m; i++)
{
sprintf(temp, "%d", n-i);
string str(temp);
result = Mult(result, str);
}
return result;
}
int fun(int n, int m)
{
if (n == m || n == 1)
{
return 1;
}
else if (n+1 == m)
{
return n;
}
else
{
int result = 0;
for (int i = n-1; i <= m-1; i++)
{
result += fun(n-1, i);
}
return result;
}
}
void calculateOdds(LotteryInfo &lottery)
{
if (lottery.Sorted)
{
string tickets = Combination(lottery.Chocies, lottery.Blanks);
if (!lottery.Unique)
{
int nBlanks = lottery.Blanks-1;
while (nBlanks > 0)
{
int nCoef = fun(nBlanks, lottery.Blanks);
char temp[32];
sprintf(temp, "%d", nCoef);
string ceof(temp);
string strF = Combination(lottery.Chocies, nBlanks);
strF = Mult(strF, ceof);
tickets = Sum(strF, tickets);
nBlanks--;
}
}
lottery.Odds = tickets;
}
else if (!lottery.Sorted && lottery.Unique)
{
string tickets = Arrangement(lottery.Chocies, lottery.Blanks);
lottery.Odds = tickets;
}
else
{
char temp[32];
sprintf(temp, "%d", lottery.Chocies);
string chocies(temp);
string tickets = "1";
for (int i = 0; i < lottery.Blanks; i++)
{
tickets = Mult(tickets, chocies);
}
lottery.Odds = tickets;
}
}
public:
vector <string> sortByOdds(vector <string> rules)
{
vector <string> result;
vector <LotteryInfo> lottery_statis;
vector <string>::iterator itor = rules.begin();
for (; itor != rules.end(); itor++)
{
LotteryInfo lottery_info = getLotteryInfo(*itor);
try
{
calculateOdds(lottery_info);
}
catch (exception& e)
{
cout << e.what() << endl;
}
lottery_statis.push_back(lottery_info);
}
sort(lottery_statis.begin(), lottery_statis.end(), Ascending);
vector<LotteryInfo>::iterator itor_lottery = lottery_statis.begin();
for (; itor_lottery != lottery_statis.end(); itor_lottery++)
{
result.push_back((*itor_lottery).Name);
}
return result;
}
};