Parallelizing Minimax with alpha-beta pruning using MPI - mpi

I am currently busy with a project that requires you to use the minimax with AB pruning.
I have successfully implemented a serial version of the program
//Assume maximizing player is WHITE
int minimax_move(int *current_board, int player, int *chosen_move, int alpha, int beta) {
int *moves_list;//capture the moves for a board
int moves_len;
int opponent = BLACK;
if (player == BLACK) {
opponent = WHITE;
}
get_moves_list(current_board,&moves_list,&moves_len,player);
//No Move to be generated
if (moves_list[0] == 0) {
*chosen_move = -1;
} else {
//Remember the best move
int best_move_value = INT_MIN;
int best_move = moves_list[1];
//Try all the moves
for (int i = 1; i <= moves_len; i++) {
int *temp_board = (int *) malloc(sizeof(int) * BOARDSIZE);
copy_board(current_board,temp_board);
apply_move(&temp_board,moves_list[i],player);
//Initial Call to minimax_value
int value = minimax_value(temp_board,player,opponent,1,alpha,beta);
//Remember best move
if (value > best_move_value) {
best_move_value = value;
best_move = moves_list[i];
}
}
//Set the chosen move
*chosen_move = best_move;
printc("Chosen Move is: %d\nFrom %s\n",*chosen_move,get_turn_player(player));
}
return *chosen_move;
}
//original_turn -> maximizing player
//current_turn -> minimizing_player
//Current turn is what alternates the turn player when simulating move look aheads
//The maximizing player is established in minimax_moves
int minimax_value(int *current_state,int original_turn, int current_turn,int depth,int a,int b) {
if (depth == MAXDEPTH || is_game_over(current_state)) {
return evaluate_board(current_state);
}
int *moves_list;
int moves_len;
int opponent = BLACK;
if (current_turn == BLACK) {
opponent = WHITE;
}
get_moves_list(current_state,&moves_list,&moves_len,current_turn);
//if no moves, skip to next player's (opponent) turn
if (moves_list[0] == 0) {
return minimax_value(board,original_turn,opponent,depth+1,a,b);
} else {
//Remember the best move - Setting the limits
//For max player
int best_move_value = INT_MIN;
int alpha = a;
int beta = b;
if (original_turn != current_turn) {
//original_turn -> max player
//current_tunr -> min player
best_move_value = INT_MAX;
}
for (int i = 1; i <= moves_len; i++) {
//Apply a move to the board
int *temp_board = (int *) malloc(sizeof(int) * BOARDSIZE);
copy_board(current_state,temp_board);
apply_move(&temp_board,moves_list[i],current_turn);
//Recursive calls
int value = minimax_value(temp_board,original_turn,opponent,depth+1,alpha,beta);
//Remember best move
//MAX PLAYER
if (original_turn == current_turn) {
if (value > best_move_value) {
best_move_value = value;
}
if (value > alpha) {
alpha = value;
}
} else {
//MIN PLAYER
if (value < best_move_value) {
best_move_value = value;
}
if (value < beta) {
beta = value;
}
}
//Alpha-Beta pruning
printc("ALPHA: %d - BETA: %d\n",alpha,beta);
if (beta <= alpha) {
printc("\n\nPRUNED\n\n");
break;
}
}
return best_move_value;
}
//return -1; ERROR
}
The project requires me to use MPI to parallelize the minimax algorithm. I have no idea where to start. I have read http://www.pressibus.org/ataxx/autre/minimax/node6.html#SECTION00060000000000000000
but am no closer to solving the problem as I do not understand the psuedo-code written.
My idea was to somehow scatter the moves_list generated in minimax_move() amongst (n-1) slave processes where 1 process will be the master process. However, the first call to minimax_move() yields a move_list of length 3, and we can assume that the number of processors that will be used to run the program will be >= 4.
I would appreciate a starting point on how to solve this as I cannot seem to wrap my head around how I would use MPI to parallelize this. It has to be done using MPI.

