프로그래머스 - 수식 최대화 (Lv. 2)

OQ·2022년 3월 15일
0

프로그래머스

목록 보기
17/33

문제 링크

풀이

import Foundation

func solution(_ expression:String) -> Int64 {
    var args: [(Operator?, Int)] = []   // (연산자, 숫자) 담을 배열
    
    // (연산자, 숫자) 튜플 형식으로 변환
    let scanner = Scanner(string: expression)
    let opertorStr = CharacterSet(charactersIn: "-+*")
    let numStr = scanner.scanUpToCharacters(from: opertorStr)!
    args.append((nil, Int(numStr)!))
    while !scanner.isAtEnd {
        if let operatorStr = scanner.scanCharacter() {
            let oper = Operator(rawValue: "\(operatorStr)")
            let numStr = scanner.scanUpToCharacters(from: opertorStr)!
            args.append((oper, Int(numStr)!))
        }
    }
    
    // 연산자 우선순위의 모든 경우의 수
    var priorityOperators: [[Operator]] = []
    Operator.priorityOperators(&priorityOperators)
    
    // 최대값 구하기
    var maxVal = 0
    for priorityOperator in priorityOperators {
        maxVal = max(operate(priorityOperator, args), maxVal)
    }
    
    return Int64(maxVal)
}

enum Operator: String, CaseIterable  {
    case plus = "+"
    case minus = "-"
    case multiple = "*"
    
    // 연산자 우선순위의 모든 경우의 수 구하기
    static func priorityOperators(_ arr: inout [[Operator]], 
                                  _ remains: [Operator] = Operator.allCases, 
                                  _ current: [Operator] = []) {
        if remains.count == 0 {
            arr.append(current)
            return
        } 
        
        for (index, oper) in remains.enumerated() {
            var operators = current
            var newRemains = remains
            operators.append(oper)
            newRemains.remove(at: index)
            priorityOperators(&arr, newRemains, operators)
        }
    }
    
    func caculate(_ arg1: Int, _ arg2: Int) -> Int {
        switch self {
            case .plus:
                return arg1 + arg2
            case .minus:
                return arg1 - arg2
            case .multiple:
                return arg1 * arg2
        }
    }
}

// 우선순위에 맞게 계산해서 결과를 리턴한다.
func operate(_ priority: [Operator], _ args: [(Operator?, Int)]) -> Int {
    var caculated = args
    for oper in priority {
        var isLoop = true
        while isLoop {
            isLoop = false
            for (index, arg) in caculated.enumerated() {
                if arg.0 == oper {
                    let result = oper.caculate(caculated[index - 1].1, arg.1)
                    caculated[index - 1].1 = result
                    caculated.remove(at: index)
                    isLoop = true
                    break
                }
            }   
        }
    }
    
    return abs(caculated[0].1)
}

후기

사칙연산하지말고 연산자 우선순위 배치해서 제일 최대값 나오는 경우를 찾아내는 문제.
문자열 인자값 파싱하는 방법으로 Scanner를 이용해보았다.
지문도 단번에 이해가고 깔끔하고 괜찮았던 문제.

profile
덕업일치 iOS 개발자

0개의 댓글