이 페이지는 코딩도장 데이터의 읽기 전용 정적 보관본입니다.

순서대로 계산기

문제

현우는 초등학생인 여동생의 수학 숙제를 도와주고 있었다.

현우는 동생을 좀 더 잘 가르치고 싶어 답을 구하는 과정을 되도록 자세히 알려주려고 오른쪽에서 왼쪽으로 순차적으로 계산하는 과정을 보여주고자 한다.

단, 일반적인 수식과 같이 곱하기(*)와 나누기(/)는 연산자 우선순위가 높으므로 먼저 계산해야 한다. 현우를 도와 수식을 입력 받으면 계산과정과 결과를 보여주는 코드를 작성하도록 하자.

입력

한 줄로 숫자와 사칙 연산 기호 +, -, *, /로 이루어진 수식이 입력된다.

출력

한 줄마다 오른쪽에서 왼쪽으로 한 단계씩 계산된 결과와 나머지 수식을 출력한다.

예시

예시 0

입력

9+5-4+8

출력

14-4+8
10+8 
18

예시 1

입력

5+6*3-6/2+5

출력

5+18-6/2+5
5+18-3+5
23-3+5
20+5
25

2018/08/13 17:05

leak

입력 받는 과정에서 공백을 써도 되나요? - 김영성, 2018/08/13 22:32
넵 상관없을듯하네요 - leak, 2018/08/13 22:40
감사합니다 - 김영성, 2018/08/14 00:13
*앞에 \를 붙이면 *를 단순한 문자로 사용하실 수 있습니다. - *IDLE*, 2018/08/25 23:48
오옹 꿀팁 감사합니다 - leak, 2018/08/30 12:57

17개의 풀이가 있습니다.

def solve(n):
    l=n
    count=0
    for i in range(len(l)):
        if n[i] in '+-':
            count+=1
        if count>=1:
            l=str(eval(n[:i]))+n[i:]
            print(l)
        count=0
    return eval(l)

print(solve('12+15*6+56/4+1+51'))

>>>12+15*6+56/4+1+51
   102+56/4+1+51
   116.0+1+51
   117.0+51
   168.0

좀있다난이도업 풀어야징

2018/08/13 17:46

leak

코드에 오류가 있는 것 같은데요 단계별로 계산한다 하셨는데 한번에 여러 계산을 합니다. def solve(n): l=n for i in range(len(l)): if n[i] in '+-': l=str(eval(n[:i]))+n[i:] print(l) return eval(l) - 김영성, 2018/08/14 00:13
지적감사합니다 아직저도부족하여.. - leak, 2018/08/14 00:12
저도 아직 한참 부족한데 지적에 기분 나빴다면 사과드립니다. 항상 좋은문제 만들어 주셔서 감사드립니다 - 김영성, 2018/08/14 00:17
아유 지적을받아야 저도 성장하는데요 덕분에 저만감사하죠 - leak, 2018/08/14 00:53

split해서 각각을 리스트로 만들어서 */ 연산 먼저 처리하고 +-처리하도록 구현했습니다. 먼저 처리하면 순번이 엇갈리는 문제가 발생해서 재귀함수로 구현했습니다.

input1 = '12+15*6+56/4+1+51'

def calc_once(input1):
    print(input1)

    if input1.isdigit():
        return input1

    for i in '+-*/':
        input1 = input1.replace(i, ' '+ i + ' ')
    arr1 = input1.split()

    for i in range(len(arr1)):
        if arr1[i] in '*/':
            data = ("".join(arr1[:i-1]) + str(eval(arr1[i-1] + arr1[i] + arr1[i+1])) + "".join(arr1[i+2:]))
            return calc_once(data)

    for i in range(len(arr1)):
        if arr1[i] in '+-':
            data = ("".join(arr1[:i-1]) + str(eval(arr1[i-1] + arr1[i] + arr1[i+1])) + "".join(arr1[i+2:]))
            return calc_once(data)

calc_once(input1)
#output
12+15*6+56/4+1+51
12+90+56/4+1+51
12+90+14.0+1+51
102+14.0+1+51
116.0+1+51
117.0+51
168.0

2018/08/13 22:22

재즐보프