Ultimately alpha-beta mini-maxing requires you to score every tree generated by a turn and choose the best one. It sounds like your task is to parallelise the calculation of the scores, you should be able to utilise different processors to score different trees.

Related

Longest Univalue path in BST

I'm trying to solve the problem:
Given a binary tree, find the length of the longest path where each node in the path has the same value. This path may or may not pass through the root.
Note: The length of path between two nodes is represented by the number of edges between them.
Sample inputs here
I am getting wrong answer on a large input. My code passes 46 tests but fails after that. I don't understand where I went wrong. Could someone please help.
Here is my code:
class Solution
{
public:
int longestPath = 0;
int findLongestPath(TreeNode *root, int depth)
{
int leftDepth, rightDepth;
leftDepth = rightDepth = 0;
if (root->left != 0 && root->left->val == root->val)
leftDepth = findLongestPath(root->left, depth + 1);
if (root->right != 0 && root->right->val == root->val)
rightDepth = findLongestPath(root->right, depth + 1);
longestPath = max(longestPath, leftDepth + rightDepth);
return max(max(leftDepth, rightDepth), depth);
}
void traverse(TreeNode *root)
{
if (root == 0)
return;
findLongestPath(root, 0);
traverse(root->left);
traverse(root->right);
}
int longestUnivaluePath(TreeNode *root)
{
traverse(root);
return longestPath;
}
};

Binary coded GA with NSGA-II in R

I have a multiobjective minimization function. I want to use NSGA-II in R. There are packages for this: nsga2R and mco. But these packages do not support binary coded chromosomes. In my fitness function I need binary chromosomes to achive best solution because of my problem's structure. Is there any way to use binary coded chromosome in nsga2 (or maybe with different algorithm) for R? Thanks.
I got the same problem so I decided to fix it on my own. But no guarentee if it's the right way.
The following part is for the package 'mco'
I copied parts out of the offical nsga2 implementation into the 'mco' package.
This workaround is only for binary (0-1) variables.
1. In /src/nsga2.c rewrite the functions as follows:
static void mutate_ind (nsga2_ctx *ctx, individual *ind) {
int j;
double prob;
GetRNGstate();
for (j = 0; j < ctx->input_dim; j++)
{
//for (k=0; k < ctx[j]->input_dim; k++)
//{
//prob = randomperc();
prob = unif_rand();
if (prob <= ctx->mutation_probability) {
if (ind->input[j] == 0)
{
ind->input[j] = 1;
}
else
{
ind->input[j] = 0;
}
ctx->input_mutations+=1;
}
//}
}
PutRNGstate();
then
static void crossover (nsga2_ctx *ctx,
individual *parent1, individual *parent2,
individual *child1, individual *child2) {
int i;
int nbits=1;
double rand;
int temp, site1, site2, temp2, temp3;
GetRNGstate();
rand=unif_rand();
if (rand <= ctx->crossing_probability)
{
ctx->input_crossings++;
//site1 = rnd(0,ctx->input_dim);
//site2 = rnd(0,ctx->input_dim);
if(unif_rand()<=0.5){
temp2=0;
}else{
temp2=1;
}
if(unif_rand()<=0.5){
temp3=0;
}else{
temp3=1;
}
site1=temp2;
site2=temp3;
if (site1 > site2)
{
temp = site1;
site1 = site2;
site2 = temp;
}
for (i=0; i<site1; i++)
{
child1->input[i] = parent1->input[i];
child2->input[i] = parent2->input[i];
}
for (i=site1; i<site2; i++)
{
child1->input[i] = parent2->input[i];
child2->input[i] = parent1->input[i];
}
for (i=site2; i<nbits; i++)
{
child1->input[i] = parent1->input[i];
child2->input[i] = parent2->input[i];
}
}
else
{
for (i=0; i<nbits; i++)
{
child1->input[i] = parent1->input[i];
child2->input[i] = parent2->input[i];
}
}
PutRNGstate();
}
and
static void population_initialize(nsga2_ctx *ctx, population *pop) {
GetRNGstate();
int i, j;
for (i = 0; i < pop->size; ++i) {
for (j=0; j<ctx->input_dim; ++j) {
/* Generate random value between lower and upper bound */
//double delta = ctx->upper_input_bound[j] - ctx->lower_input_bound[j];
//pop->ind[i].input[j] = ctx->lower_input_bound[j] + delta*unif_rand();
if(unif_rand() <= 0.5){
pop->ind[i].input[j] = 0;
}
else{
pop->ind[i].input[j] = 1;
}
}
}
PutRNGstate();
}
2. define the function randomperc() as follows
double seed;
double oldrand[55];
int jrand;
/* Create next batch of 55 random numbers */
void advance_random ()
{
int j1;
double new_random;
for(j1=0; j1<24; j1++)
{
new_random = oldrand[j1]-oldrand[j1+31];
if(new_random<0.0)
{
new_random = new_random+1.0;
}
oldrand[j1] = new_random;
}
for(j1=24; j1<55; j1++)
{
new_random = oldrand[j1]-oldrand[j1-24];
if(new_random<0.0)
{
new_random = new_random+1.0;
}
oldrand[j1] = new_random;
}
}
/* Fetch a single random number between 0.0 and 1.0 */
double randomperc()
{
jrand++;
if(jrand>=55)
{
jrand = 1;
advance_random();
}
return((double)oldrand[jrand]);
}
3. replace every unif_rand() with randomperc() in 'nsga2.c'
4. build the package in R

Using a distance sensor in Processing to control the attributes of shapes

I'm trying to make a program that will use the readings it gets from a distance sensor to control the attributes of circles (size, xy and colour). To do this I'm trying to make it record the current value and apply that to the value when you press the relevant key (Eg. press 's' and it changes the size to whatever the distance was at that point). - Ideally I'd like the circle to change whatever field is next dynamically as you move your hand over the sensor, but that seems a bit beyond me.
I've tried to do as much as I can, but everything I'm not sure of I've commented out. Any tips or advice? I'm really not sure what I'm doing when it comes to classes and constructors.
EDIT: When I run the code, nothing happens.
import processing.serial.*;
int xpos, ypos, s, r, g, b;
Circle circle;
int shapeSize, distance;
String comPortString;
Serial myPort;
void setup(){
size(displayWidth,displayHeight); //Use entire screen size.
//Open the serial port for communication with the Arduino
myPort = new Serial(this, "/dev/cu.usbmodem1411", 9600);
myPort.bufferUntil('\n'); // Trigger a SerialEvent on new line
}
void draw(){
background(0);
delay(50); //Delay used to refresh screen
println(distance);
}
void serialEvent(Serial cPort){
comPortString = (new String(cPort.readBytesUntil('\n')));
if(comPortString != null) {
comPortString=trim(comPortString);
/* Use the distance received by the Arduino to modify the y position
of the first square (others will follow). Should match the
code settings on the Arduino. In this case 200 is the maximum
distance expected. The distance is then mapped to a value
between 1 and the height of your screen */
distance = int(map(Integer.parseInt(comPortString),1,200,1,height));
if(distance<0){
/*If computer receives a negative number (-1), then the
sensor is reporting an "out of range" error. Convert all
of these to a distance of 0. */
distance = 0;
}
}
}
void keyPressed()
{
// N for new circle (and keep old one)
if((key == 'N') || (key == 'n')) {
println("n");
circle = new Circle(1,1,1,1,1,1);
}
//r - change red
if((key == 'R') || (key == 'r')) {
float red = map(distance, 0, 700, 0, 255);
r = int(red);
println("r " + r);
}
//g - change green
if((key == 'G') || (key == 'g')) {
float green = map(distance, 0, 700, 0, 255);
g = int(green);
println("g " + g);
}
//b - change blue
if((key == 'B') || (key == 'b')) {
float blue = map(distance, 0, 700, 0, 255);
b = int(blue);
println("b " + b);
}
//S - change Size
if((key == 'S') || (key == 's')) {
s = distance;
println("s " + s);
}
//X - change x pos
if((key == 'X') || (key == 'x')) {
xpos = distance;
println("x " + xpos);
}
//y - change y pos
if((key == 'Y') || (key == 'y')) {
ypos = distance;
println("y " + ypos);
}
}
class Circle {
Circle(int xpos, int ypos, int s, int r, int g, int b){
ellipse(xpos, ypos, s, s);
color(r, g, b);
}
int getX(){
return xpos;
}
int getY(){
return ypos;
}
}
I would split this into steps/tasks:
Connecting to the Arduino
Reading values from Arduino
Mapping read values
Controlling mapping
You've got the Arduino part pretty much there, but things look messy when trying to map read values to the circle on screen.
For now, for simplicity reasons, let's ignore classes and focus on simply drawing a single ellipse with x,y,size,r,g,b properties.
To get read of jitter you should update the property ellipse continuously, not just when pressing a key. On the key event you should simply change what property gets updated.
You could use extra variables to keep track of what ellipse properties you're updating.
Here's a refactored version of the code based on the points above:
import processing.serial.*;
int xpos,ypos,s,r,g,b;
int distance;
int propertyID = 0;//keep track of what property should be updated on distance
int PROP_XPOS = 0;
int PROP_YPOS = 1;
int PROP_S = 2;
int PROP_R = 3;
int PROP_G = 4;
int PROP_B = 5;
void setup(){
size(400,400);
//setup some defaults to see something on screen
xpos = ypos = 200;
s = 20;
r = g = b = 127;
//initialize arduino - search for port based on OSX name
String[] portNames = Serial.list();
for(int i = 0 ; i < portNames.length; i++){
if(portNames[i].contains("usbmodem")){
try{
Serial arduino = new Serial(this,portNames[i],9600);
arduino.bufferUntil('\n');
return;
}catch(Exception e){
showSerialError();
}
}
}
showSerialError();
}
void showSerialError(){
System.err.println("Error connecting to Arduino!\nPlease check the USB port");
}
void draw(){
background(0);
fill(r,g,b);
ellipse(xpos,ypos,s,s);
}
void serialEvent(Serial arduino){
String rawString = arduino.readString();//fetch raw string
if(rawString != null){
String trimmedString = rawString.trim();//trim the raw string
int rawDistance = int(trimmedString);//convert to integer
distance = (int)map(rawDistance,1,200,1,height);
updatePropsOnDistance();//continously update circle properties
}
}
void updatePropsOnDistance(){
if(propertyID == PROP_XPOS) xpos = distance;
if(propertyID == PROP_YPOS) ypos = distance;
if(propertyID == PROP_S) s = distance;
if(propertyID == PROP_R) r = distance;
if(propertyID == PROP_G) g = distance;
if(propertyID == PROP_B) b = distance;
}
void keyReleased(){//only change what proprty changes on key press
if(key == 'x' || key == 'X') propertyID = PROP_XPOS;
if(key == 'y' || key == 'Y') propertyID = PROP_YPOS;
if(key == 's' || key == 'S') propertyID = PROP_S;
if(key == 'r' || key == 'R') propertyID = PROP_R;
if(key == 'g' || key == 'G') propertyID = PROP_G;
if(key == 'b' || key == 'B') propertyID = PROP_B;
}
//usually a good idea to test - in this case use mouseY instead of distance sensor
void mouseDragged(){
distance = mouseY;
updatePropsOnDistance();
}
If this makes sense, it can easily be encapsulated in a class.
We could use an array to store those properties, but if something like props[0] for x, props1 for y, etc. is harder to read, you could use an IntDict which allows you to index values based on a String instead of a value (so you can do props["x"] instead of props[0]).
Here's an encapsulated version of the code:
import processing.serial.*;
Circle circle = new Circle();
void setup(){
size(400,400);
//initialize arduino - search for port based on OSX name
String[] portNames = Serial.list();
for(int i = 0 ; i < portNames.length; i++){
if(portNames[i].contains("usbmodem")){
try{
Serial arduino = new Serial(this,portNames[i],9600);
arduino.bufferUntil('\n');
return;
}catch(Exception e){
showSerialError();
}
}
}
showSerialError();
}
void showSerialError(){
System.err.println("Error connecting to Arduino!\nPlease check the USB port");
}
void draw(){
background(0);
circle.draw();
}
void serialEvent(Serial arduino){
String rawString = arduino.readString();
if(rawString != null){
String trimmedString = rawString.trim();
int rawDistance = int(trimmedString);
int distance = (int)map(rawDistance,1,200,1,height);
circle.update(distance);
}
}
void keyReleased(){
circle.setUpdateProperty(key+"");//update the circle property based on what key gets pressed. the +"" is a quick way to make a String from the char
}
//usually a good idea to test - in this case use mouseY instead of distance sensor
void mouseDragged(){
circle.update(mouseY);
}
class Circle{
//an IntDict (integer dictionary) is an associative array where instead of accessing values by an integer index (e.g. array[0]
//you access them by a String index (e.g. array["name"])
IntDict properties = new IntDict();
String updateProperty = "x";//property to update
Circle(){
//defaults
properties.set("x",200);
properties.set("y",200);
properties.set("s",20);
properties.set("r",127);
properties.set("g",127);
properties.set("b",127);
}
void draw(){
fill(properties.get("r"),properties.get("g"),properties.get("b"));
ellipse(properties.get("x"),properties.get("y"),properties.get("s"),properties.get("s"));
}
void setUpdateProperty(String prop){
if(properties.hasKey(prop)) updateProperty = prop;
else{
println("circle does not contain property: " + prop+"\navailable properties:");
println(properties.keyArray());
}
}
void update(int value){
properties.set(updateProperty,value);
}
}
In both examples you can test the distance value by dragging your mouse on the Y axis.
Regarding the HC-SR04 sensor, you can find code on the Arduino Playground to get the distance in cm. I haven't used the sensor myself yet, but I notice other people has some issues with it, so it's worth checking this post as well. If you want to roll your own Arduino code, no problem, you can use the HC-SR04 datasheet(pdf link) to get the formula:
Formula: uS / 58 = centimeters or uS / 148 =inch; or: the range = high
level time * velocity (340M/S) / 2; we suggest to use over 60ms
measurement cycle, in order to prevent trigger signal to the echo
signal.
It's important to get accurate values (you'll avoid jitter when using these to draw in Processing). Additionally you can use easing or a moving average.
Here's a basic moving average example:
int historySize = 25;//remember a number of past values
int[] x = new int[historySize];
int[] y = new int[historySize];
void setup(){
size(400,400);
background(255);
noFill();
}
void draw(){
//draw original trails in red
stroke(192,0,0,127);
ellipse(mouseX,mouseY,10,10);
//compute moving average
float avgX = average(x,mouseX);
float avgY = average(y,mouseY);
//draw moving average in green
stroke(0,192,0,127);
ellipse(avgX,avgY,10,10);
}
void mouseReleased(){
background(255);
}
float average(int[] values,int newValue){
//shift elements by 1, from the last to the 2nd: count backwards
float total = 0;
int size = values.length;
for(int i = size-1; i > 0; i--){//count backwards
values[i] = values[i-1];//copy previous value into current
total += values[i];//add values to total
}
values[0] = newValue;//add the newest value at the start of the list
total += values[0];//add the latest value to the total
return (float)total/size;//return the average
}

