본문 바로가기
Project/JavaScript

[JavaScript 프로젝트 : 공학용 계산기] 중복 연산자 제거

by 꾸압 2022. 1. 19.

계산기에서 숫자없이 연산자를 연속으로 입력할 경우, 마지막에 입력한 연산자만이 기능한다.

그 기능을 넣고자 한다

 

<1차 시도, 문자열 replace>

let form = '2+*+/3';

let operator = ['+', '-', '*', '/'];
let replacedForm = "";

console.log(form.charAt(0));

// 연산자 단일 기능
for(let i=0; i<form.length; i++) {

    console.log('form.charAt(' + i + ') 출력 확인 : ' + form.charAt(i));
    console.log('form : ' + form);

    if(operator.includes(form.charAt(i)) 
        && operator.includes(form.charAt(i-1)) 
        && (i !== 0)) { 
            replacedForm = 
                form.substring(0, i-1) + 
                "" + form.substring(i); 
            
            form = replacedForm;
        }
}

console.log(replacedForm);

위 코드는 문자열의 앞 뒤를 비교하여 연산자가 반복 될 경우, 앞의 것을 제거하는 로직이다.

문제는 해당 index 에서 replace를 한번 수행하면, 앞에 또 다른 연산자(이미 replace를 수행하고 잔재한 친구)가 있어도 삭제하지 않고 넘어간다.

홀수 번째 연산자만 삭제하는 이런 기묘한...

 

<2차 시도, 배열에 나눠 넣기>

각 값을 2개 배열에 넣어 요소 일치를 확인하고, 마지막에 남은 배열의 요소들을 합쳐 다시 문자열로 만든다.

생각해본 logic 을 정리해 봤다,

 

<logic>

1) 입력 문자를 받을 때마다 배열 or 스택에 넣는다. (기능을 고려하여 임의로 arr, stack이라 지칭)

2) 숫자면 num arr 에 넣고
2-1) 연산자면 op stack 에 넣는다

3) stack 에 들어갈 연산자가 앞의 것과 기능 중복이 발생하면, 
stack을 초기화시켜( stack =[] ) 들어간 모든 요소를 삭제하고
새로운 연산자를 stack에 삽입한다.

3-1) '(' 왼 괄호에 한하여 괄호 앞에 괄호가 아닌 연산자 1개 허용
3-2 ) '(' 오른 괄호에 한하여 괄호 뒤에 괄호가 아닌 연산자 1개 허용

4) arr 에 숫자가 들어오거나 조건을 만족시키면( 괄호 등), 
 arr와 stack에 있는 요소를 결과값 문자열에 합친다(add)

5) 문자열의 마지막에 도달하면 모든 arr 및 stack 의 요소를 저장



3 * (2 + 1) 이란 문자열이 있을 때


arr 저장 : 3
stack 저장 : * ( 

숫자가 넘어오면 arr, stack 에 있는 요소 모두 push
push 순서는 arr >>> stack 순서로 행한다.

arr 저장 : 2
stack 저장 : + 

숫자가 넘어오면 다시 push 반복

arr 저장 : 1
stack 저장 : )

문자열의 마지막을 확인하고 logic 마무리

 

==> FEEDBACK

위 2번 논리대로 코드를 구현하려고 하였으나 굳이 배열을 사용할 필요없음을 알았다.

원본 문자열의 요소를 반복문으로 하나씩 논리 전개하여 새로운 문자열에 더한다.

원본 문자 요소는 들어가기 전, 새로운 문자열의 마지막 element와 비교하여 연산자 중복을 확인한다.

그에 따라 경우의 수를 나눠 코드를 작성

 

<최종?>

let form = '(3+1)(*(2++1)';

let tmpArr = [];
let numTmpArr = [];
let opTmpStack = [];

for(let i=0; i < form.length; i++) {

    let classifi = form.charAt(i);

    // i-1 index 를 쓰기 위해 index[0] 은 항상 push
    if(i === 0 ) {
        tmpArr.push(classifi);
    }
    else {
        // 숫자면
        if(!isNaN(classifi)) {
            tmpArr.push(classifi);
        }
        // 이전 및 현재 index 모두 연산자면
        else if(isNaN(classifi) && isNaN(form.charAt(i-1))) {

            // 이전 index ['(']
            if(form.charAt(i-1) === '(') {
                
                // 현재 index : ['('] >>> 이전 괄호 pop
                if(classifi === '(') {
                    tmpArr.pop();
                    tmpArr.push(classifi);
                }
                // 현재 index : [')'] >>> 괄호 둘 다 제거
                else if(classifi === ')') {
                    tmpArr.pop();
                }
                // 현재 index : ['연산자'] >>> 이전 중복 연산자 모두 제거. 현재 index 생존
                else {
                    while(isNaN(tmpArr[tmpArr.length-1])) {
                        tmpArr.pop();
                    }
                    tmpArr.push(classifi);
                }
            }
            // 이전 index [')']
            else if(form.charAt(i-1) === ')') {

                // 현재 index : ['('] || index : [')]
                if(classifi === '(' || classifi === ')') { }
                // 현재 index : ['나머지 연산자']
                else {
                    tmpArr.push(classifi);
                }
            }
            // 이전 index ['나머지 연산자']
            else {
                // 현재 index '('
                if(classifi === '(') {
                    tmpArr.push(classifi);
                }
                // ')'
                else if(classifi === ')') {
                    tmpArr.pop();
                    tmpArr.push(classifi);
                }
                // 'rest operator'
                else {
                    tmpArr.pop();
                    tmpArr.push(classifi);
                }
            }
        }
        // 현재 index 는 연산자, 이전 index는 숫자
        else if(isNaN(classifi) && !isNaN(form.charAt(i-1))) {
            tmpArr.push(classifi);
        }
    }
}

let reformed = tmpArr.join("");

console.log(reformed);

 

위 코드의 원본 문자열 '(3+1)(*(2++1)' 에 대한 결과 값은 '(3+1*(2+1)' 다.

괄호 ( ) 를 올바른 숫자만큼 입력하면 정상출력되나, 요소 삭제가 발생하면 '(' or ')' 가 하나씩 남는 문제가 잔존한다.

어차피 저렇게 괄호를 이상하게 입력한 이상 display 에 '사용자가 잘못 입력하였음' 이라고 띄울까 싶기에

여기까지 생각하기로 한다.

 

(3+1*(2+1)
(3+1*(2+1)

 

 

 

 

 

 

댓글