제로부터 시작하는 코딩 생활

[파이썬] 괄호쌍 검증기 본문

파이썬 예제

[파이썬] 괄호쌍 검증기

VacTEn 2022. 4. 7. 04:11

Q. 코드에선 괄호의 쌍이 올바르지 않으면 에러가 난다. 괄호쌍이 올바른지 판별하는 코드를 작성하라

코드공개

a = input("코드입력: ")

Brakets = {"[","]","{","}","(",")"}
BraketList = []
purity = True
extinction = False
loop = 0

def CheckA():
    global loop
    global extinction
    global purity
    loop = loop + 1
    if BraketList[loop] == "]":
        del BraketList[loop-1:loop+1]
        extinction = True
    elif BraketList[loop] == "{":
        CheckB()
    elif BraketList[loop] == "(":
        CheckC()
    elif BraketList[loop] == ")" or BraketList[loop] == "}":
        purity = False

def CheckB():
    global loop
    global extinction
    global purity
    loop = loop + 1
    if BraketList[loop] == "}":
        del BraketList[loop-1:loop+1]
        extinction = True
    elif BraketList[loop] == "[":
        CheckA()
    elif BraketList[loop] == "(":
        CheckC()
    elif BraketList[loop] == ")" or BraketList[loop] == "]":
        purity = False
    
def CheckC():
    global loop
    global extinction
    global purity
    loop = loop + 1
    if BraketList[loop] == ")":
        del BraketList[loop-1:loop+1]
        extinction = True
    elif BraketList[loop] == "[":
        CheckA()
    elif BraketList[loop] == "{":
        CheckB()
    elif BraketList[loop] == "]" or BraketList[loop] == "}":
        purity = False
    
    
for i in a:
    if i in Brakets:
        BraketList.append(i)

while (purity == True) and (BraketList != []):
    for i in BraketList:
        if purity == False or extinction == True:
            loop = 0
            extinction =False
            break
        elif i == "[":
            CheckA()
        elif i == "{":
            CheckB()
        elif i == "(":
            CheckC()
        else:
            purity = False
if purity == False:
    print("괄호쌍 오류")
else:
    print("괄호쌍 정상")

막힌부분

 함수를 정의 할때 함수밖의 변수를 함수내에 사용하면 오류가 발생하였다. 구글링을 통해 오류의 원인을 알 수 있었다. 이를 이해하기 위해선 지역변수와 전역변수라는 개념을 알아야 한다. 

 기본적으로 함수내에 선언되는 변수는 그 함수내에서만 사용가능하고 함수 외부에서 호출할 수 없다. 이를 지역변수라 부른다. 내부로 호출도 마찬가지다. 따라서 이를 전역변수로 바꾸어 주어야 변수가 어디에 있던 불러올 수 있다. 전역변수로 바꿔주는 것은 간단하다. global을 사용하면 된다.

해석

구상한 로직은 다음과 같다.

코드에서 괄호만을 순서대로 추출하여 리스트로 만들어준다. 여는 괄호 (,{,[ 바로뒤에 짝이맞는 닫는괄호 ),},] 가 등장하면 리스트에서 쌍소멸시킨다. 여는 괄호 뒤에 여는 괄호가 등장하는 것은 괜찮지만 짝이 맞지 않는 닫는괄호가 등장하는 것은 문법 오류이다. 또한 리스트의 첫 요소가 닫힌괄호로 문법오류이다. 첫 요소가 열린 괄호일경우 다음 요소가 짝이맞는 닫는괄호면 소멸시키고 짝이 아닌 닫는괄호면 문법오류이다. 또한 열린괄호이면 다시 그 다음요소에 대해 직전 괄호와 짝인지 아닌지 계속해서 반복하여 파고 들어간다. 문법에 오류가 발견되지 않거나 리스트가 빈 리스트가 될때까지 반복한다. 오류를 표시하는 변수의 상태에 따라 결과를 출력한다.

a = input("코드입력: ")

Brakets = {"[","]","{","}","(",")"}
BraketList = []
purity = True
extinction = False
loop = 0
for i in a:
    if i in Brakets:
        BraketList.append(i)

입력받은 코드에서 괄호만을 추출하여 리스트로 만든다.

