// ------------------------------------------------------------------------- // file info // ------------------------------------------------------------------------- // file: game24.cpp // description: an implementation of the game of 24 // author: ori schwartz (ori@bu.edu) // ------------------------------------------------------------------------- // libraries // ------------------------------------------------------------------------- #include #include #include #include #include // -------------------------------------------------------------------------- // constants // -------------------------------------------------------------------------- float solution[ 5 ][ 5 ]; // use for printing valid solutions string expressions[ 4 ]; // an expression used in generating solutions char* ops[] = { " + ", " - ", " * ", " / " }; // -------------------------------------------------------------------------- // function prototypes // -------------------------------------------------------------------------- bool isQuad( int v1, int v2, int v3, int v4 ); bool isQuadHelper( int numValues, float v1, float v2, float v3, float v4 ); void printSolution(); // -------------------------------------------------------------------------- // main program // -------------------------------------------------------------------------- int main() { // used for user input int input[ 4 ]; // prompt for input cout << "Enter 4 integers:" << endl; for ( int i = 0; i < 4; i++ ) { cout << " >"; cin >> input[ i ]; } if ( isQuad( input[ 0 ], input[ 1 ], input[ 2 ], input[ 3 ] ) ) cout << "\nAt least one solution was found!\n" << endl; else cout << "\nNo solutions were found.\n" << endl; printSolution(); cout << endl; return 0; } // -------------------------------------------------------------------------- // functions // -------------------------------------------------------------------------- // function: isQuad // purpose: a wrapper function which simplifies the call to passing only // the four numbers (ints) in question. bool isQuad( int v1, int v2, int v3, int v4 ) { return isQuadHelper( 4, v1, v2, v3, v4 ); } // function: isQuadHelper // purpose: a recursive function that solves the game of 24; solves from // a given set of <= 4 numbers, trying all combinations of 2 numbers with // all possible operators; thus one number is eliminated and a recursive // call is made. bool isQuadHelper( int numValues, float v1, float v2, float v3, float v4 ) { // create an array of modified values that are the result of our efforts // to eliminate a number double newValues[ 4 ], difference; // find the difference between v1 and 24 difference = abs( 24 - v1 ); // store for ease of printing later on solution[ numValues ][ 0 ] = v1; solution[ numValues ][ 1 ] = v2; solution[ numValues ][ 2 ] = v3; solution[ numValues ][ 3 ] = v4; // see if we are done; this is indicated by a value of 24 in v1 and the // presence of only 1 number; some divisions result in answers close to // 24 so accept all answers within .00001 of 24 if ( numValues == 1 && difference < 0.00001 ) return 1; // failure: no quad exists; this happens when we are down to one number // that is not 24 if ( numValues == 1 && v1 != 24 ) return 0; // recursion: go through all number combinations and operators for ( int i = 0; i < numValues; i++ ) for ( int j = 0; j < numValues; j++ ) // cannot operate number on itself if ( i != j ) // go through all 4 operators for ( int operation = 0; operation < 4; operation++ ) { // allow us to cycle through all possible options newValues[ 0 ] = v1; newValues[ 1 ] = v2; newValues[ 2 ] = v3; newValues[ 3 ] = v4; stringstream operand1, operand2, answer; operand1 << newValues[ i ]; operand2 << newValues[ j ]; // + if ( operation == 0 ) newValues[ i ] = newValues[ i ] + newValues[ j ]; // - if (operation == 1 ) newValues[ i ] = newValues[ i ] - newValues[ j ]; // * if ( operation == 2 ) newValues[ i ] = newValues[ i ] * newValues[ j ]; // / : division must check for 0 denominator if ( operation == 3 && newValues[ j ] != 0 ) newValues[ i ] = newValues[ i ] / newValues[ j ]; // make sure that when numvalues is decreased, we don't ignore // a valid number; also, discard the used operand by overwriting it newValues[ j ] = newValues[ numValues - 1 ]; answer << newValues[ i ]; // check if the new values form a quad, recursively if ( isQuadHelper( numValues - 1, newValues[ 0 ], newValues[ 1 ], newValues[ 2 ], newValues[ 3 ] ) ) { // save correct expression expressions[ numValues - 1 ] = operand1.str() + ops[ operation ] + operand2.str() + " = " + answer.str(); // return success return 1; } } // if function reaches this point then no quads exist return 0; } // function: printSolution // purpose: print a valid solution and its corresponding steps void printSolution() { cout << "Numbers used:\t\tExpression Needed:" << endl << "-------------------------------------------\n"; for ( int i = 4; i >= 1; i-- ) { for ( int j = 0; j < i; j++ ) cout << setprecision( 3 ) << solution[ i ][ j ] << " "; // format output if ( i != 4 ) cout << " "; if ( i != 1 ) cout << "\t\t( " << expressions[ i - 1 ] << " )\n"; } }