※ 본 사진과 해당 게시글 내용의 문제 모두 프로그래머스[Programmers]사이트에 발췌해왔습니다.
(주의!) 이번 게시물엔 개인적으로 풀어보다 정확도에서 실패한 코드이지만 배운 점과 알아볼 부분이 있어 정답 코드 외 요상한(?) 코드가 출현합니다..
해당문제가 개편되서 다른분들의 풀이가 틀리는 경우가 많았던 것 같아
다른 풀이에서 첫번째로 사용할 코드의 경우는 현재 오답으로 처리되는 코드입니다..!!
문자열로 구성된 리스트 strings와, 정수 n이 주어졌을 때,
각 문자열의 인덱스 n번째 글자를 기준으로 오름차순 정렬하려 합니다.
예를 들어 strings가 ["sun", "bed", "car"]이고 n이 1이면
각 단어의 인덱스 1의 문자 "u", "e", "a"로 strings를 정렬합니다.
제한 조건 :
strings는 길이 1 이상, 50이하인 배열입니다.
strings의 원소는 소문자 알파벳으로 이루어져 있습니다.
strings의 원소는 길이 1 이상, 100이하인 문자열입니다.
모든 strings의 원소의 길이는 n보다 큽니다.
인덱스 1의 문자가 같은 문자열이 여럿 일 경우,
사전순으로 앞선 문자열이 앞쪽에 위치합니다.
<입출력 예>
strings | n | return
["sun", "bed", "car"] | 1 | ["car", "bed", "sun"]
["abce", "abcd", "cdx"] | 2 | ["abcd", "abce", "cdx"]
제한 조건 :
⭕정답
def solution(strings, n):
mix = []
for s in strings :
mix.append(s[n]+s)
mix.sort()
answer = []
for s in mix :
answer.append(s[1:])
return answer
곧 설명할 예정이지만
밑에 있는 여러 코드들의 실패를 맛보고 해당 문제를 서치하며 다른 분들의 코드를 참고하여 풀게되었다.
우선 결론부터 말해보자면 strings 내부에 있는 단어들의n 인덱스를 가진 글자만 가져와 각 단어들의 앞에 붙인 후,
붙인 상태에서 정렬한 다음, 다시 분리하여 반환하는 방식이다.
for문을 통해
각 단어들에서 조건(n)위치의 글자를 기존 단어들 앞에 붙여 (.append(s[n]+s)
)
미리 선언해둔 빈 리스트(mix
)에 넣어준 후, 정렬(.sort()
)한다.
정렬하는 과정은 다른 변수에 대입하지 않고 자체 단독 명령을 해주어야한다.
그 후,
정답으로 반환할 리스트에 붙였던 조건 위치의 글자를 제외한 원래 단어들만 추출해서 넣어주고 정답으로 return한다.
❌실패
# (1)
# 정확도 낮음(25%)
def solution(strings, n):
words = [[word[n:],word] for word in strings]
words.sort(key=lambda x: x[0])
answer = []
for ls in words :
answer.append(ls[1])
return answer
# (2)
# 정확도 낮음(25%)
def solution(strings, n):
mix = []
for s in strings :
mix.append([s[n:], s])
mix = sorted(mix, key=lambda x: x[0])
return [ls[1] for ls in mix]
우선 놀라웠던 점은..
sort()
를 new_list = mix.sort()
와 같이
다른 리스트에 선언하면 안되고 단독 명령해야한다는 점이였다...
NoneType 오류가 발생하는지 궁금해서 더 알아봐야 겠다는 생각이 들었다.
1번부터 살펴 보자면
.sort()
를 사용하는 부분까지는 근접했고
key라는 인수로 정렬기준을 지정해서 작성해보았지만 NoneType 오류가 발생한 코드이다.
조건 중 "인덱스 1의 문자가 같은 문자열이 여럿 일 경우,
사전순으로 앞선 문자열이 앞쪽에 위치합니다." 라는 조건 때문에
조건위치의 문자가 같을 경우 를 대비해 뒤따라 오는 글자들까지 같이 합쳐 비교하려했다.
그렇게 [ (정렬 기준 문자) , (기존 문자) ] 로 이루어진 리스트를 가진 이중 리스트를 생성하고
이 리스트를 요소의 첫 번째 값을 기준으로 정렬해주었다.(.sort(key = lambda x:x[0])
)
정렬한 후,
다시 각 리스트들의 2번째 값만 따로 추출해서 반환하여 테스트 코드는 통과했지만 제출했을 때 실패하였다.
2번 코드 또한
테스트 코드는 통과했지만 제출했을 때 실패한 코드이다.
비슷해보이지만 다른 점이라 한다면
sorted()
라는 메서드를 사용하여 재선언하였고
return은 위 코드와 동일하게 작성하였다.
(1)
def strange_sort(strings, n):
'''strings의 문자열들을 n번째 글자를 기준으로 정렬해서 return하세요'''
min = []
result = []
for i in strings:
min.append(i[n])
sorted_min = sorted(min)
while len(result) != len(strings):
for j in range(0, len(strings)):
for k in range(0, len(strings)):
if sorted_min[j] in strings[k][n]:
index = k
result.append(strings[index])
continue
return result
현재는 실행시간이 10초가 초과되어서 틀린 답으로 나온 코드이지만
for문과 while문을 중첩시키면서 고민하셨을 노고와 끈기가 대단하신 것 같아 가져왔습니다...!!
위 풀이도 조건위치 글자가 동일할 경우를 대비해서 while문을 사용한 경우이다.
결과를 담을 result 리스트가 기준 글자를 담은 min 리스트의 길이가 다를 동안 돌아가는 while문이다.
중첩 for문으로 가지를 쳐 "string리스트의 길이의 2승"만큼 돌아가는데
각 단어마다 기준 index의 글자를 "정렬된 기준 글자 리스트(min)" 가 있으면 .append
하고 넘어가는(continue
) 형식이다.
이렇게 정렬된 순서대로 확인하여 해당하는 글자를 append하는 방법을 사용했다.
(2)
from operator import itemgetter
def solution(strings, n):
return sorted(sorted(strings), key=itemgetter(n))
operator.itemgetter
모듈은 주로 sorted와 같은 정렬 함수의 key 매개변수에 적용되어
다중 수준의 정렬을 가능하게 해주는 모듈이라고 한다.
itemgetter()
는 리스트나 튜플들이 중첩되어 구성된 배열에서 특정 위치의 값들만 가져오는 기능을 수행한다.
위 코드는
1차적으로 정렬한 string을 다시
기준 글자를 key로 재정렬한 것을 알 수 있다.
(확실하게 처리하는 군요....)