Complicated Expression

2015 网易校招的一道题

写了一年多的lua, C++ 都生锈了,拿出来操练一下

在lisp语言中,表达式都用前缀法表示,例如,1 + 2 在lisp中使用(+ 1 2)来表示,其中,表达式的括号是必需的。Bob 想实现一种类 lisp 的脚本语言,这个语言中的表达式是这样定义的:

1、每个表达式的形式都是 ( operator arg_1 arg_2 ... ),即由左括号,运算符,运算数,和右括号组成。

2、运算符包括三种,分别是‘+‘, ‘-‘, ‘*‘。

3、运算符如果可以接受一个运算数,就称为一元运算符,如果可以接受两个运算数,就称为二元运算符,如果可以接受三个及以上运算数,就称为多元运算符。

+ 可以是一元,二元,乃至多元运算符。

(+ 9) 表示正整数9;

(+ 1 2) 代表 1 + 2;

(+ 1 2 3 4) 代表 1, 2, 3, 4 的连加和。

- 可以是一元或者二元运算符。

(- 9) 表示整数-9;

(- 5 4) 代表 5 - 4。

* 可以是二元运算符或者多元运算符。

(* 2 3) 代表 2 * 3;

(* 1 2 3 4) 代表 1 * 2 * 3 * 4。

4、运算数可以是一个正整数,或者0,还可以是另外一个表达式,例如

(+ (* 2, 3) 1) 也是一个合法的表达式,代表了 2 * 3 + 1

5、运算符与运算数之间,运算数与运算数相互之间都以空格进行分隔。在不产生歧义的情况下,空格也可以省略。例如,

(+ 2 3) 和 ( +2 3) 都被认为是合法的输入,且有相同的意义,代表 2 + 3。(+ 23)也是一个合法的输入,但其代表的是正整数23。

输入
输入由多行组成,第一行包含一个正整数T(T <= 5000)。代表共包含T组测试数据。

接下来会有T行输入。每一行包含一个表达式。这个表达式可能是一个合法的表达式,也可能是不合法的表达式。

每行数据所包含的字符数,不超过1000000。

输入数据中的数字全部是十进制正整数或者0,而且正整数的值不会大于65535。

输入中的表达式只包含三种不同类型的错误,除此之外的情况,都不必考虑。

第一类错误,括号不匹配,例如

(+ (* 2 3) 1)) 多了一个右括号;

+ 2 3 缺少括号等。

第二类错误,运算符缺失,例如

(2 3) 没有运算符。

第三类错误,运算符与数字不匹配,例如

(- 1 2 3),由于 - 只能接受最多两个算数,所以这也是一个不合法的表达式。

输出
对于合法的表达式,请输出表达式的值,对于不合法的表达式,请输出“invalid expression”。

可以假设最后的结果不超过32位整数的表示范围,但不保证在某些情况下,计算的中间值全部不超过32位整数的表示范围。

样例输入
5
(+ 1 (* 2 3)))
(2 3)
(- 3 2 1)
(+ (+ 1 2) (* 2 3) (- 2 1))
(- 2)
样例输出
invalid expression
invalid expression
invalid expression
10
-2

这题就是对栈的使用,学过数据结构的应该都会。只是时间长短而已,不得不承认工作久了写这种东西明显不如学生时代了。