문법의 무결성여부를 표시해주는 변수 purity를 만들어 초기값을 이상없음으로 해준다.

쌍소멸시 리스트의 요소들이 앞으로 두칸씩 당겨지므로 다시처음부터 하기위해 소멸여부를 확인하게 해주는 변수 extinction을 만들어 초기값을 거짓으로 해준다.

열린괄호 뒤에 열린괄호가 나올때 계속해서 다음 요소와 직전 요소를 확인해주어야 하므로 몇번 파고 들어갔는지 표시해주는 변수 loop를 만들어 초기값을 0으로 해준다.

def CheckA():
    global loop
    global extinction
    global purity
    loop = loop + 1
    if BraketList[loop] == "]":
        del BraketList[loop-1:loop+1]
        extinction = True
    elif BraketList[loop] == "{":
        CheckB()
    elif BraketList[loop] == "(":
        CheckC()
    elif BraketList[loop] == ")" or BraketList[loop] == "}":
        purity = False

def CheckB():
    global loop
    global extinction
    global purity
    loop = loop + 1
    if BraketList[loop] == "}":
        del BraketList[loop-1:loop+1]
        extinction = True
    elif BraketList[loop] == "[":
        CheckA()
    elif BraketList[loop] == "(":
        CheckC()
    elif BraketList[loop] == ")" or BraketList[loop] == "]":
        purity = False
    
def CheckC():
    global loop
    global extinction
    global purity
    loop = loop + 1
    if BraketList[loop] == ")":
        del BraketList[loop-1:loop+1]
        extinction = True
    elif BraketList[loop] == "[":
        CheckA()
    elif BraketList[loop] == "{":
        CheckB()
    elif BraketList[loop] == "]" or BraketList[loop] == "}":
        purity = False

 요소가 (,{,[ 각 상황에 맞게 세가지의 루트가 필요하기에 각각 함수를 만들어준다.함수로 만들어주는 이유는 열린괄호 뒤에 열린괄호의 경우 열린괄호가 연속된 수 만큼 동일 작업을 해주어야 하기 때문에 해당 작업을 함수로 미리 정의해준다.  또한 함수가 한번 반복 될때마다 loop를 1씩 증가시켜 증가된 loop를 사용하여 계속해서 다음 요소를 검사하고 때에 따라서 소멸시킬수 있게끔 한다.

 첫번째 함수만 설명해보면 이는 [ 가 등장했을때 실행되는 함수이다. 다음 요소가 ] 면 쌍소멸시키고 extinction을 True로 바꾸어준다. 소멸되면 리스트의 순서가 두칸씩 밀리기때문에 for문을 처음부터 하기 위한 표시이다. 만약 열린괄호가 등장할경우 괄호의 종류에 맞는 함수를 다시 실행시킨다. 만약 짝이 맞지 않는 닫힌 괄호가 등장하면 오류를 표시해준다.

while (purity == True) and (BraketList != []):
    for i in BraketList:
        if purity == False or extinction == True:
            loop = 0
            extinction =False
            break
        elif i == "[":
            CheckA()
        elif i == "{":
            CheckB()
        elif i == "(":
            CheckC()
        else:
            purity = False
if purity == False:
    print("괄호쌍 오류")
else:
    print("괄호쌍 정상")

  쌍소멸이 일어나면 for문을 깨고 loop을 다시 초기값으로 돌려준다. 소멸에 의해 for문이 깨져도 다시 실행되기 위해 상위에 while문을 추가하여 문법오류가 발견이 되지않고 리스트가 비워지지 않았다면 계속해서 for문을 실행한다. 만약 문법오류가 발견되면 for문을 깨고 이때는 while의 조건도 깨지기 때문에 바로 코드를 중단하고 오류임을 출력한다.

리스트의 첫요소가 열린괄호이면 상황에 맞는 함수를 실행시키고 닫힌괄호이면 오류를 표시한다.

'파이썬 예제' 카테고리의 다른 글

[파이썬] Sigmoid 활성화 함수 구현  (0) 2022.03.27
[파이썬] 삼각형 판별  (0) 2022.03.22
[파이썬] 최대 최소 찾기  (0) 2022.03.22