Showing posts with label ACM Problems. Show all posts
Showing posts with label ACM Problems. Show all posts

Thursday, September 24, 2009

Credit Card Processing

Credit Card Processing from Problem Set 2005-2006

http://www.socalcontest.org/current/index.shtml

Solution :

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cctype>
#include <sstream>
#include <vector>

using namespace std;

string util_trim_right( const string& s, const string& delim = " " ) {
string temp( s );
string::size_type o = temp.find_last_not_of( delim );
if ( o == string::npos )
return temp;
else
return temp.erase( temp.find_last_not_of( delim ) + 1 );
}

string util_trim_left( const string& s, const string& delim = " " ) {
string temp( s );
return temp.erase( 0, s.find_first_not_of( delim ) );
}

vector< string > util_tokenize_string( const string& str, const string& del = "," ) {
vector< string > result;
string::size_type start = 0;
string::size_type end = str.find_first_of( del, start );
string::size_type length = str.length();
string word;

while ( string::npos != end && end < length ) {
word = str.substr( start, end - start );
result.push_back( word );
start = end + 1;
end = str.find_first_of( del, start );
}

end = str.find_last_of( del ) + 1;
result.push_back( str.substr( end ) );

return result;
}

void util_delete_all_white_space( string& s ) {
s.erase( remove( s.begin(), s.end(), ' ' ), s.end() );
}

bool util_is_all_white_space( const string& s ) {
for ( unsigned o = 0, o_end = s.length(); o < o_end; ++o )
if ( s[ o ] != ' ' )
return false;

return true;
}


class Customer {
public :
string cu_first_name;
string cu_last_name;
string cu_address;
string cu_city;
string cu_state;
string cu_zipcode;
string cu_ssn;
string cu_credit_1;
string cu_credit_2;
string cu_credit_3;
char cu_literal_semicolon;

public :
// bussiness rule 1
bool cu_test_leading_white_space_and_null() const;

// bussiness rule 2
bool cu_test_byte_field_isdigit_isalpha() const;

// bussiness rule 3
bool cu_test_credit_score() const;

// bussiness rule 4
bool cu_test_credit_score_mean() const;

void cu_show_customer_info() const;

};


void Customer::cu_show_customer_info() const {
cout << "1." << cu_first_name << "\n";
cout << "2." << cu_last_name << "\n";
cout << "3." << cu_address << "\n";
cout << "4." << cu_city << "\n";
cout << "5." << cu_state << "\n";
cout << "6." << cu_zipcode << "\n";
cout << "7." << cu_ssn << "\n";
cout << "8." << cu_credit_1 << "\n";
cout << "9." << cu_credit_2 << "\n";
cout << "10." << cu_credit_3 << "\n";
}

bool Customer::cu_test_credit_score() const {
istringstream o1( cu_credit_1, istringstream::in );
istringstream o2( cu_credit_2, istringstream::in );
istringstream o3( cu_credit_3, istringstream::in );

int val_1, val_2, val_3;
o1 >> val_1;
o2 >> val_2;
o3 >> val_3;

if (
val_1 < 400 ||
val_2 < 400 ||
val_3 < 400 ) {

return false;
}

return true;
}

bool Customer::cu_test_credit_score_mean() const {
istringstream o1( cu_credit_1, istringstream::in );
istringstream o2( cu_credit_2, istringstream::in );
istringstream o3( cu_credit_3, istringstream::in );

int val_1, val_2, val_3;
o1 >> val_1;
o2 >> val_2;
o3 >> val_3;

double mean = static_cast< double >( val_1 + val_2 + val_3 ) / 3.0;
if ( mean < 500 ) {
return false;
}

return true;
}

bool Customer::cu_test_byte_field_isdigit_isalpha() const {

// check literal_semicolon
if ( cu_literal_semicolon != ';' )
return false;

// check byte field
if ( cu_state.length() != 2 || cu_zipcode.length() != 5 )
return false;

// check city for non-alphanumeric
for ( unsigned o = 0, o_end = cu_city.length(); o < o_end; ++o ) {
if ( isdigit( cu_city[ o ] ) == false && isalpha( cu_city[ o ] ) == false )
return false;
}

// check state for only alphabetic
for ( unsigned o = 0, o_end = cu_state.length(); o < o_end; ++o ) {
if ( isalpha( cu_state[ o ] ) == false )
return false;
}

// check zipcode for only numeric
for ( unsigned o = 0, o_end = cu_zipcode.length(); o < o_end; ++o ) {
if ( isdigit( cu_zipcode[ o ] ) == false )
return false;
}

// check ssn for only numeric
for ( unsigned o = 0, o_end = cu_ssn.length(); o < o_end; ++o ) {
if ( isdigit( cu_ssn[ o ] ) == false )
return false;
}

unsigned CREDIT_DIGITS = 3;
// check credit_1, credit_2, credit_3 for only numeric
for ( unsigned o = 0; o < CREDIT_DIGITS; ++o ) {
if (
isdigit( cu_credit_1[ o ] ) == false ||
isdigit( cu_credit_2[ o ] ) == false ||
isdigit( cu_credit_3[ o ] ) == false ) {

return false;
}
}

// check credit_1, credit_2, credit_3 for valid range ( 200 - 800 )
istringstream o1( cu_credit_1, istringstream::in );
istringstream o2( cu_credit_2, istringstream::in );
istringstream o3( cu_credit_3, istringstream::in );

int val_1, val_2, val_3;
o1 >> val_1;
o2 >> val_2;
o3 >> val_3;

if (
val_1 < 200 || val_1 > 800 ||
val_2 < 200 || val_2 > 800 ||
val_3 < 200 || val_3 > 800 ) {
return false;
}

return true;
}

bool Customer::cu_test_leading_white_space_and_null() const {

// check for NULL character
if ( cu_literal_semicolon == ' ' )
return false;

// check for NULL string

if (
util_is_all_white_space( cu_first_name ) == true ||
util_is_all_white_space( cu_last_name ) == true ||
util_is_all_white_space( cu_address ) == true ||
util_is_all_white_space( cu_city ) == true ||
util_is_all_white_space( cu_state ) == true ||
util_is_all_white_space( cu_zipcode ) == true ||
util_is_all_white_space( cu_ssn ) == true ||
util_is_all_white_space( cu_credit_1 ) == true ||
util_is_all_white_space( cu_credit_2 ) == true ||
util_is_all_white_space( cu_credit_3 ) == true ) {

return false;
}

// check for leading white space
if (
cu_first_name[ 0 ] == ' ' ||
cu_last_name[ 0 ] == ' ' ||
cu_address[ 0 ] == ' ' ||
cu_city[ 0 ] == ' ' ||
cu_state[ 0 ] == ' ' ||
cu_zipcode[ 0 ] == ' ' ) {

return false;
}

return true;
}

vector< Customer > main_prog_get_data_from_file( const char* file_name ) {
ifstream o( file_name );
string oneline;
vector< Customer > cus_vec;

while ( getline( o, oneline ) ) {

cout << oneline << endl;
Customer cus;
string temp; // use for a_c_s_z string

// get the last character
cus.cu_literal_semicolon = oneline[ 89 ];

for ( unsigned o = 0; o < 12; ++o ) {
cus.cu_first_name.push_back( oneline[ o ] );
}

for ( unsigned o = 12; o < 29; ++o ) {
cus.cu_last_name.push_back( oneline[ o ] );
}

for ( unsigned o = 30; o < 71; ++o ) {
temp.push_back( oneline[ o ] );
}

for ( unsigned o = 71; o < 79; ++o ) {
cus.cu_ssn.push_back( oneline[ o ] );
}

for ( unsigned o = 80; o < 83; ++o ) {
cus.cu_credit_1.push_back( oneline[ o ] );
}

for ( unsigned o = 83; o < 86; ++o ) {
cus.cu_credit_2.push_back( oneline[ o ] );
}

for ( unsigned o = 86; o < 89; ++o ) {
cus.cu_credit_3.push_back( oneline[ o ] );
}


/* trim right for :
1. first name
2. last name
*/
cus.cu_first_name = util_trim_right( cus.cu_first_name );
cus.cu_last_name = util_trim_right( cus.cu_last_name );

/*
Since we need to have enough commas( 3 )
to handle the tokenizer, we need to test :
1. All whitespace
2. No comma
3. Not enough comma

One of these 3 fails, we will set all the 4 field :
- cu_address
- cu_city
- cu_state
- cu_zipcode
to all whitespace so it will fail later on
business rule 1
*/
bool is_all_white_space = true;
for ( unsigned o = 0, o_end = temp.length(); o < o_end; ++o ) {
if ( temp[ o ] != ' ' )
is_all_white_space = false;
}

bool is_no_comma_separator = true;
for ( unsigned o = 0, o_end = temp.length(); o < o_end; ++o ) {
if ( temp[ o ] == ',' )
is_no_comma_separator = false;
}

bool is_not_enough_commad = false;
unsigned comma_count = 0;
for ( unsigned o = 0, o_end = temp.length(); o < o_end; ++o ) {
if ( temp[ o ] == ',' )
comma_count++;
}

if ( comma_count < 3 )
is_not_enough_commad = true;

if ( is_no_comma_separator == true ||
is_all_white_space == true ||
is_no_comma_separator == true ) {
fill_n( cus.cu_address.begin(), cus.cu_address.length(), ' ' );
fill_n( cus.cu_city.begin(), cus.cu_city.length(), ' ' );
fill_n( cus.cu_state.begin(), cus.cu_state.length(), ' ' );
fill_n( cus.cu_zipcode.begin(), cus.cu_zipcode.length(), ' ' );
} else {

vector< string > address_city_state_zipcode;
address_city_state_zipcode = util_tokenize_string( temp );
/* trim right for :
3. address
4. city
5. state
6. zipcode
*/
cus.cu_address = util_trim_right( address_city_state_zipcode[ 0 ] );
cus.cu_city = util_trim_right( address_city_state_zipcode[ 1 ] );
cus.cu_state = util_trim_right( address_city_state_zipcode[ 2 ] );
cus.cu_zipcode = util_trim_right( address_city_state_zipcode[ 3 ] );
}

/* delete all white space for :
1. ssn
2. credit 1
3. credit 2
4. credit 3
*/
util_delete_all_white_space( cus.cu_ssn );
util_delete_all_white_space( cus.cu_credit_1 );
util_delete_all_white_space( cus.cu_credit_2 );
util_delete_all_white_space( cus.cu_credit_3 );


cus_vec.push_back( cus );
}

return cus_vec;
}

void main_prog_test_all_customers( const vector< Customer >& v ) {
for ( unsigned o = 0, o_end = v.size(); o < o_end; ++o ) {
cout << "\n\n --- Customer " << o + 1 << "\n";

bool status = true;
status = v[ o ].cu_test_leading_white_space_and_null();
cout << "Status 1 " << status << endl;

status = v[ o ].cu_test_byte_field_isdigit_isalpha();
cout << "Status 2 " << status << endl;

status = v[ o ].cu_test_credit_score();
cout << "Status 3 " << status << endl;

status = v[ o ].cu_test_credit_score_mean();
cout << "Status 4 " << status << endl;
}
}

int main() {

vector< Customer > v;
v = main_prog_get_data_from_file( "in1.txt" );
main_prog_test_all_customers( v );
return 0;
}