프로그래머스_3차 파일명정렬

임정민·2024년 2월 5일
0

알고리즘 문제풀이

목록 보기
157/173
post-thumbnail

프로그래머스 Lv2 문제입니다. 실전에 대비하기 위해 60분 시간제한을 두고 풀었습니다.

문제

https://school.programmers.co.kr/learn/courses/30/lessons/17686#

[나의 풀이]

⌛ 시간초과 (20/100)


def solution(files):
    
    # HEAD : 문자
    # NUNMBER : 숫자, 0000, 0101
    # TAIL : 숫자 or 문자
    
    # 1) HEAD 사전순, 대소 구분X
    # 2) NUMBER : 숫자순, 앞 0 무시
    # 3) 같으면 원래 입력 순서 유지
    
    dic = {}
    idx = 0
    
    HEADs = set()
    
    for idx,file in enumerate(files):
        # print("-------------")
        dic[file] = ('',0,idx) # HEAD 문자열, NUMBER 수, .소숫점
        
        endHEAD = [False,0]
        endNUMBER = [False,0]
        HEAD = ''
        NUMBER = 0
        NUMBER_len = 0
        
        for i,x in enumerate(file):
            
            if not endHEAD[0]:
                if x.isdigit():
                    endHEAD = [True,i]
                    HEAD = file[:i].upper() 
                    # print("HEAD : ",HEAD)
                    HEADs.add(HEAD)
            else:
                NUMBER_len += 1
                # print("x :",x)
                # print("NUMBER_len : ",NUMBER_len)
                if not x.isdigit() or NUMBER_len>3:
                    NUMBER_len += 1
                    endNUMBER = [True,i]
                    NUMBER = int(file[endHEAD[1]:i])
                    # print("NUMBER : ",NUMBER)
                    break
        dic[file] = (HEAD,NUMBER,idx+1)

        # print("file : ",file)
        # print("endHEAD : ",endHEAD)
        # print("endNUMBER : ",endNUMBER)
    
    # print(dic)
    HEADs = sorted(list(HEADs))
    HEADs2 = dict()
    for i,HEAD in enumerate(HEADs):
        HEADs2[HEAD] = i+1
    # print(HEADs2)
    
    tmp = {}
    for k,v in dic.items():
        HEAD, NUMBER, idx = v
        tmp[k] = HEADs2[HEAD]*1000000+NUMBER+idx/1000000
        
    # print(sorted(tmp.items(), key = lambda x:x[1]))
    # print(sorted(tmp.items(), key = lambda x:x[1]))
    tmp = sorted(tmp.items(), key = lambda x:x[1])
    answer = []
    
    for x in tmp:
        answer.append(x[0])
    
    # print(answer)
#     print(files)
#     files.sort()
#     print(files)
    
    return answer
    

입력된 파일명들을 (files) HEAD, NUMBER, TAIL로 구분짓고 정렬하는 문제입니다.🐈🐈🐈

파일명 'foo010bar020.zip' 하나가 있다면 HEAD는 첫문자열부터 숫자가 나올 때까지인'foo', NUMBER은 HEAD 이후 최대 5자리까지의 숫자 '010'이며 TAIL은 NUMBER 이후 문자열인 'bar020.zip' 입니다.

HEAD를 대소문자 구분없이 정렬하고 NUMBER는 숫자로 취급하여 정렬한 뒤, HEAD와 NUMBER가 같다면 TAIL 부분과 상관없이 입력된 순서대로 출력하는 문제입니다.

입력된 파일명별 HEAD,NUMBER,입력 순서를 파악하여 이를 수치화 한 뒤, 정렬하여 구현하고자 하였습니다.

이를 위해, 모든 대소구분 없는 HEAD 값들에 점수를 부여하는 dict객체를 만들었습니다. 이후 HEAD*100000+NUMBER 값으로 수치화하여 정렬하였고 HEAD~NUMBER까지의 값이 같을 때는 입력순서(idx)를 기억하여 .소숫점 자릿수로 더하는 방식으로 연산하였습니다.

하지만 위 풀이 기준으로 해결되지 않는 반례들이 많아 시도해보았지만 다른 풀이를 검색해보아도 같은 방식의 풀이나 반례가 나오지 않아 다음번에 다시 시도해보겠습니다.

[다른 사람의 풀이1]


def solution(files):
    answer = []
    for f in files:
        head, number, tail = '', '', ''

        number_check = False
        for i in range(len(f)): # 문자열 자르기
            if f[i].isdigit():  # 처음 나오는 숫자부터는 NUMBER로
                number += f[i]
                number_check = True
            elif not number_check:  # NUMBER가 나오기 전까지는 HEAD
                head += f[i]
            else:               # NUMBER가 이미 나왔고, 숫자가 아닌 문자가 나오면 TAIL
                tail = f[i:]
                break
        answer.append((head, number, tail))  # HEAD, NUMBER, TAIL 하나의 튜플로 저장

    # print(answer)
    answer.sort(key=lambda x: (x[0].upper(), int(x[1])))  # HEAD 우선, NUMBER 차선으로 정렬
    # print(answer)

    return [''.join(t) for t in answer]   # 원래 형태로 문자열 만들어서 반환

파일명별 HEAD, NUMBER, TAIL을 각각 구하고 lambda 식을 활용하여 정렬한 풀이 입니다.🐍🐍🐍

'나의 풀이'에서는 문제에서 제시한 '두 파일의 HEAD 부분과, NUMBER의 숫자도 같을 경우, 원래 입력에 주어진 순서를 유지한다.'라는 조건을 만족하기 위해 따로 입력 순서를 기억하였지만, 파일의 HEAD, NUMBER를 기준으로 정렬할 때 이가 같다면 저절로 입력 순서대로 정렬되는 것을 볼 수 있었습니다.

[다른 사람의 풀이2]


# SOL 1)

def solution(files):
    lst = []
    head, number, tail = '', '', ''
    
    for file in files:
        for i in range(len(file)):
            
            if file[i].isdigit():
                head = file[:i]
                number = file[i:]

                for j in range(len(number)):
                    if not number[j].isdigit():
                        tail = number[j:]
                        number = number[:j]
                        break
                lst.append([head, number, tail])
                head, number, tail = '', '', ''
                break
            
    lst = sorted(lst, key = lambda x : (x[0].upper(), int(x[1])))
    return [''.join(i) for i in lst]

'다른 사람의 풀이1'과 같이 HEAD, NUMBER, TAIL을 구하고 lambda식이 포함된 정렬을 통해 구현한 풀이입니다.🐥🐥🐥

감사합니다.

profile
https://github.com/min731

0개의 댓글