Finding Largest value in an array using recursion

This is my test array
int [] A = {1,2,7,3,5,6};
this is the method
public static int largest(int [] A)
{
int temp = A[0];
return largestRec(A, 0, A.length - 1, temp);
}
// WRITE THIS METHOD that returns the largest of the elements in A
// that are indexed from low to high. RECURSIVELY!
private static int largestRec(int [] A, int low, int high, int temp)
{
if (low == high)
return A[low];
if (low <= A.length){
if (A[low] > temp){
temp = A[low];
}
largestRec(A, low+1, high, temp);
}
return temp
}
Why does the tem reset and return A[0] which is 1?
The problem is that you are not doing anything with the return value of the recursive call to largestRec. Remember that parameters are pass by value (even in recursive calls to the same function) so changing it inside the function does not affect the outside.
I don't think you should be passing the temp as a parameter at all.
private static int largestRec(int [] A, int low, int high )
{
int temp;
if (low == high)
temp = A[low];
else
{
temp = largetstRec( A, low+1, high );
if (A[low] > temp){
temp = A[low];
}
}
return temp;
}
That keeps temp local to the function (which I think is what you probably meant be calling it temp in the first place).
private static int largestRec(int [] A, int low, int high){
var largest = A[low];
if(low == high)
return largest; // or A[high] because both are same
for(var i = low; i < high; i++){
if(largest < A[i])
largest = A[i];
}
return largest;
}

