컴퓨터로 미분하는 방법(문자열 파싱에서 항상 실수하는 부분 복기)

1. 문제

 

15725번: 다항함수의 미분 (acmicpc.net)

 

15725번: 다항함수의 미분

첫째 줄에 최대 일차 일변수 다항식이 주어진다. 항의 개수는 최대 2개이고, 변수는 항상 x로 주어지며, 각 항은 공백 문자로 구분되지 않는다. 주어지는 계수와 상수의 절댓값은 10,000을 넘지 않

www.acmicpc.net

 

2. 풀이

 

그냥 간단하게 일차함수를 미분하면 된다

 

input으로 일차함수 형태가 들어오는데, 일차함수 미분은 결국 x의 계수니까, x의 계수를 파싱해서 출력하면 된다

 

말은 간단하지만... x의 계수를 컴퓨터가 찾기는 쉽지가 않지

 

여러가지 경우의 수를 생각해보자.

 

크게는 일차항이 없는 경우와 일차항이 있는 경우로 나뉠 것이다.

 

일차항이 없는 경우는 미분하면 0이니까...

 

input을 순회해서 x가 존재하는지 아닌지를 먼저 검사해보자. 존재하지 않으면 0을 출력한다

 

from sys import stdin

s = stdin.readline().rstrip()

len_s = len(s)

#일차항의 존재 유무 검사

find = False

for i in range(len_s):
    
    if s[i] == 'x':
        
        find = True
        break

#일차항이 없으면, 미분이 0
if find == False:
    
    print(0)

 

다음은 일차항이 있는 경우이다.

 

일차항이 있는 경우는..

 

3x+4도 있고 x+4도 있고.. -x+4도 있고... 4+x도 있고... 4+2x도 있고... 4-x도 있고...

 

for문 순회로 찾기 힘든 경우가 사실 x+4나 -x+4 같이 숫자 1이 숨겨져 있는 경우이다.

 

먼저 순회했는데 0번째에 x가 존재하는 경우... 그것은 "x+a"의 형태니까.. 미분하면 1이다.

 

else:
    
    #0번째 문자가 x이면... "x+a"의 경우
    if i == 0:
        
        print(1)

 

다음은 1번째 문자가 x인 경우이다.

 

그러니까 3x+4나 -x+4나.. 

 

이 경우에는 0번째 문자가 '-'인가? 아닌가?로 나뉠 것이다.

 

'-'라면 -1을 출력하고 아니라면 0번째 문자가 곧 숫자니까 그것을 출력  

 

    elif i == 1:
        
        #"-x+a"같은 경우
        if s[0] == '-':
            
            print(-1)
        
        #"bx+a"같은 경우
        else:
            
            print(s[0])

 

다음은 2번째 이후부터 x가 존재하는 경우이다.

 

여기서 생각해야할 것이..

 

그냥 습관적으로 x 앞에 숫자가 하나밖에 없겠지라고 생각하는 것이다.

 

사실은 10x+4나 100x+4나 1000x+4같이 x앞에 숫자가 여러개 있을 수도 있는데..

 

그거는 평소에 전혀 생각을 못하는 경우가 많았다는 것

 

그러니까 그냥 x가 i번째에 존재하면... 아무 생각없이 i-1번째 문자를 출력해버린다는 것이지.

 

실제로는 x앞에 붙은 숫자가 2자리 이상일수도 있는데    

 

elif i >= 2:
        
        num = s[:i]
            
        num_list = num.split('-')

        if len(num_list) >= 2:
            
            if num_list[-1] == '':
                
                print(-1)
            
            else:
                
                print(-int(num_list[-1]))

 

 

아무튼 이제는.. i-1번째 이전의 문자가 모두 x의 계수가 될 수 있다는 점이다.

 

그래서 num = s[:i]로 일단 가지고 오고

 

이렇게 되면 어떤 경우가 있을까?

 

 

300+200x  >>> 300+200

 