源代码:

  1 #include <iostream>
  2 //#include <string>
  3 #include <stack>
  4 #include <stdio.h>
  5 #include <string.h>
  6
  7 using namespace std;
  8
  9 typedef std::stack<std::string> strStack;
 10 typedef std::stack<double> valueStack;
 11
 12
 13 inline int parseStr(const char*& str, strStack &tempStack)
 14 {
 15     const char* begin = str;
 16     const char* p = str;
 17     while (*p)
 18     {
 19         char buf[50];
 20         if (*p == ‘(‘ || *p == ‘+‘ || *p == ‘-‘ || *p == ‘*‘)
 21         {
 22             buf[0] = *p;
 23             buf[1] = 0;
 24             tempStack.push(buf);
 25             if (p == begin)
 26                 ++begin;
 27         }
 28         else if (*p == ‘ ‘)
 29         {
 30             if (p == begin)
 31                 ++begin;
 32             else
 33             {
 34                 int size = p - begin;
 35                 strncpy(buf, begin, size);
 36                 buf[size] = 0;
 37                 tempStack.push(buf);
 38                 begin = p + 1;
 39             }
 40         }
 41         else if (*p == ‘)‘)
 42         {
 43             if (p != begin)
 44             {
 45                 int size = p - begin;
 46                 strncpy(buf, begin, size);
 47                 buf[size] = 0;
 48                 tempStack.push(buf);
 49                 begin = p + 1;
 50             }
 51             ++p;
 52             break;
 53         }
 54         else
 55         {
 56             // 可以做一些非法字符检查, 这题貌似不需要
 57         }
 58         ++p;
 59     }
 60     str = p;
 61     return 0;
 62 }
 63
 64
 65 inline int calAdd(strStack& stack, double&result)
 66 {
 67     if (stack.size() < 1)
 68         return -1;
 69
 70     double r = 0;
 71     while (!stack.empty())
 72     {
 73         std::string str = stack.top();
 74         stack.pop();
 75         double val;
 76         sscanf(str.c_str(), "%lf", &val);
 77         r += val;
 78     }
 79     result = r;
 80     return 0;
 81 }
 82
 83 inline int calSub(strStack& stack, double&result)
 84 {
 85     if (stack.size() < 1 || stack.size() > 2)
 86         return -1;
 87
 88     std::string str = stack.top();
 89     stack.pop();
 90     double val1;
 91     sscanf(str.c_str(), "%lf", &val1);
 92     if (stack.size() == 0)
 93     {
 94         result = -val1;
 95         return 0;
 96     }
 97
 98     str = stack.top();
 99     stack.pop();
100     double val2;
101     sscanf(str.c_str(), "%lf", &val2);
102     result = val1 - val2;
103
104     return 0;
105 }
106
107 inline int calMul(strStack& stack, double& result)
108 {
109     if (stack.size() < 1)
110         return -1;
111
112     double r = 1;
113     while ( !stack.empty())
114     {
115         std::string str = stack.top();
116         stack.pop();
117         double val;
118         sscanf(str.c_str(), "%lf", &val);
119         r *= val;
120     }
121     result = r;
122     return 0;
123 }
124
125
126 // 成功返回0
127 int calSubOprator(strStack& stack, double &result)
128 {
129     int r = 0;
130     double val = 0;
131     std::string operaterStr = stack.top();
132     stack.pop();
133     if (operaterStr == "+")
134     {
135         r = calAdd(stack, val);
136     }
137     else if (operaterStr == "-")
138     {
139         r = calSub(stack, val);
140     }
141     else if (operaterStr == "*")
142     {
143         r = calMul(stack, val);
144     }
145     else
146         return -1;
147
148     if (r == -1)
149         return -1;
150
151     result = val;
152     return 0;
153 }
154
155 inline int calcStr(strStack &tempStack, valueStack& resultStack)
156 {
157     strStack temp;
158     while (true)
159     {
160         if (tempStack.empty())
161             return -1;
162
163         std::string str = tempStack.top();
164         if (str == "#")
165         {
166             double val = resultStack.top();
167             resultStack.pop();
168             tempStack.pop();
169             char buf[50];
170             sprintf(buf, "%d", int(val));
171             temp.push(buf);
172         }
173         else if (str == "(")
174         {
175             tempStack.pop();
176             break;
177         }
178         else
179         {
180             temp.push(tempStack.top());
181             tempStack.pop();
182         }
183     }
184
185     double val;
186     if (calSubOprator(temp, val) == -1)
187         return -1;
188
189     resultStack.push(val);
190     return 0;
191 }
192
193
194 int calc(const char* str, double &resultVal)
195 {
196     if (str == NULL || *str == 0)
197         return -1;
198
199     const char* p = str;
200     strStack tempStr;
201     valueStack tempVal;
202
203     while (true)
204     {
205         int r = 0;
206         r = parseStr(p, tempStr);
207         if (r == -1)
208             return -1;
209
210         r = calcStr(tempStr, tempVal);
211         if (r == -1)
212             return -1;
213
214         if (*p == 0)
215         {
216             if (tempStr.empty())
217             {
218                 resultVal = tempVal.top();
219                 tempVal.pop();
220             }
221             else
222                 return -1;
223             break;
224         }
225         else
226         {
227             // 临时结果入栈
228             tempStr.push("#");
229         }
230     }
231
232     return 0;
233 }
234
235
236 int main()
237 {
238
239     const char*arr[] = {
240         "(+ 1 (* 2 3)))",
241         "(2 3)",
242         "(- 3 2 1)",
243         "(+ (+ 1 2) (* 2 3) (- 2 1))",
244         "(- 2)"
245     };
246
247
248     for (int i = 0; i < 5; ++i)
249     {
250         const char* buf = arr[i];
251         double result = 0;
252         if (calc(buf, result) == 0)
253         {
254             cout << result << endl;
255         }
256         else
257         {
258             cout << "invalid expression" << endl;
259         }
260
261     }
262
263     return 0;
264 }
时间: 2024-10-13 11:55:13

