일반적으로 괄호가 없는 사칙연산을 계산할 때는 왼쪽에서부터 계산하며, 곱하기와 나누기를 더하기와 빼기보다 먼저 계산한다.
괄호가 없는 사칙연산 식을 입력받았을 때 오른쪽에서부터, 더하기나 빼기를 곱하기나 나누기보다 먼저 계산한 결과를 리턴하는 코드를 작성하라.
(단, 사칙연산 식은 문자열의 형식으로 입력받는다)
입력예시:
2+3*12/15-9
출력예시:
10
12개의 풀이가 있습니다.
import re
def split(text, type = True):
list = []
type1 = re.compile('[*]|[/]|[^*/]+')
type2 = re.compile('[+]|[-]|[0-9]+')
if type == True:
result = type1.finditer(text)
else:
result = type2.finditer(text)
for item in result:
list.append(item.group())
return list
def addandsubstract(text):
list = split(text, False)
result = float(list[0])
i = 1
while i < len(list):
if list[i] == "+":
result += float(list[i+1])
else:
result -= float(list[i+1])
i += 2
return result
def calculate(text):
list = split(text, True)
print(list)
result = addandsubstract(list[0])
i = 1
while i < len(list):
if list[i] == "*":
result *= addandsubstract(list[i+1])
else:
result /= addandsubstract(list[i+1])
i += 2
return result
test = '2+3*12/15-9'
print(calculate(test))
import re
k = '2+3*12/15-9'
def solution(a) :
tmp1 = re.split('(\D)', a)
for i in range(len(tmp1)-1):
if tmp1[i]=="+" or tmp1[i]=="-":
tmp1[i+1] = str(eval("".join(tmp1[i-1:i+2])))
tmp1[i-1] = ""
tmp1[i] = ""
return(eval("".join(tmp1)))
solution(k) # 10
+-가 없어질때까지 치환하고, */를 계산하는 방법이 있지만 다른분들이 풀이를 하셔서 저는 후위표기법으로 변환후에 계산하는것으로 풀어보았습니다.
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
/**
* @author Kimseongsu
* @see http://codingdojang.com/scode/590
*
*/
public class P590 {
public static void main(String[] args) {
final String INPUT = "2+3*12/15-9";
// System.out.println("input: " + INPUT);
final List<String> postfix = toPostfix(INPUT);
// System.out.println("postfix: [" + String.join(", ", postfix) + "]");
final int result = calc(postfix);
System.out.println(result);
}
/**
* 입력값을 후위표기법으로 변환
*/
private static List<String> toPostfix(final String input) {
List<String> infix = new ArrayList<>();
StringTokenizer st = new StringTokenizer(input, "-+*/", true);
while (st.hasMoreTokens()) {
infix.add(st.nextToken());
}
List<String> postfix = new ArrayList<>();
Stack<String> operator = new Stack<>(); // 연산자 임시 저장 스택
for (int i=infix.size()-1; i>=0; i--) { // 오른쪽부터
String exp = infix.get(i);
if (isNumber(exp)) {
postfix.add(exp);
} else {
if (operator.isEmpty() || getOpPriority(exp) > getOpPriority(operator.lastElement())) {
operator.push(exp);
} else {
while (!operator.isEmpty() && getOpPriority(exp) <= getOpPriority(operator.lastElement())) {
postfix.add(operator.pop());
}
operator.push(exp);
}
}
}
while (!operator.isEmpty()) {
postfix.add(operator.pop());
}
return postfix;
}
private static boolean isNumber(String str) {
return str.matches("\\d+");
}
private static int getOpPriority(String str) {
if (str.equals("+") || str.equals("-")) {
return 2;
}
if (str.equals("*") || str.equals("/")) {
return 1;
}
throw new RuntimeException("Unsupported Operator.");
}
private static int calc(List<String> postfix) {
Stack<Integer> result = new Stack<>();
for (String exp : postfix) {
if (isNumber(exp)) {
// 숫자일경우 그대로 스택에 push
result.push(Integer.valueOf(exp));
} else {
// 오른쪽부터 후위표기법으로 바꾸었으니, 먼저 들어간게 오른쪽값이 됨.
final int right = result.pop();
final int left = result.pop();
// 연산자에 따라 계산후, 다시 스택에 push
if (exp.equals("+")) {
result.push(right + left);
} else if (exp.equals("-")) {
result.push(right - left);
} else if (exp.equals("*")) {
result.push(right * left);
} else if (exp.equals("/")) {
result.push(right / left);
} else {
throw new RuntimeException("Unsupported Operator.");
}
}
// final String stackLog = String.join(", ", Arrays.asList(result.toArray()).stream().map(String::valueOf).collect(Collectors.toList()));
// System.out.println("exp: " + exp + ", \tstack: [" + stackLog + "]");
}
return result.pop(); // 마지막에 남은 숫자가 결과값.
}
}
#include<iostream>
#include"stdafx.h"
void Make_My_List(const string str,list<char> <)
{
for (string::size_type i = 0; i < str.size(); i++)
{
if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')
{
lt.push_front(str[i]);
}
}
}
void extract_num(const string str, list<int> &num_lt)
{
int branch=0;
for (string::size_type i = 0; i < str.size(); i++)
{
if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')
{
int k = 0;
char temp[10];
for (int j=branch; j<i; j++)
{
temp[k] = str[j];
k++;
}
num_lt.push_front(atoi(temp));
branch = i+1;
}
}
int k = 0;
char temp[10];
while (branch <= str.size())
{
temp[k++] = str[branch++];
}
num_lt.push_front(atoi(temp));
}
void Calculator(const string str,list<char> <,list<int> &num_lt)
{
if (lt.size() == 0)
return ;
else
{
list<char>::iterator iter1 = lt.begin();
list<int>::iterator iter2 = num_lt.begin();
if (*iter1 == '*' || *iter1 == '/')
{
list<char>::iterator comp;
if (lt.size() == 1)
comp = lt.begin();
else comp = ++iter1;
if (*comp == '+'|| *comp == '-')
{
int a, b;
iter2++, a = *iter2;
iter2 = num_lt.erase(iter2);
b = *iter2, num_lt.erase(iter2);
if (*comp == '+') num_lt.push_front(b + a);
else num_lt.push_front(b - a);
lt.erase(comp);
}
else
{
if (lt.size() > 1)
--iter1;
int a, b;
a = *iter2;
iter2++;
b = (*iter2);
num_lt.pop_front();
num_lt.pop_front();
if (*iter1 == '*') num_lt.push_front(b*a);
else num_lt.push_front(b / a);
lt.pop_front();
}
}
else
{
int a, b;
a = *iter2;
iter2++;
b = (*iter2);
num_lt.pop_front();
num_lt.pop_front();
if(*iter1=='+') num_lt.push_front(b+a);
else num_lt.push_front(b - a);
lt.pop_front();
}
return Calculator(str, lt, num_lt);
}
}
int main()
{
string str="2+3*12/15-9";
list<char> lt;
list<int> num_lt;
int result=0;
//cout << "input:";
//cin >> str;
Make_My_List(str, lt);
extract_num(str, num_lt);
Calculator(str, lt, num_lt);
cout << num_lt.front();
}
stl공부중인데 아직 너무 미숙하네요... 도중에 deque로 바꾸려고 했으나 오기 생겨서 끝까지list로 풀었네요;
t = input('입력: ')
x = list(i for i in t if i == '+' or i == '-' or i == '*' or i == '/')
y = t.replace('+',' ').replace('-',' ').replace('*',' ').replace('/',' ').split()
for i in range(len(x)-1,-1,-1):
if x[i] == '-' or x[i] == '+':
y[i] = str(eval(y[i] + x.pop(i) + y.pop(i+1)))
for i in sorted(range(len(x)),reverse=True):
y[i] = str(eval(y[i] + x.pop(i) + y.pop(i+1)))
print('출력: {}'.format(y[0]))
입력: 2+3*12/15-9
출력: 10.0
import re
s = '2+3*12/15-9'
while len(re.findall("\+|-", s)) > 0:
found = re.findall("\d+[\+|-]\d+", s)[0]
s = s.replace(found, str(eval(found)), 1)
print(eval(s))
def parse(string):
for op in '+-*/':
string = string.replace(op, ' ' + op + ' ')
return string.split()
def eval_(src):
# 더하기 빼기
lst = []
while src:
t = src.pop()
if t not in '+-':
lst = [t] + lst
else:
lst[0] = str(eval(src.pop() + t + lst[0]))
# 곱하기 나누기
val = lst.pop()
while lst:
op, t = lst.pop(), lst.pop()
val = str(eval(t + op + val))
return val
#inp = input()
inp = '2+3*12/15-9'
print(eval_(parse(inp)))
inp=input("사칙연산을 입력하십시오: ") #2+3*12/15-9
elst=[] # "*" 또는 "/"를 받기 위한 빈 리스트 생성
for num in inp:
if num=="*" or num=="/": #inp의 요소가 "*" 또는 "/"이면 elst에 추가하고 inp에 "*"이나 "/"은 " "(공백)으로 대체
elst.append(num)
inp=inp.replace(num," ")
inp=inp.split() #inp를 공백을 기준으로 나눔 -> ['2+3', '12', '15-9']
lst=[] #계산 결과를 받기 위한 빈 리스트 생성
for num in inp: #inp의 요소들을 계산하여 lst에 추가
result=eval(num)
lst.append(result)
lst=list(map(str,lst)) #계산결과는 숫자형태이므로 문자형으로 전환
i=0
for eq in elst: #lst의 홀수번째에 "*"나 "/"를 삽입
lst.insert(2*i+1,eq)
i+=1
print(eval("".join(lst))) #lst를 문자열화 시켜서 계산. #10.0
import re
def solution(s) :
numCom, opCom = re.compile("\d*\.?\d+"), re.compile("[*+-\/]{1}")
nums, ops = numCom.findall(s), opCom.findall(s)
while True :
for opIndex in range(len(ops)-1, -1, -1) :
if ops[opIndex] in ('+', '-') :
nums[opIndex] = str(eval(nums[opIndex]+ops[opIndex]+nums[opIndex+1]))
p1, p2 = nums.pop(opIndex+1), ops.pop(opIndex)
if not '+' in ops and not '-' in ops :
break
while True :
for opIndex in range(len(ops)-1, -1, -1) :
if ops[opIndex] in ('*', '/') :
nums[opIndex] = str(eval(nums[opIndex]+ops[opIndex]+nums[opIndex+1]))
p1, p2 = nums.pop(opIndex+1), ops.pop(opIndex)
if not '*' in ops and not '/' in ops :
break
return float(nums[0])
solution('2+3*12/15-9')
원시적인(?) 방법이라고 생각하면서 풀었는데, 풀고나서 보니 이렇게 푸신 분들도 좀 계시네요. 연산자랑 숫자를 전부 분리한 다음, 첫 번째 루프에서 덧셈과 뺄셈을, 두 번째 루프에서 곱셈과 나눗셈을 오른쪽부터 순서대로 계산하도록 했습니다.
결과
10.0
python 3.8
import re
a='2+3*12/15-9' # 부호가 있는 숫자는 고려하지 않았음
b=re.findall(r'[+*/\-]',a) # 부호부 분리
c=re.findall(r'\d+',a) # =re.split(r'\D',a) 숫자부
# b=re.split(r'(\D)',a) 숫자와 부호 분리
i=len(b)-1
while i>= 1: # +,- 고려 역순 계산
if b[i] in ['*','/'] and b[i-1] in ['-','+']:
c[i]=str(eval(c[i-1]+b[i-1]+c[i]))
c[i-1]=str(eval(c[i]+b[i]+c[i+1]))
i=i-2
else:
c[i]=str(eval(c[i]+b[i]+c[i+1]))
i=i-1
print(c[0]) # sum
자바로 풀어봤습니다.
import java.util.ArrayList;
import java.util.Scanner;
import java.util.List;
public class calculator {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
ArrayList<String> elements = new ArrayList<>();
ArrayList<String> result = new ArrayList<>();
// 입력
System.out.print("괄호가 없는 사칙연산식 입력:");
String equation = scan.nextLine();
String[] signs = {"+", "-", "*", "/"};
// 숫자, 기호 분리해서 리스트에 저장하기
equation = equation.replaceAll(" ", "");
while(equation.length()>0) {
// equation내에 연산 기호가 없으면 숫자만 있다고 판단하여 리스트에 저장
if(equation.contains("+")==false&equation.contains("-")==false&
equation.contains("*")==false&equation.contains("/")==false) {
elements.add(equation);
equation = "";
}
loop1 :
for(int i=0; i<equation.length(); i++) {
String element = equation.substring(i, i+1);
loop2 :
for(String sign : signs) {
if(element.equals(sign)) {
// 연산 기호 앞에 있는 숫자를 리스트에 저장
elements.add(equation.substring(0, i));
// 연산 기호를 리스트에 저장
elements.add(equation.substring(i, i+1));
// 리스트에 저장하지 않는 부분을 잘라서 다시 equation에 저장
equation = equation.substring(i+1, equation.length());
break loop1;
}
}
}
}
// +과 -부터 계산
String[] firstSigns = {"+", "-"};
loop3 :
for(int i=elements.size()-1; i>=0; i--) {
loop4 :
for(String sign : firstSigns) {
if(elements.get(i).equals(sign)) {
// i-2번째까지 elements 객체들을 result 리스트에 임시 저장
for(int j=0; j<i-1; j++) {
result.add(elements.get(j));
}
// 숫자들을 eleements 리스트에서 뽑아서 double형으로 변환
double m = Double.parseDouble(elements.get(i-1));
double n = Double.parseDouble(elements.get(i+1));
// 계산하고 result 리스트에 저장
if(sign.equals("+")) {
result.add(String.valueOf(m+n));
}else {
result.add(String.valueOf(m-n));
}
// 나머지 부분 result 리스트에 저장
for(int j=i+2; j<elements.size(); j++) {
result.add(elements.get(j));
}
// result 리스트를 elements 리스트에 복사 붙어넣기
elements.clear();
for(int j=0; j<result.size(); j++) {
elements.add(result.get(j));
}
result.clear();
break loop4;
}
}
}
// *과 / 계산
String[] secondSigns = {"*", "/"};
loop5 :
for(int i=elements.size()-1; i>=0; i--) {
loop6 :
for(String sign : secondSigns) {
if(elements.get(i).equals(sign)) {
// i-2번째까지 elements 객체들을 result 리스트에 임시 저장
for(int j=0; j<i-1; j++) {
result.add(elements.get(j));
}
// 숫자들을 eleements 리스트에서 뽑아서 double형으로 변환
double m = Double.parseDouble(elements.get(i-1));
double n = Double.parseDouble(elements.get(i+1));
// 계산하고 result 리스트에 저장
if(sign.equals("*")) {
result.add(String.valueOf(m*n));
}else {
result.add(String.valueOf(m/n));
}
// 나머지 부분 result 리스트에 저장
for(int j=i+2; j<elements.size(); j++) {
result.add(elements.get(j));
}
// result 리스트를 elements 리스트에 복사 붙어넣기
elements.clear();
for(int j=0; j<result.size(); j++) {
elements.add(result.get(j));
}
result.clear();
break loop6;
}
}
}
// 결과 출력
for(int i=0; i<elements.size(); i++) {
System.out.println("결과: "+elements.get(i));
}
}
}
def calc(op, v1, v2):
if op == '+': v1 += v2
elif op == '-': v1 -= v2
elif op == '*': v1 *= v2
elif op == '/': v1 //= v2
return v1
problem = '2+3*12/15-9'
nums = []
ops = []
su, op = '', ''
for p in problem:
if p == '*' or p == '/':
if op != '':
nums[-1] = calc(op, nums[-1], int(su))
else:
nums.append(int(su))
ops.append(p)
su, op = '', ''
elif p == '+' or p == '-':
nums.append(int(su))
op, su = p, ''
else:
su += p
if op == '+' or op == '-':
nums[-1] = calc(op, nums[-1], int(su))
else:
nums.append(int(su))
for i in range(len(ops)):
nums[0] = calc(ops[i],nums[0], nums[i+1])
print('\n\t{0} = {1}'.format(problem,nums[0]))