class Solution:
def isMatch(self, s: str, p: str) -> bool:
s = list(s)
p = list(p)
last_element = None
finished_with_asterist = False
while s and p:
print("first loop")
print(s)
print(p)
print("---")
ns = s.pop(0)
np = p.pop(0)
last_element = ns
if np == ".":
if p:
nnp = p[0]
if nnp == "*":
if (p[-1] in ):
return True
else:
return False
continue
elif np == "*":
finished_with_asterist = True
continue
while p:
print("second loop")
print(s)
print(p)
print("---")
nnp = p[0]
if nnp == "*":
if np != ns:
p.pop(0)
s.insert(0, ns)
finished_with_asterist = False
break
else:
while s:
nns = s[0]
if np == nns:
s.pop(0)
continue
else:
break
p.pop(0)
finished_with_asterist = True
else:
if ns == np:
break
else:
return False
while p:
print("final process P")
print(p)
print("---")
np = p.pop(0)
if np == ".":
return False
elif np == "*":
continue
else:
if p:
nnp = p.pop(0)
if nnp == "*":
continue
else:
return False
else:
if finished_with_asterist and (last_element == np):
break
else:
return False
print("before return answer")
print(s)
print(p)
print("---")
if (not s) and (not p):
return True
else:
if finished_with_asterist and (not s):
return True
elif (len(s) == 1):
ns = s.pop()
if finished_with_asterist and (ns == last_element):
return True
return False
먼저 나의 코드가 형편 없음을 고백한다.
그럼에도 불구하고 이 글을 작성하는 이유는 형편 없는 코드를 짜는 과정 속에서 깨달음 바가 있기 때문이다.
나는 처음에 모든 경우의 수를 처리할 수 있다면, 해당 문제를 풀 수 있다고 판단했다. 그래서 나는 크게 세 가지의 경우의 수를 나누고 문제를 풀었다.
즉, 위와 같이 모든 경우의 수를 직접 if-else 문으로 catch 할 수 있다면 문제를 풀 수 있다고 판단하였다.
모든 경우의 수를 고려하기 위해선 순차적으로 P와 S를 순환할 필요가 있었다. 그래서 나는 index를 활용하여 순환하는 전략을 세웠다. 이 전략을 세우면서 고려했던 것들은 다음과 같다.
그러나 코드에서 볼 수 있듯이, 모든 경우의 수를 if-else문으로 catch 하는 것은 매우 어려웠다. 왜냐하면 코드를 실행할 때마다 edge case가 나왔고, 이후에는 내가 이해할 수 없는 edge case가 나오는 지경에 이르렀다. 즉, if-else 방식으로 모든 경우의 수를 처리하기에는 경우의 수가 너무 많았다. 보통 적합한 방식으로 문제에 접근했을 땐, 이러한 비효율이 발생하지 않는다.
특히 나를 힘들게 했던 것은 수식을 해석하는 방식이었다. 처음에는 왼쪽에서 오른쪽으로 p를 읽어가며 정규표현식을 처리했다. 이렇게 접근하니 "a*a"와 같은 패턴을 처리하지 못했다. 더 나아가선 "a*b*c"와 같은 패턴은 더더욱 처리하기 어려웠다. 그래서 오른쪽에서 왼쪽으로 p를 읽어가며 패턴을 처리하려고 하니 동일한 케이스에서 문제가 발생했다.
즉, 애초에 내가 생각한 방식 자체가 잘못된 것이다.
그래서 문제의 해설을 찾아보니 Tree구조를 이용하여 dfe와 같은 알고지름을 순환하여 데이터를 처리하는 것 같았다.
이 문제를 통해 나의 알고리즘적인 역량의 한계를 느꼈다. graph 관련된 알고리즘에 대한 역량을 보충할 필요가 있다. 알고리즘 공부 좀 하자!
또한 문제를 풀면서 중위표현식을 계산하는 알고리즘을 구현했던 경험이 떠올랐다. 어떻게 보면 컴퓨터 내부에서 수식을 처리할 땐 정규표현식의 문제처럼 동일하게 수식을 처리하지 않을까란 생각이 들었다. 그래서 컴퓨터 프로그램의 구조와 해석이란 책을 읽어야겠단 생각도 들었다.
다음 글에서는 이러한 부족한 점을 어떻게 채웠는지 서술해보겠다.
요즘의 나는 기본기가 많이 부족함을 느낀다. 그래서 컴퓨터공학의 기본적인 지식을 채우기 위해서 오라클 구조 등을 공부하고 있으며, 앞으로는 시스템 성능을 측정하기 위해서 어떤 것들을 고려해야 하는지 Low level 관점에서 파악해보고자 한다.
High level의 코딩은 앞으로 인공지능이 더욱 잘하지 않을까? 요즘 들어 인공지능이 할 수 없는 일은 무엇일까 계속 고민하게 된다.