def i(e,f):
     return e.index(f) if f in e else len(e)+1

def cal1(e):
     print(e)
     e = list(e)
     for x in range(e.count('-')+e.count('+')+e.count('*')+e.count('/')):
          if e.count('-')+e.count('+')+e.count('*')+e.count('/') == 1:
                    print(eval(''.join(e)))
                    exit()
          ix = min(i(e,'*'),i(e,'/')) if '*' in e or '/' in e else min(i(e,'+'),i(e,'-'))
          c1,c2 = ix-1,ix+1
          while True:
               if e[c2] in '+-*/' and e[c1] in '+-*/':
                    break
               else:
                    c1 -= 0 if e[c1] in '+-*/' else 1
                    c2 += 0 if e[c2] in '+-*/' else 1
          if c1 < -1:
               c1 = -1
          e[c2-1] = str(eval(''.join(e[c1+1:c2])))
          del e[c1+1:c2-1]
          print(''.join(e))

#공백이 있을 때
def cal2(e):
     print(e)
     e = e.split()
     for x in range(e.count('-')+e.count('+')+e.count('*')+e.count('/')):
          ix = min(i(e,'*'),i(e,'/')) if '*' in e or '/' in e else min(i(e,'+'),i(e,'-'))
          e[ix+1] = str(eval(''.join(e[ix-1:ix+2])))
          del e[ix-1:ix+1]
          print(''.join(e))

2018/08/14 00:23

김영성

import re

def slow_cal(line):
    nums, ops = re.findall('\d+', line), re.findall('[+\-*/]', line)
    for o in ops :
        if o in "*/":
            idx = ops.index(o)
            a, b = nums.pop(idx), nums.pop(idx)
            nums.insert(idx, str(int(eval(a+o+b))))
            ops.remove(o)
            pp(nums, ops)
    while len(ops) > 0 :
        nums.insert(0, str(int(eval(nums.pop(0)+ops.pop(0)+nums.pop(0)))))
        pp(nums, ops)

def pp(nums, ops):
    i, r = 0, ""
    while i < len(ops):
        r += nums[i] + ops[i]
        i += 1
    print(r + nums[i])

slow_cal("5+6*3-6/2+5")

2018/08/17 14:33

Sukeoul Jang

eval() 일부러 안 쓰고 했습니다.

dict() is not callable....

몰랐던 걸 알았네요.

def tokenize(str):
    for op in '*/+-':
        str = str.replace(op, ' ' + op + ' ')
    return str.split()

