fork download
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <memory>
  5. #include <map>
  6. #include <tuple>
  7.  
  8. struct Item{
  9. virtual char GetToken()=0;
  10. };
  11. struct Num :public Item {
  12. int N;
  13. Num(int N_){
  14. N = N_;
  15. }
  16. char GetToken(){
  17. return 'N';
  18. }
  19. };
  20. struct Token :public Item {
  21. char C;
  22. Token(char C_){
  23. C = C_;
  24. }
  25. char GetToken(){
  26. return C;
  27. }
  28. };
  29.  
  30. struct bunsuu :public Item {
  31. public:
  32. int C,M;
  33.  
  34. bunsuu(int C_, int M_){
  35. C = C_;
  36. M = M_;
  37. }
  38.  
  39. char GetToken(){
  40. return ':';
  41. }
  42.  
  43. };
  44. typedef std::shared_ptr<Item> IType;
  45. typedef std::vector<IType> MType;
  46. typedef std::tuple<MType, MType> PType;
  47.  
  48.  
  49. int ToNumber(wchar_t C){
  50. std::map<wchar_t, int> m{ { L'0', 0 }, { L'1', 1 }, { L'2', 2 }, { L'3', 3 }, { L'4', 4 }, { L'5', 5 }, { L'6', 6 }, { L'7', 7 }, { L'8', 8 }, { L'9', 9 }, };
  51.  
  52. return m[C];
  53. }
  54. char ToToken(wchar_t C){
  55. std::map<wchar_t, char> m{ { L'/', ':' }, { L'÷', '/' }, { L'+', '+' }, { L'-', '-' }, { L'×', '*' }, { L'*', '*' }};//分数記号はなんかいい案無いだろうか。
  56.  
  57. return m[C];
  58. }
  59. bool IsNumber(wchar_t C){
  60. std::map<wchar_t, bool> m{ { L'0', true }, { L'1', true }, { L'2', true }, { L'3', true }, { L'4', true }, { L'5', true }, { L'6', true }, { L'7', true }, { L'8', true }, { L'9', true }, };
  61.  
  62. return m[C];
  63. }
  64. bool IsToken(wchar_t C){
  65. std::map<wchar_t, bool> m{ { L'/', true }, { L'÷', true }, { L'+', true }, { L'-', true }, { L'×', true }, { L'*', true }};
  66.  
  67. return m[C];
  68. }
  69.  
  70. MType MakeSiki(std::wstring& s){
  71. MType R;
  72. std::shared_ptr<Item> I;
  73. for (std::size_t i = 0; i < s.length(); i++){
  74. switch (s[i])
  75. {
  76. case L'1':
  77. case L'2':
  78. case L'3':
  79. case L'4':
  80. case L'5':
  81. case L'6':
  82. case L'7':
  83. case L'8':
  84. case L'9':
  85. R.push_back(std::make_shared<Num>(ToNumber(s[i])));
  86. break;
  87. case L'+':
  88. case L'-':
  89. case L'*':
  90. case L'×':
  91. case L'÷':
  92. R.push_back(std::make_shared<Token>(ToToken(s[i])));
  93. break;
  94. case L'/':
  95. I = R.back();
  96. R.pop_back();
  97. R.push_back(std::make_shared<bunsuu>(static_cast<Num*>(&(*I))->N, ToNumber(s[i + 1])));
  98. i++;
  99. break;
  100. default:
  101. break;
  102. }
  103. }
  104. return R;
  105. }
  106.  
  107. PType SepSiki(MType& s){
  108. MType N;
  109. MType T;
  110. for (auto&o : s){
  111. switch (o->GetToken())
  112. {
  113. case ':':
  114. case 'N':
  115. N.push_back(o);
  116. break;
  117. case '+':
  118. case '-':
  119. case '*':
  120. case '/':
  121. T.push_back(o);
  122. break;
  123. default:
  124. break;
  125. }
  126. }
  127.  
  128. return std::make_tuple(N, T);
  129. }
  130.  
  131. IType CalcOne(int A, int B,char o){
  132. switch (o)
  133. {
  134. case '+':
  135. return std::make_shared<Num>(A + B);
  136. case '-':
  137. return std::make_shared<Num>(A - B);
  138. case '*':
  139. return std::make_shared<Num>(A * B);
  140. case '/':
  141. return std::make_shared<bunsuu>(A , B);
  142.  
  143. default:
  144. break;
  145. }
  146. return std::make_shared<Num>(0);
  147. }
  148. IType CalcOne(bunsuu A, bunsuu B,char o){
  149. bunsuu C(1,1);
  150. bunsuu D(A.C*B.M, A.M*B.M);//GCDが無いとオーバーフローする。
  151. bunsuu E(B.C*A.M, B.M*A.M);
  152. switch (o)
  153. {
  154. case '+':
  155. C.M = D.M;
  156. C.C = D.C+E.C;
  157. break;
  158. case '-':
  159. C.M = D.M;
  160. C.C = D.C-E.C;
  161. break;
  162.  
  163. case '*':
  164. C.M = B.M*A.M;
  165. C.C = B.C*A.C;
  166. break;
  167. case '/':
  168. C.M = B.C*A.M;
  169. C.C = B.M*A.C;
  170. break;
  171.  
  172. default:
  173. break;
  174. }
  175.  
  176. if (C.C%C.M == 0){
  177. return std::make_shared<Num>(C.C / C.M);
  178. }
  179. else{
  180. return std::make_shared<bunsuu>(C);
  181. }
  182. }
  183. IType CalcOne(bunsuu A, int B,char o){
  184. return std::make_shared<Num>(-1);
  185. }
  186. IType CalcOne(int A, bunsuu B,char o){
  187. bunsuu C(1,1);
  188. switch (o)
  189. {
  190. case '/':
  191. C.M = B.C;
  192. C.C = B.M*A;
  193. break;
  194. default:
  195. break;
  196. }
  197.  
  198. if (C.C%C.M == 0){
  199. return std::make_shared<Num>(C.C / C.M);
  200. }
  201. else{
  202. return std::make_shared<bunsuu>(C);
  203. }
  204.  
  205. }
  206.  
  207. IType CalcOne(IType a, IType b, IType o){
  208.  
  209. if (a->GetToken() == 'N'){
  210. if (b->GetToken() == 'N'){
  211. return CalcOne(static_cast<Num*>(&(*a))->N, static_cast<Num*>(&(*b))->N, o->GetToken());
  212. }
  213. else{
  214. return CalcOne(static_cast<Num*>(&(*a))->N, *static_cast<bunsuu*>(&(*b)), o->GetToken());
  215. }
  216. }
  217. else{
  218. if (b->GetToken() == 'N'){
  219. return CalcOne(*static_cast<bunsuu*>(&(*a)), static_cast<Num*>(&(*b))->N, o->GetToken());
  220. }
  221. else{
  222. return CalcOne(*static_cast<bunsuu*>(&(*a)), *static_cast<bunsuu*>(&(*b)), o->GetToken());
  223. }
  224. }
  225.  
  226. /** /
  227. return CalcOne(
  228. a->GetToken() == 'N' ? (static_cast<Num*>(&(*a)))->N : *static_cast<bunsuu*>(&(*a)),
  229. a->GetToken() == 'N' ? (static_cast<Num*>(&(*a)))->N : *static_cast<bunsuu*>(&(*a)),
  230. o->GetToken()
  231. );
  232. */
  233. return std::make_shared<Num>(-1);
  234. }
  235.  
  236. IType Calc(PType& P){
  237. MType &N = std::get<0>(P);
  238. MType &T = std::get<1>(P);
  239. for (std::size_t i = 0; i < T.size(); i++){
  240. if (T[i]->GetToken() == '*' || T[i]->GetToken() == '/'){
  241. N[i] = CalcOne(N[i], N[i + 1], T[i]);
  242. N.erase(N.begin() + i + 1);
  243. T.erase(T.begin() + i);
  244. i--;
  245. }
  246. }
  247. for (std::size_t i = 0; i < T.size(); i++){
  248. if (T[i]->GetToken() == '+' || T[i]->GetToken() == '-'){
  249. N[i] = CalcOne(N[i], N[i + 1], T[i]);
  250. N.erase(N.begin() + i + 1);
  251. T.erase(T.begin() + i);
  252. i--;
  253. }
  254. }
  255. return N[0];
  256. }
  257.  
  258. //コピペした。もう無理。
  259. //http://w...content-available-to-author-only...l.edu/~victor/mfmm/
  260. //http://w...content-available-to-author-only...l.edu/~victor/mfmm/compaa/gcd.c
  261. int gcd(int a, int b)
  262. {
  263. int c;
  264. while (a != 0) {
  265. c = a; a = b%a; b = c;
  266. }
  267. return b;
  268. }
  269.  
  270. bool Show(IType i){
  271. if (i->GetToken() == 'N'){
  272. std::cout<<static_cast<Num*>(&(*i))->N<<std::endl;
  273. }
  274. else{
  275. bunsuu &b = *static_cast<bunsuu*>(&(*i));
  276. int N = gcd(b.C, b.M);
  277. std::cout<<b.C/N<<'/'<<b.M/N<<std::endl;
  278. }
  279. return true;
  280. }
  281.  
  282. IType MakeHoge(std::wstring s){
  283. MType Siki = MakeSiki(s);
  284. PType P = SepSiki(Siki);
  285.  
  286. IType R = Calc(P);
  287.  
  288. return R;
  289. }
  290.  
  291. int main(){
  292. IType A = 0;
  293.  
  294. A = MakeHoge(L"9-3÷1/3+1");
  295. Show(A);
  296. A = MakeHoge(L"1/2÷3/4÷5/6×7/8");
  297. Show(A);
  298.  
  299. return 0;
  300. }
Success #stdin #stdout 0s 3492KB
stdin
Standard input is empty
stdout
1
7/10