-300+200x >>> -300+200

 

300-200x >>> 300-200

 

-300-200x >>> -300-200

 

300+x >>> 300+

 

300-x >>> 300-

 

200x+3 >> 200

 

-200x+3 >>> -200

 

그러면 이렇게 가지고온 문자열에서 -와 +로 split을 해야할 것 같다.

 

먼저 -로 split을 하고... 얻은 리스트의 길이를 구해서 길이가 2 이상이라는 것은..

 

-300-200같이 ["", "300", "", "200"]

 

300-200같이 ["300","","200"]

 

이런 경우는 이제 -1번 원소에 -를 붙인 원소가  x의 계수가 된다

 

근데 300-같은 경우 -로 split하면... ["300", ""]으로 나온다.

 

그래서 -1번 원소가 ""인 경우는 x의 계수가 -1인 것이다.

 

        elif len(num_list) == 1:
            
            num_list = num_list[0].split('+')

            if len(num_list) >= 2:
                
                if num_list[-1] == '':
                    
                    print(1)
                
                else:

                    print(num_list[-1])
            
            elif len(num_list) == 1:
                
                print(num_list[0])

 

근데 -로 split해도 길이가 1인 리스트가 나온다면..

 

["300+200"]이나 ["300+"] 같은 경우가 될 것이다.

 

이런 경우에는 0번 원소를 가지고 와서 +로 split을 해주면 될것 같다.

 

비슷한 논리로 길이가 2이상일때, -1번 원소가 ""이라면 x의 계수는 +1이고

 

""가 아니라면, -1번 원소가 x의 계수가 된다.

 

그런데 길이가 1이라면... 다음과 같은 경우일 것이다.

 

["300000"]  

 

즉, 10000x 같은 경우가 이에 해당한다.

 

이는 그냥 0번 원소를 출력해주면 된다. 

 

from sys import stdin

s = stdin.readline().rstrip()

len_s = len(s)

#일차항이 존재하는 지 검사
find = False

for i in range(len_s):
    
    if s[i] == 'x':
        
        find = True
        break

#일차항이 없다면, 미분은 0
if find == False:
    
    print(0)

#일차항이 있다면,
else:
    
    #0번 원소가 x라면.. 계수는 1
    if i == 0:
        
        print(1)
    
    #1번 원소가 x라면...
    elif i == 1:
        
        #"-x+a"같은 경우
        if s[0] == '-':
            
            print(-1)
        
        #"bx+a"같은 경우
        else:
            
            print(s[0])
    
    #2번 이후에 x가 존재한다면...
    elif i >= 2:
        
        num = s[:i]
        
        #먼저 -로 split해보고
        num_list = num.split('-')
        
        #["","3000"]이나 ["","300","","200"]이나 ["200",""]같은 경우...
        if len(num_list) >= 2:
            
            #-1번에 x의 계수가 존재하는데... ''이라면 -1
            if num_list[-1] == '':
                
                print(-1)
            
            #''이 아니라면, -를 붙여서 출력
            else:
                
                print(-int(num_list[-1]))
        
        #-로 split해도 길이가 1이라면...
        elif len(num_list) == 1:
            
            #["300+200"]이나 ["300+"]같은 경우이다..
            num_list = num_list[0].split('+')
            
            #["300","","200"]이나 ["300",""] 같은 경우..
            if len(num_list) >= 2:
                
                #-1번 원소에 x의 계수가 있는데.. ''이라면.. 1
                if num_list[-1] == '':
                    
                    print(1)
                
                #''이 아니라면... -1번 원소를 그대로 출력
                else:

                    print(num_list[-1])
            
            #["1000"]같은 경우 +로 split해도 소용없다.
            elif len(num_list) == 1:
                
                #0번 원소를 그대로 출력
                print(num_list[0])

  

조건이 많이 분기된다는 점...

 

고려사항이 많아 실수하기 쉬운데..

 

생각을 많이 해야겠지

TAGS.

Comments