Are there any example of Mutual recursion?

Are there any examples for a recursive function that calls an other function which calls the first one too ?
Example :
function1()
{
//do something
function2();
//do something
}
function2()
{
//do something
function1();
//do something
}
Mutual recursion is common in code that parses mathematical expressions (and other grammars). A recursive descent parser based on the grammar below will naturally contain mutual recursion: expression-terms-term-factor-primary-expression.
expression
+ terms
- terms
terms
terms
term + terms
term - terms
term
factor
factor * term
factor / term
factor
primary
primary ^ factor
primary
( expression )
number
name
name ( expression )
The proper term for this is Mutual Recursion.
http://en.wikipedia.org/wiki/Mutual_recursion
There's an example on that page, I'll reproduce here in Java:
boolean even( int number )
{
if( number == 0 )
return true;
else
return odd(abs(number)-1)
}
boolean odd( int number )
{
if( number == 0 )
return false;
else
return even(abs(number)-1);
}
Where abs( n ) means return the absolute value of a number.
Clearly this is not efficient, just to demonstrate a point.
An example might be the minmax algorithm commonly used in game programs such as chess. Starting at the top of the game tree, the goal is to find the maximum value of all the nodes at the level below, whose values are defined as the minimum of the values of the nodes below that, whose values are defines as the maximum of the values below that, whose values ...
I can think of two common sources of mutual recursion.
Functions dealing with mutually recursive types
Consider an Abstract Syntax Tree (AST) that keeps position information in every node. The type might look like this:
type Expr =
| Int of int
| Var of string
| Add of ExprAux * ExprAux
and ExprAux = Expr of int * Expr
The easiest way to write functions that manipulate values of these types is to write mutually recursive functions. For example, a function to find the set of free variables:
let rec freeVariables = function
| Int n -> Set.empty
| Var x -> Set.singleton x
| Add(f, g) -> Set.union (freeVariablesAux f) (freeVariablesAux g)
and freeVariablesAux (Expr(loc, e)) =
freeVariables e
State machines
Consider a state machine that is either on, off or paused with instructions to start, stop, pause and resume (F# code):
type Instruction = Start | Stop | Pause | Resume
The state machine might be written as mutually recursive functions with one function for each state:
type State = State of (Instruction -> State)
let rec isOff = function
| Start -> State isOn
| _ -> State isOff
and isOn = function
| Stop -> State isOff
| Pause -> State isPaused
| _ -> State isOn
and isPaused = function
| Stop -> State isOff
| Resume -> State isOn
| _ -> State isPaused
It's a bit contrived and not very efficient, but you could do this with a function to calculate Fibbonacci numbers as in:
fib2(n) { return fib(n-2); }
fib1(n) { return fib(n-1); }
fib(n)
{
if (n>1)
return fib1(n) + fib2(n);
else
return 1;
}
In this case its efficiency can be dramatically enhanced if the language supports memoization
In a language with proper tail calls, Mutual Tail Recursion is a very natural way of implementing automata.
Here is my coded solution. For a calculator app that performs *,/,- operations using mutual recursion. It also checks for brackets (()) to decide the order of precedence.
Flow:: expression -> term -> factor -> expression
Calculator.h
#ifndef CALCULATOR_H_
#define CALCULATOR_H_
#include <string>
using namespace std;
/****** A Calculator Class holding expression, term, factor ********/
class Calculator
{
public:
/**Default Constructor*/
Calculator();
/** Parameterized Constructor common for all exception
* #aparam e exception value
* */
Calculator(char e);
/**
* Function to start computation
* #param input - input expression*/
void start(string input);
/**
* Evaluates Term*
* #param input string for term*/
double term(string& input);
/* Evaluates factor*
* #param input string for factor*/
double factor(string& input);
/* Evaluates Expression*
* #param input string for expression*/
double expression(string& input);
/* Evaluates number*
* #param input string for number*/
string number(string n);
/**
* Prints calculates value of the expression
* */
void print();
/**
* Converts char to double
* #param c input char
* */
double charTONum(const char* c);
/**
* Get error
*/
char get_value() const;
/** Reset all values*/
void reset();
private:
int lock;//set lock to check extra parenthesis
double result;// result
char error_msg;// error message
};
/**Error for unexpected string operation*/
class Unexpected_error:public Calculator
{
public:
Unexpected_error(char e):Calculator(e){};
};
/**Error for missing parenthesis*/
class Missing_parenthesis:public Calculator
{
public:
Missing_parenthesis(char e):Calculator(e){};
};
/**Error if divide by zeros*/
class DivideByZero:public Calculator{
public:
DivideByZero():Calculator(){};
};
#endif
===============================================================================
Calculator.cpp
//============================================================================
// Name : Calculator.cpp
// Author : Anurag
// Version :
// Copyright : Your copyright notice
// Description : Calculator using mutual recursion in C++, Ansi-style
//============================================================================
#include "Calculator.h"
#include <iostream>
#include <string>
#include <math.h>
#include <exception>
using namespace std;
Calculator::Calculator():lock(0),result(0),error_msg(' '){
}
Calculator::Calculator(char e):result(0), error_msg(e) {
}
char Calculator::get_value() const {
return this->error_msg;
}
void Calculator::start(string input) {
try{
result = expression(input);
print();
}catch (Unexpected_error e) {
cout<<result<<endl;
cout<<"***** Unexpected "<<e.get_value()<<endl;
}catch (Missing_parenthesis e) {
cout<<"***** Missing "<<e.get_value()<<endl;
}catch (DivideByZero e) {
cout<<"***** Division By Zero" << endl;
}
}
double Calculator::expression(string& input) {
double expression=0;
if(input.size()==0)
return 0;
expression = term(input);
if(input[0] == ' ')
input = input.substr(1);
if(input[0] == '+') {
input = input.substr(1);
expression += term(input);
}
else if(input[0] == '-') {
input = input.substr(1);
expression -= term(input);
}
if(input[0] == '%'){
result = expression;
throw Unexpected_error(input[0]);
}
if(input[0]==')' && lock<=0 )
throw Missing_parenthesis(')');
return expression;
}
double Calculator::term(string& input) {
if(input.size()==0)
return 1;
double term=1;
term = factor(input);
if(input[0] == ' ')
input = input.substr(1);
if(input[0] == '*') {
input = input.substr(1);
term = term * factor(input);
}
else if(input[0] == '/') {
input = input.substr(1);
double den = factor(input);
if(den==0) {
throw DivideByZero();
}
term = term / den;
}
return term;
}
double Calculator::factor(string& input) {
double factor=0;
if(input[0] == ' ') {
input = input.substr(1);
}
if(input[0] == '(') {
lock++;
input = input.substr(1);
factor = expression(input);
if(input[0]==')') {
lock--;
input = input.substr(1);
return factor;
}else{
throw Missing_parenthesis(')');
}
}
else if (input[0]>='0' && input[0]<='9'){
string nums = input.substr(0,1) + number(input.substr(1));
input = input.substr(nums.size());
return stod(nums);
}
else {
result = factor;
throw Unexpected_error(input[0]);
}
return factor;
}
string Calculator::number(string input) {
if(input.substr(0,2)=="E+" || input.substr(0,2)=="E-" || input.substr(0,2)=="e-" || input.substr(0,2)=="e-")
return input.substr(0,2) + number(input.substr(2));
else if((input[0]>='0' && input[0]<='9') || (input[0]=='.'))
return input.substr(0,1) + number(input.substr(1));
else
return "";
}
void Calculator::print() {
cout << result << endl;
}
void Calculator::reset(){
this->lock=0;
this->result=0;
}
int main() {
Calculator* cal = new Calculator;
string input;
cout<<"Expression? ";
getline(cin,input);
while(input!="."){
cal->start(input.substr(0,input.size()-2));
cout<<"Expression? ";
cal->reset();
getline(cin,input);
}
cout << "Done!" << endl;
return 0;
}
==============================================================
Sample input-> Expression? (42+8)*10 =
Output-> 500
Top down merge sort can use a pair of mutually recursive functions to alternate the direction of merge based on level of recursion.
For the example code below, a[] is the array to be sorted, b[] is a temporary working array. For a naive implementation of merge sort, each merge operation copies data from a[] to b[], then merges b[] back to a[], or it merges from a[] to b[], then copies from b[] back to a[]. This requires n ยท ceiling(log2(n)) copy operations. To eliminate the copy operations used for merging, the direction of merge can be alternated based on level of recursion, merge from a[] to b[], merge from b[] to a[], ..., and switch to in place insertion sort for small runs in a[], as insertion sort on small runs is faster than merge sort.
In this example, MergeSortAtoA() and MergeSortAtoB() are the mutually recursive functions.
Example java code:
static final int ISZ = 64; // use insertion sort if size <= ISZ
static void MergeSort(int a[])
{
int n = a.length;
if(n < 2)
return;
int [] b = new int[n];
MergeSortAtoA(a, b, 0, n);
}
static void MergeSortAtoA(int a[], int b[], int ll, int ee)
{
if ((ee - ll) <= ISZ){ // use insertion sort on small runs
InsertionSort(a, ll, ee);
return;
}
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoB(a, b, ll, rr);
MergeSortAtoB(a, b, rr, ee);
Merge(b, a, ll, rr, ee); // merge b to a
}
static void MergeSortAtoB(int a[], int b[], int ll, int ee)
{
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoA(a, b, ll, rr);
MergeSortAtoA(a, b, rr, ee);
Merge(a, b, ll, rr, ee); // merge a to b
}
static void Merge(int a[], int b[], int ll, int rr, int ee)
{
int o = ll; // b[] index
int l = ll; // a[] left index
int r = rr; // a[] right index
while(true){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
while(r < ee){ // else copy rest of right run
b[o++] = a[r++];
}
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
while(l < rr){ // else copy rest of left run
b[o++] = a[l++];
}
break; // and return
}
}
}
static void InsertionSort(int a[], int ll, int ee)
{
int i, j;
int t;
for (j = ll + 1; j < ee; j++) {
t = a[j];
i = j-1;
while(i >= ll && a[i] > t){
a[i+1] = a[i];
i--;
}
a[i+1] = t;
}
}

Resources