def calc(exp, i):
    opr1, op, opr2 = int(exp[i - 1]), exp[i], int(exp[i + 1])
    func = [lambda x, y: x * y, lambda x, y: x // y, lambda x, y: x + y, lambda x, y: x - y]
    newterm = str(func['*/+-'.index(op)](opr1, opr2))
    return exp[:i-1] + [newterm] + exp[i + 2:]

def reduce_once(exp):
    for i in range(len(exp)):
        if exp[i] in '*/':
            return calc(exp, i)

    for i in range(len(exp)):
        if exp[i] in '+-':
            return calc(exp, i)

def reduce(exp_str):
    print(exp_str)
    exp = tokenize(exp_str)
    while len(exp) > 1:
        exp = reduce_once(exp)
        print(''.join(exp))

reduce('9+5-4+8')
reduce('5+6*3-6/2+5')

2018/08/19 01:50

Noname

import re
t= re.compile('[\d]*([+]|[-])[\d]*')
t2= re.compile('[\d]*([*]|[/])[\d]*')
a ='9+5-4+8'
b ='5+6*3-6/2+5'

def func(a):
    while t.search(a):
        if t.search(a):
            a=a.replace(t.search(a).group(0),str(eval(t.search(a).group(0))))
            print(a)

while t2.search(b):
    if t2.search(b):
        b=b.replace(t2.search(b).group(0),str(int(eval(t2.search(b).group(0)))))
        print(b)
func(b)
print('-------------------')
func(a)

2018/08/20 16:24

S.H

처음에 만든 방식입니다.

sprit으로 나누고 연산기호 하나 계산 후 다시 String으로 합치는 것을 반복합니다.
위 과정을 while로 돌렸습니다.

문제에서 제시한 예시는 정상적으로 출력됩니다만.. 첫 숫자가 음수이거나 답이 음수가 되는 경우 정상적인 출력이 되지 않았습니다.
    public static void main(String[] args) {
        String math = "3434+523*6*3-4312/2+245*45";
        String[] num = math.split("[^0-9]");
        String[] sign = math.split("[0-9]+");
        while (!math.matches("[0-9]+")) {
            for (int i = 1; i < sign.length; i++) {
                if (sign[i].matches("[*/]") || (!math.matches(".*[*/].*") && sign[i].matches("[\\+\\-]"))) {
                    int a = Integer.valueOf(num[i - 1]);
                    int b = Integer.valueOf(num[i]);
                    num[i - 1] = (sign[i].equals("*") ? a * b
                            : sign[i].equals("/") ? a / b : sign[i].equals("+") ? a + b : a - b) + "";
                    num[i] = sign[i] = "";
                    math = math(num, sign, "");
                    num = math.split("[^0-9]");
                    sign = math.split("[0-9]+");
                    System.out.println(math);
                    break;
                }
            }
        }
    }

    private static String math(String[] num, String[] sign, String math) {
        for (int i = 0; i < num.length; i++)
            math += i == num.length - 1 ? num[i] : num[i] + sign[i + 1];
        return math;
    }
두번째로 만든 코드입니다.

하나의 배열에 전부 나눠넣어 곱하기와 나누기 연산을 끝낸 후
새로운 for로 더하기 빼기를 했습니다.

음수냐 아니냐에 따라 sprit으로 나눠지는 위치가 달라 고생을 하였습니다.
public static void main(String[] args) {
        String input = "5*1217+4*7+3*123+8*3*4*5*6*7*2/2+3";
        String[] math = (input.replaceAll("\\+", " +").replaceAll("-", " -").replaceAll("\\*", " *").replaceAll("/",
                " /")).split(" ");
        for (int i = math[0].equals("") ? 2 : 1; i < math.length; i++) {
            if (math[i].matches("[*/].*")) {
                int temp = Check(math, i - 1);
                int a = Integer.valueOf(math[temp]);
                int b = Integer.valueOf(math[i].substring(1));
                math[temp] = (math[i].startsWith("*") ? a * b : a / b) + "";
                math[i] = "";
                print(math);
            }
        }
        for (int i = 2; i < math.length; i++)
            if (!math[i].equals("")) {
                int temp = math[0].equals("") ? 1 : 0;
                math[temp] = (Integer.valueOf(math[temp]) + Integer.valueOf(math[i])) + "";
                math[i] = "";
                print(math);
            }
    }

    private static void print(String[] math) {
        for (int i = 0; i < math.length; i++)
            System.out.print(math[i].matches("[0-9]+")
                    ? math[0].equals("") ? i == 1 ? math[i] : "+" + math[i] : i == 0 ? math[i] : "+" + math[i]
                    : math[i]);
        System.out.println();
    }

    private static int Check(String math[], int i) {
        return math[i].equals("") ? Check(math, i - 1) : i;
    }
쉬울줄 알고 시작했는데 막상 해보니 음수 관련 부분이 생각보다 까다로웠습니다.
사칙연산을 잘 못하여 배우는 초등학생이 음수 연산을 배웠을리는 없겠으나..........

2018/08/28 13:10

김지훈

첫자리/결과값 음수, 소수점 모두 계산 가능합니다.

import re


def cal(s):
    s = print_step("\*|/", s)
    s = print_step("\+|-", s)


def print_step(p, s):
    while re.findall(p, s[1:] if s[0] == "-" else s):
        pattern = "[-+]?\d+[.]?\d*[" + p + "][-+]?\d+[.]?\d*"
        found = re.findall(pattern, s)[0]
        val = str(eval(found))
        val = val if val[0] == "-" else "+" + val
        s = s.replace(found, val)
        s = s[1:] if s[0] == "+" else s
        print(s)
    return s

s = "5+6*3-6/2+5"
cal(s)

2018/08/30 10:46

Wannagenie

Ruby

def calc(exp)
  exp = exp.split(/(\d+)/).reject(&:empty?) if exp.is_a? String 
  idx = (exp.index {|e| e =~ /[*\/]/} || exp.index {|e| e =~ /[+-]/})&.pred
  calc(exp.insert(idx, eval(exp.slice!(idx, 3)*'')).tap {|e| puts e*''}) if idx
end

Test

expect{ calc("5+6*3-6/2+5") }.to output("5+18-6/2+5\n" +
                                        "5+18-3+5\n" +
                                        "23-3+5\n" +
                                        "20+5\n" +
                                        "25\n").to_stdout

2018/08/30 19:51

rk

def teach_calc(s):
  for i in '*/+-': s = s.replace(i, f'{i:^3}')
  eq = s.split()

  print(s)
  idx = 0
  while idx < len(eq):
    if eq[idx] in '*/':
      eq[idx-1: idx+2] = [str(eval(''.join(eq[idx-1:idx+2])))]
      print(''.join(eq))
    else: idx += 1
  while len(eq) > 1:
    eq[:3] = [str(eval(''.join(eq[:3])))]
    print(''.join(eq))

test = '5+6*3-6/2+5'
teach_calc(test)
5 + 6 * 3 - 6 / 2 + 5
5+18-6/2+5
5+18-3.0+5
23-3.0+5
20.0+5
25.0

2018/09/06 21:44

Creator

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string n;
    // 입력
    cin >> n;
    // 첫번째 인덱스 저장
    int sum = stoi(n.substr(0, n.find('+' | '-', 0)));
    int index;

    for (int i = 0; i <n.length(); i++)
    {
        if (n[i] == '+')
        {
            sum += stoi(n.substr(i + 1, n.find('+' | '-', i)));
            cout << sum;
            if (n.find('+', i + 1) < n.find('-', i + 1))
                index = n.find('+', i);
            else
                index = n.find('-', i);
            for (int j = index; j < n.length(); j++)
                cout << n[j];
            cout << endl;
        }
        else if (n[i] == '-')
        {
            sum -= stoi(n.substr(i + 1, n.find('+' | '-', i)));
            cout << sum;
            if (n.find('+', i + 1) < n.find('-', i + 1))
                index = n.find('+', i);
            else
                index = n.find('-', i);
            for (int j = index; j < n.length(); j++)
                cout << n[j];
            cout << endl;
        }

    }
}

예시 1 버전도 해볼께요 ㅎㅎ...

2018/09/24 16:52

Jun ki Kim

// ===============================================

        String st = "5+6*3-6/2+5";
        String math = "+-*/";
        String temp1;
        String temp2;
        String temp3;
        String temp4;
        String temp5;
        String temp6;

        for (int i = 0; i < st.length(); i++) {
            if (st.charAt(i) == math.charAt(2)) {
                temp1 = st.substring(2, 3);
                temp2 = st.substring(4, 5);
                System.out.print(st.substring(0, 2));
                System.out.print((Integer.valueOf(temp1) * Integer.valueOf(temp2)));
                System.out.println(st.substring(5, 11));
            }
            if (st.charAt(i) == math.charAt(3)) {
                temp1 = st.substring(2, 3);
                temp2 = st.substring(4, 5);
                temp3 = st.substring(6, 7);
                temp4 = st.substring(8, 9);
                System.out.print(st.substring(0, 2));
                System.out.print((Integer.valueOf(temp1) * Integer.valueOf(temp2)));
                System.out.print(st.substring(5, 6));
                System.out.print((Integer.valueOf(temp3) / Integer.valueOf(temp4)));
                System.out.println(st.substring(9, 11));
            }

        }
        if (st.charAt(0) == st.charAt(0)) {
            temp1 = st.substring(2, 3);
            temp2 = st.substring(4, 5);
            temp3 = st.substring(6, 7);
            temp4 = st.substring(8, 9);
            temp5 = st.substring(0, 1);
            System.out.print(Integer.valueOf(temp5) + (Integer.valueOf(temp1) * Integer.valueOf(temp2)));
            System.out.print(st.substring(5, 6));
            System.out.print((Integer.valueOf(temp3) / Integer.valueOf(temp4)));
            System.out.println(st.substring(9, 11));
        }
        if (st.charAt(1) == st.charAt(1)) {
            temp1 = st.substring(2, 3);
            temp2 = st.substring(4, 5);
            temp3 = st.substring(6, 7);
            temp4 = st.substring(8, 9);
            temp5 = st.substring(0, 1);
            System.out.print(Integer.valueOf(temp5) + (Integer.valueOf(temp1) * Integer.valueOf(temp2))
                    - (Integer.valueOf(temp3) / Integer.valueOf(temp4)));
            System.out.println(st.substring(9, 11));
        }
        if (st.charAt(0) == st.charAt(0)) {
            temp1 = st.substring(2, 3);
            temp2 = st.substring(4, 5);
            temp3 = st.substring(6, 7);
            temp4 = st.substring(8, 9);
            temp5 = st.substring(0, 1);
            temp6 = st.substring(10, 11);
            System.out.print(Integer.valueOf(temp5) + (Integer.valueOf(temp1) * Integer.valueOf(temp2))
                    - (Integer.valueOf(temp3) / Integer.valueOf(temp4)) + Integer.valueOf(temp6));
        }

