스킬트리
by Cori문제
선행 스킬이란 어떤 스킬을 배우기 전에 먼저 배워야 하는 스킬을 뜻합니다.
예를 들어 선행 스킬 순서가 스파크 → 라이트닝 볼트 → 썬더일때, 썬더를 배우려면 먼저 라이트닝 볼트를 배워야 하고, 라이트닝 볼트를 배우려면 먼저 스파크를 배워야 합니다.
위 순서에 없는 다른 스킬(힐링 등)은 순서에 상관없이 배울 수 있습니다. 따라서 스파크 → 힐링 → 라이트닝 볼트 → 썬더와 같은 스킬트리는 가능하지만, 썬더 → 스파크나 라이트닝 볼트 → 스파크 → 힐링 → 썬더와 같은 스킬트리는 불가능합니다. 선행 스킬 순서 skill과 유저들이 만든 스킬트리를 담은 배열 skill_trees가 매개변수로 주어질 때, 가능한 스킬트리 개수를 return 하는 solution 함수를 작성해주세요.
제한사항
· 스킬은 알파벳 대문자로 표기하며, 모든 문자열은 알파벳 대문자로만 이루어져 있습니다.
· 스킬 순서와 스킬트리는 문자열로 표기합니다. (C->B->D => "CBD")
· 선행 스킬 순서 skill의 길이는 1이상 26이하이며, 스킬은 중복해 주어지지 않습니다.
· skill_trees는 길이 1이상 20이하인 배열입니다.
· skill_trees의 원소는 스킬을 나타낸 문자열로, skill_trees의 원소의 길이는 2이상 26이하인 문자열이며, 스킬이 중복해서 주어지지 않습니다.
입출력 예
skill | skill_trees | return |
"CBD" | ["BACDE", "CBADF", "AECB", "BDA"] | 2 |
테스트케이스
skill (string) | skill_trees(string []) | return |
"CBD" | ["BACDE", "CBADF", "AECB", "BDA"] | 2 |
"CBD" | ["CAD"] | 0 |
"CBD" | ["AEF", "ZJW"] | 2 |
"REA" | ["REA", "POA"] | 1 |
"CBDK" | ["CB", "CXYB", "BD", "AECD", "ABC", "AEX", "CDB", "CBKD", "IJCB", "LMDK"] | 4 |
풀이
1. Me
def solution(skill, skill_trees):
answer = 0
for i in skill_trees:
tmp = []
for j in skill:
tmp.append(i.find(j)) # 찾는 문자열이 없을 경우 -1 반환
num_cnt = tmp.count(-1)
# print(num_cnt, i, tmp)
# [a,b,c,-1,-1] 과 같은 형태 (a < b < c) -> +1
# print(tmp[-num_cnt:] == [-1] * num_cnt)
if tmp[-num_cnt:] == [-1] * num_cnt:
# print(tmp)
if tmp[:-num_cnt] == sorted(tmp[:-num_cnt]):
# print(tmp[:-num_cnt])
answer += 1
elif -1 not in tmp:
if tmp == sorted(tmp):
# print(tmp)
answer += 1
# if tmp[-num_cnt:] == [-1] * num_cnt and
# 그외의 경우 -> continue
return answer
해당 문제를 풀기 위해 엄청나게 고민했다.. 단일 테스트케이스 통과는 되는데, 제출 후 채점하니 엄청나게 많이 틀려서 질문하기에 있는 테스트 케이스를 가져와 테스트케이스 실행을 통해 실험하며 작성한 코드 ..
일단 스킬셋에 있는 스킬을 스킬트리에서 검색하고, 인덱스를 찾는다. (find 함수, 없을 경우 -1 반환) 스킬셋에 대해 인덱스를 가진 배열을 얻게 되었고, 이를 정렬하여 정렬한 경우 스킬 사용이 가능하다고 판단하였는데, 스킬셋에 스킬이 없는 경우는 -1을 반환하기 때문에 무작정 정렬해서 비교하면 틀린 답을 뱉어냈다.
* 주어진 스킬: "CBDK", 스킬트리: ["CB", "CXYB", "BD"]인 경우, tmp = [0, 1, -1, -1], [0, 3, -1, -1], [-1, 0, 1, -1]
고민에 고민을 한 결과, 스킬 발동이 가능한 스킬트리의 경우는
1. 스킬트리가 주어진 스킬 + 기타 스킬로 구성된 경우 -> [a, b, c, ..., -1, -1], a < b < c 와 같은 형태일 경우 스킬이 발동된다. 스킬트리에 해당 스킬이 없을지라도 맨 마지막부터 순서대로 없는 경우라면 스킬 구현이 가능하다.
2. 스킬트리가 주어진 스킬로만 구성된 경우로, tmp에 -1이 없는 경우 -> [a, b, c], a < b < c와 같은 형태일 경우 스킬이 발동됨
위 코드를 다시 정리하면 아래와 같다.
def solution(skill, skill_trees):
answer = 0
for i in skill_trees:
tmp = []
for j in skill:
tmp.append(i.find(j)) # 찾는 문자열이 없을 경우 -1 반환
num_cnt = tmp.count(-1)
if tmp[-num_cnt:] == [-1] * num_cnt: # [a,b..d,-1,-1] 형태인 경우
if tmp[:-num_cnt] == sorted(tmp[:-num_cnt]): # [a ~ d]가 정렬되어 있으면
answer += 1
elif -1 not in tmp: # 찾는 문자열이 모두 있고
if tmp == sorted(tmp): # 순서대로 되어 있으면
answer += 1
return answer
2. Others
def solution(skill, skill_trees):
answer = 0
for skills in skill_trees:
skill_list = list(skill)
for s in skills:
if s in skill:
if s != skill_list.pop(0):
break
else:
answer += 1
return answer
for ~ else 구문이 있다는 걸 위 코드를 통해 처음 알았다. skill_trees를 탐색하며, 각각의 스킬트리의 스킬이 스킬목록에 들어있고, 들어있는 스킬이 스킬 목록의 맨 앞 스킬과 다른 경우는 break한다.. answer이 1씩 증가하는 경우는 스킬트리의 스킬이 스킬 목록에 없거나, 들어있는 스킬이 스킬 목록의 맨 앞 스킬과 같은 경우 두 가지 경우 !!
* for ~ else 구문은, for문이 중간에 break 등으로 끊기지 않고 끝까지 수행되었을 때 else문이 수행되도록 해준다.
def solution(skill,skill_tree):
answer=0
for i in skill_tree:
skil_list=''
for z in i:
if z in skill:
skil_list+=z
if skil_list==skill[0:len(skil_list)]:
answer+=1
return answer
각각의 스킬트리의 스킬이 스킬목록에 들어있는 경우에만 새로운 스킬 목록에 추가하고, 이를 기존의 스킬 목록과 비교하여 동일한 경우에 카운트한다. 스킬트리의 각 스킬이 스킬 목록에 들어있지 않은 경우에도 비어있는 리스트와 비교할 수 있기 때문에, 카운트 할 수 있음 !
'CS > Coding Test' 카테고리의 다른 글
이상한 문자 만들기 (0) | 2021.09.09 |
---|---|
제일 작은 수 제거하기 (0) | 2021.09.08 |
소수 만들기 (0) | 2021.09.04 |
올바른 괄호 (0) | 2021.09.04 |
다음 큰 숫자 (0) | 2021.09.03 |
블로그의 정보
코딩하는 오리
Cori