Skip to content

Instantly share code, notes, and snippets.

@zhezheng
Last active December 25, 2015 06:09
Show Gist options
  • Save zhezheng/6929850 to your computer and use it in GitHub Desktop.
Save zhezheng/6929850 to your computer and use it in GitHub Desktop.
Spreadsheet Calculator
/***************************
test case format:
3 2
A2
4 5 *
A1
A1 B2 / 2 +
3
39 B1 B2 * /
****************************/
#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
void initsheet(map<int,string> &str_map, int &width, int &height);
double operaHelper(double first, double second, char opt);
double opera(int order, map<int,string> str_map, map<int,double> &num_map, map<int,bool> &num_flag, int width, int height);
int main() {
map<int,string> str_map;
map<int,double> num_map;
map<int,bool> num_flag;
int width,height;
initsheet(str_map,width,height);
for(int i=0;i<width*height;i++) {
if(num_flag[i] == false) {
num_map[i] = opera(i, str_map, num_map, num_flag, width, height);
}
}
cout << width << " " << height << endl;
for(int i=0;i<int(num_map.size());i++) {
cout << fixed;
cout << setprecision(5) << num_map[i] << endl;
}
return 0;
}
//initialize the spreadsheet, first line is width and height, then each cell A(1), A(2), B(1).......
void initsheet(map<int,string> &str_map, int &width, int &height) {
string wh;
getline(cin,wh);
int num=0;
for(int i=0;i<int(wh.size());i++) {
if(wh[i]>='0' && wh[i]<='9'){
num = num*10 + int(wh[i] - '0');
}
else if(wh[i]==' ') {
width = num;
num = 0;
}
}
height = num;
for(int i=0;i<width*height;i++) {
string str_temp;
getline(cin,str_temp);
str_map[i] = str_temp;
}
}
//operator help function, deal with operator '+', '-', '*', '/' between two numbers
double operaHelper(double first, double second, char opt) {
if(opt == '+'){
return first + second;
}
else if(opt == '-'){
return first - second;
}
else if(opt == '*'){
return first * second;
}
else{
return first / second;
}
}
// Key function....
// Scan the string from beginning
// If it's a number, push it to the stack
// If it's a operator, pop two numbers from the stack, after calculation, push the result to the stack
// If it's a symbol of cell, do the recursion
// After finding value of a cell, set its flag true
double opera(int order, map<int,string> str_map, map<int,double> &num_map, map<int,bool> &num_flag, int width, int height) {
stack<double> num_stk;
string str = str_map[order];
double num_temp = 0;
bool hasNum = false;
for(int i=0; i<int(str.length());i++) {
if(str[i]>='A' && str[i]<='Z') {
int width_temp = 0;
int order_temp = int(str[i] - 'A')*width;
for(int j=i+1;j<int(str.length());j++) {
if(str[j] == ' ') {
break;
}
width_temp = 10*width_temp + int(str[j] - '0');
i = j;
}
order_temp += width_temp - 1;
if(num_flag[order_temp]) {
num_stk.push(num_map[order_temp]);
}
else {
num_temp = opera(order_temp, str_map, num_map, num_flag, width, height);
num_stk.push(num_temp);
num_temp = 0;
}
}
else if(str[i]>='0' && str[i]<='9') {
num_temp = 10*num_temp + double(str[i] - '0');
hasNum = true;
}
else if(str[i] == ' ') {
if(hasNum){
num_stk.push(num_temp);
num_temp = 0;
hasNum = false;
}
}
else if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
double second = num_stk.top();
num_stk.pop();
double first = num_stk.top();
num_stk.pop();
double result = operaHelper(first,second,str[i]);
num_stk.push(result);
}
}
if(hasNum) {
num_stk.push(num_temp);
hasNum = false;
}
num_map[order] = num_stk.top();
num_flag[order] = true;
return num_stk.top();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment