알고리즘

프로그래머스 - 수식 최대화(67257)

SniKuz 2023. 7. 6. 22:37

링크 : https://school.programmers.co.kr/learn/courses/30/lessons/67257

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


문제 설명

오직 숫자와 +, -, * 연산자로 이루어진 문자열 수식이 다음과 같이 제공됩니다. "100-200*300-500+20" 
이 문자열 수식에서 연산자 우선순위를 정의하여 해당 수식에 결과의 절대값이 가장 큰 값이 무엇인지 구해야합니다.

예시로 "100-200*300-500+20"  수식은 * > + > - 로 연산자 우선순위를 정한다면 -60,420으로 절대값 60420으로 가장 큰 결과 값을 가집니다.

다음 주어진 수식들을 가장 절대값이 큰 결과값이 나오도록 연산자 우선순위를 정하고 결과값을 구하시오.


아이디어

1. 먼저 주어진 문자열을 숫자와 연산자로 분리합니다. ["100", "-", "200" ... "+", "20"]

2. 연산자가 3개이니 3! = 6으로 6가지 연산자 조합이 나오니 6가지 연산자 조합을 일일히 돌려줍니다.

3. 나온 결과를 가지고 비교해서 최대 결과값을 구합니다.


코드

#include <string>
#include <vector>
#include <iostream>
#include <list>
#include <algorithm>

using namespace std;

void separate(list<string> &e, string s)
{
    string tmp = "";
    for(auto c : s)
    {
        if(c == '-' || c == '*' || c == '+'){
            e.push_back(tmp);
            tmp = "";
            tmp += c;
            e.push_back(tmp);
            tmp = "";
        }
        else{
            tmp += c;
        }
    }
    e.push_back(tmp);
}

long long caculate(list<string> e, string priority){
    for(auto p : priority){
        long long tmp;
        list<string>::iterator iter = e.begin();
        
        while(true){
            if(iter == e.end()) break;
            
            string sp(1, p);
            if(*iter == sp){
                // ++, -- 였는데 prev, next로 변경하고 통과
                list<string>::iterator before = prev(iter);
                list<string>::iterator after = next(iter);
                if(p == '*') tmp = stoll(*before) * stoll(*after);
                if(p == '+') tmp = stoll(*before) + stoll(*after);
                if(p == '-') tmp = stoll(*before) - stoll(*after);
                
                *(before) = to_string(tmp);
                iter = e.erase(iter);
                iter = e.erase(iter);
            }
            else{
                iter++;
            }
        }
    }
    return abs(stoll(e.front()));
}

long long solution(string expression) {
    long long answer = 0;
    list<string> e;
    separate(e, expression);
    vector<string> operation = {"*+-", "*-+", "+*-", "+-*", "-*+", "-+*"};
    
    for(auto s : operation){
        caculate(e, s);
        answer = max(answer, caculate(e, s));
    }
    
    return answer;
}

추가 내용

○ 리스트 사용 : 분리된 문자열을 리스트로 쓴 이유는 연산자 우선순위를 따라 연산된 노드들을 삭제할 일이 많아 생성/삭제에 용이한 리스트를 쓰는게 좋다 생각했습니다.

○ caculate함수에서 iterator 자체를 조작하다가 문제가 많이 생겼는데, prev(), next()를 사용해서 해결됐습니다.