Complicated Expression的相关文章

C++ Primer 读书笔记1

1.在Windows系统中输入文件结束符的方法为Ctrl+Z 2.如何选择类型? 1) Use an unsigned type when youknow that the values cannot be negative 2) Use int for integer arithmetic.short is usually too small and, in practice, long often has the same size asint. If your data values ar

Machine Learning - Neural Networks Learning: Cost Function and Backpropagation

This series of articles are the study notes of " Machine Learning ", by Prof. Andrew Ng., Stanford University. This article is the notes of week 5, Neural Networks Learning. This article contains some topic about Cost Function and Backpropagatio

Code Complete阅读笔记(二)

2015-03-06   328   Unusual Data Types    ——You can carry this technique to extremes,putting all the variables in your program into one big,juicy variable and then passingit everywhere.Careful programmers avoid bundling data any more than is logically

统计学习笔记(3) 监督学习概论(3)

Some further statements on KNN: It appears that k-nearest-neighbor fits have a single parameter, the number of neighbors k, compared to the p parameters in least-squares fits. Although this is the case, we will see that the effective number of parame

为什么深度神经网络难以训练Why are deep neural networks hard to train?

Imagine you're an engineer who has been asked to design a computer from scratch. One day you're working away in your office, designing logical circuits, setting out AND gates, OR gates, and so on, when your boss walks in with bad news. The customer h

Spark1.1.0 Spark SQL Programming Guide

Spark SQL Programming Guide Overview Getting Started Data Sources RDDs Inferring the Schema Using Reflection Programmatically Specifying the Schema Parquet Files Loading Data Programmatically Configuration JSON Datasets Hive Tables Performance Tuning

MinGW - GCC 6.1.0

GCC 6.1 mingw-gcc-6.1.7z 极限压缩(39.8MB) https://sourceforge.net/projects/mingwbundle/files/GCC%206.1.0/ https://gcc.gnu.org/gcc-6/changes.html GCC 6 Release Series — Changes, New Features, and Fixes - GNU Project - Free Software Foundation (FSF) GCC 6

LeetCode 10. Regular Expression Matching

https://leetcode.com/problems/regular-expression-matching/description/ Implement regular expression matching with support for '.' and '*'. '.' Matches any single character. '*' Matches zero or more of the preceding element. The matching should cover

Spring AOP中pointcut expression表达式解析 及匹配多个条件

Pointcut 是指那些方法需要被执行"AOP",是由"Pointcut Expression"来描述的. Pointcut可以有下列方式来定义或者通过&& || 和!的方式进行组合. args() @args() execution() this() target() @target() within() @within() @annotation 其中 execution 是用的最多的,其格式为: execution(modifiers-pat