파이썬으로 프로그래머스 풀기 :: 쇠막대기
문제 설명
여러 개의 쇠막대기를 레이저로 절단하려고 합니다. 효율적인 작업을 위해서 쇠막대기를 아래에서 위로 겹쳐 놓고, 레이저를 위에서 수직으로 발사하여 쇠막대기들을 자릅니다. 쇠막대기와 레이저의 배치는 다음 조건을 만족합니다.
- 쇠막대기는 자신보다 긴 쇠막대기 위에만 놓일 수 있습니다.
- 쇠막대기를 다른 쇠막대기 위에 놓는 경우 완전히 포함되도록 놓되, 끝점은 겹치지 않도록 놓습니다.
- 각 쇠막대기를 자르는 레이저는 적어도 하나 존재합니다.
- 레이저는 어떤 쇠막대기의 양 끝점과도 겹치지 않습니다.
아래 그림은 위 조건을 만족하는 예를 보여줍니다. 수평으로 그려진 굵은 실선은 쇠막대기이고, 점은 레이저의 위치, 수직으로 그려진 점선 화살표는 레이저의 발사 방향입니다.
이러한 레이저와 쇠막대기의 배치는 다음과 같이 괄호를 이용하여 왼쪽부터 순서대로 표현할 수 있습니다.
(a) 레이저는 여는 괄호와 닫는 괄호의 인접한 쌍 '()'으로 표현합니다. 또한 모든 '()'는 반드시 레이저를 표현합니다.
(b) 쇠막대기의 왼쪽 끝은 여는 괄호 '('로, 오른쪽 끝은 닫힌 괄호 ')'로 표현됩니다.
위 예의 괄호 표현은 그림 위에 주어져 있습니다.
쇠막대기는 레이저에 의해 몇 개의 조각으로 잘리는데, 위 예에서 가장 위에 있는 두 개의 쇠막대기는 각각 3개와 2개의 조각으로 잘리고, 이와 같은 방식으로 주어진 쇠막대기들은 총 17개의 조각으로 잘립니다.
쇠막대기와 레이저의 배치를 표현한 문자열 arrangement가 매개변수로 주어질 때, 잘린 쇠막대기 조각의 총 개수를 return 하도록 solution 함수를 작성해주세요.
제한사항
- arrangement의 길이는 최대 100,000입니다.
- arrangement의 여는 괄호와 닫는 괄호는 항상 쌍을 이룹니다.
입출력 예
arrangement | return |
---|---|
()(((()())(())()))(()) | 17 |
입출력 예 설명
문제에 나온 예와 같습니다.
문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/42585
코드1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def solution(arrangement) : arrangement = list(arrangement) temp = list() x = 0; cnt = 0 for i in range(len(arrangement)) : a = arrangement.pop(0) if a == "(" : x+=1; cnt+=1 else : if temp[-1] == "(" : x-=1; cnt-=1; cnt+=x else : x-=1 temp.append(a) # print(i, x, cnt) return cnt | cs |
x가 안잘려진 막대기의 수, cnt가 잘려진 막대기의 수이다.
"("이면 일단 막대기가 하나 더 놓아졌다고 생각해 x와 cnt에 각각 +1 해준다.
이후 들어오는 문자가 ")"이면 이것이 레이저를 뜻하는지, 막대의 끝점인지 확인한다. (temp[-1]가 "(" 라면 레이저, ")"라면 막대이다.)
레이저를 뜻한다면 막대가 하나 더 놓아진 것이 아니기 때문에 +1 해준것을 그대로 다시 빼주고, 잘린 막대의 수를 cnt에 더해준다.
레이저가 한 번 지날 때마다 잘리지 않았다고 가정했을때 존재하는 막대의 수만큼 막대가 증가하기 때문에 cnt에 x를 더해주면 된다.
예)
이 상태로 시작한다.
가장 처음 "(" 이기 때문에 x와 cnt에 각각 +1한다.
")"에 대해서는 이전 문자(temp[-1])와 비교하여 레이저인지 막대의 끝인지 확인한다.
레이저라면 x와 cnt에 +1했던것을 다시 되돌리고(막대가 늘어난 것이 아니기 때문),
cnt에 x만큼 더해준다.(막대가 잘리면 x개 만큼 늘어나기 때문)
위의 과정을 반복한다.
...
...
코드2
1 2 3 4 5 6 7 8 | def solution(arrangment) : arrangement = arrangment.replace("()","0") x = 0;cnt = 0; for e in arrangement : if e == "(" : x+=1; cnt+=1 elif e == "0" : cnt+=x else : x-=1 return cnt | cs |
위 코드와 비슷한 방식이나, 좀 더 간단하다. "()" 를 애초에 다른 문자로 바꿔놓으면 ")"가 들어왔을 때, 이것이 레이저를 의미하는지 막대의 끝을 의미하는지 확인하지 않아도 된다.
'코딩테스트 연습 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] 숫자 야구 in python (0) | 2019.12.12 |
---|---|
[프로그래머스] 다리를 지나는 트럭 in python (1) | 2019.12.11 |
[프로그래머스] 가장 큰 수 in python (2) | 2019.12.09 |
[프로그래머스] 카펫 in python (5) | 2019.12.08 |
[프로그래머스] 124 나라의 숫자 in python (2) | 2019.12.07 |