2018/09/28 20:55

채규빈

import re

def calc(s):
    p1 = re.compile('\d+[*/]\d+')
    p2 = re.compile('\d+[+-]\d+')

    while p1.search(s):
        print(s)
        m1 = p1.search(s)
        t = str(int(eval(m1.group())))
        s = p1.sub(t, s, count=1)

    while p2.search(s):
        print(s)
        m2 = p2.search(s)
        t = str(int(eval(m2.group())))
        s = p2.sub(t, s, count=1)

    print(s)
>>> calc('9+5-4+8')
9+5-4+8
14-4+8
10+8
18
>>> calc('5+6*3-6/2+5')
5+6*3-6/2+5
5+18-6/2+5
5+18-3+5
23-3+5
20+5
25

2019/04/30 16:11

messi

import re

INP = input("INPUT : ")
c = re.compile("\d*\.?\d+[*/]\d*\.?\d+")
while True : #먼저 *, / 를 계산합니다.
    SEP = c.search(INP)
    if SEP == None : #search의 결과가 None일 경우 루프를 나갑니다.
        break
    else :
        print(c.sub(str(eval(c.search(INP).group(0))), INP, count = 1)) #search의 결과 중 제일 첫 번째 결과를 계산해 결과를 바꿔넣습니다.
        INP = c.sub(str(eval(c.search(INP).group(0))), INP, count = 1) #문자열을 갱신합니다.
d = re.compile("\d*\.?\d+[+-]\d*\.?\d+")
while True : # +, -를 계산합니다.
    PPE = d.search(INP)
    if PPE == None :
        break
    else :
        print(d.sub(str(eval(d.search(INP).group(0))), INP, count = 1))
        INP = d.sub(str(eval(d.search(INP).group(0))), INP, count = 1)

결과

INPUT : 12+15*6+56/4+1+51
12+90+56/4+1+51
12+90+14.0+1+51
102+14.0+1+51
116.0+1+51
117.0+51
168.0

2019/12/04 16:37

GG

inp=input("사칙연산을 입력하십시오: ")
elst=[]
for num in inp:
    if num=="+" or num=="-": #곱셈과 나눗셈을 먼저 해야하니 +와 -를 분리하여 elst에 넣음
        elst.append(num)
        inp=inp.replace(num," ")
inp=inp.split()
i=0
for eq in elst: #+와 -를 홀수번째에 삽입
    inp.insert(2*i+1,elst[i])
    i+=1
for i in range(len(inp)): #곱셈(*)과 나눗셈(/) 계산
    if "*" in inp[i] or "/" in inp[i]:
        inp[i]=str(eval(inp[i]))
        print("".join(inp))
while len(inp)!=1: #리스트의 첫번째, 두번째, 세번째 요소를 뽑아 계산 후 리스트의 첫번째 요소로 넣는 것을 반복
    a=inp.pop(0)
    b=inp.pop(0)
    c=inp.pop(0)
    num=[str(eval(a+b+c))]
    inp=num+inp
    print("".join(inp))

결과

사칙연산을 입력하십시오: 5+6*3-6/2+5
5+18-6/2+5
5+18-3.0+5
23-3.0+5
20.0+5
25.0

사칙연산을 입력하십시오: 12+15*6+56/4+1+51
12+90+56/4+1+51
12+90+14.0+1+51
102+14.0+1+51
116.0+1+51
117.0+51
168.0

다만 위 코드는, 2+3 * 12/15-9와 같은 경우에 2+36/15-9, 2+2.4-9, 4.4-9, -4.6 이런식이 아니라, 바로 2+2.4-9로 곱셈과 나눗셈이 연속될 경우 한꺼번에 계산하는 단점이 있네요. 나중에 보고 다른 방법으로 도전해보겠습니다.

2020/02/13 21:40

박시원

output = [i for i in input().split(" ")]

while True:

  for i in output:

    if i ==  "*" or i == "/":
      idx = output.index(i)
      num1  = int(output.pop(idx -1))
      calculator = output.pop(idx -1)
      num2 = int(output.pop(idx -1))
      if i ==  "*":
        output.insert(idx-1, int(num1 * num2))
      if i ==  "/":
        output.insert(idx-1, int(num1 / num2))
      print(*output)
      break
  if "*" not in output and "/" not in output:
    break

while True:

  for i in output:

    if i ==  "+" or i == "-":
      idx = output.index(i)
      num1  = int(output.pop(idx -1))
      calculator = output.pop(idx -1)
      num2 = int(output.pop(idx -1))
      if i ==  "+":
        output.insert(idx-1, int(num1 + num2))
      if i ==  "-":
        output.insert(idx-1, int(num1 - num2))
      print(*output)
      break

  if "+" not in output and "-" not in output:
    break

2023/07/20 15:45

스탠리

using System;
using System.Collections.Generic;

namespace solution
{
    class Program
    {
        static void Main(string[] args)
        {
            //string prob = "12+15*6+56/4+1+51";
            Console.WriteLine("계산할 문제를 입력하세요:");
            string prob = Console.ReadLine();

            calcInOrder(prob);
        }

        private static void calcInOrder(string prob)
        {
            List<string> plist = new List<string>();
            string s = "";
            for (int i = 0; i < prob.Length; i++)
            {
                if (prob[i] == ' ')
                    continue;
                else if (!char.IsDigit(prob[i]))
                {
                    plist.Add(s);
                    s = "";
                    plist.Add(prob[i].ToString());
                }
                else
                    s += prob[i];
            }
            plist.Add(s);
            Console.WriteLine(string.Join(" ", plist));

            while(plist.Count > 2)
            {
                if (plist.Contains("*") || plist.Contains("/"))
                {
                    for (int i = 0; i < plist.Count; i++)
                    {
                        if (plist[i] == "*")
                        {
                            int su = int.Parse(plist[i - 1]) * int.Parse(plist[i + 1]);
                            for (int n = 0; n < 3; n++)
                                plist.RemoveAt(i - 1);
                            plist.Insert(i - 1, su.ToString());
                            break;
                        }
                        else if (plist[i] == "/")
                        {
                            int su = int.Parse(plist[i - 1]) / int.Parse(plist[i + 1]);
                            for (int n = 0; n < 3; n++)
                                plist.RemoveAt(i - 1);
                            plist.Insert(i - 1, su.ToString());
                            break;
                        }
                    }
                }
                else if (plist.Contains("+") || plist.Contains("-"))
                {
                    for (int i = 0; i < plist.Count; i++)
                    {
                        if (plist[i] == "+")
                        {
                            int su = int.Parse(plist[i - 1]) + int.Parse(plist[i + 1]);
                            for (int n = 0; n < 3; n++)
                                plist.RemoveAt(i - 1);
                            plist.Insert(i - 1, su.ToString());
                            break;
                        }
                        else if(plist[i] == "-")
                        {
                            int su = int.Parse(plist[i - 1]) - int.Parse(plist[i + 1]);
                            for (int n = 0; n < 3; n++)
                                plist.RemoveAt(i - 1);
                            plist.Insert(i - 1, su.ToString());
                            break;
                        }
                    }
                }
                Console.WriteLine("= {0}",string.Join(" ", plist));
            }
        }
    }
}

2023/09/06 14:25

insperChoi

목록으로