Day 2:

  1. 메뉴 리뉴얼
  2. 방문 길이
  3. 파일명 정렬
  4. 캐시
  5. 괄호 변환

뭔가 잘 풀릴 것 같은데 안 풀림?


1. 프로그래머스 메뉴 리뉴얼

내가 작성한 코드

from itertools import combinations  
from collections import Counter

#모든 경우의 수를 만들고 -> 하나만 뽑는다
def solution(orders,course):
    answer = []
    #course중 최대값 하나씩 찾아야하니까 필요
    for c in course:
        temp = []
        for order in orders:
            #정렬 -> 조합으로 모든 경우의 수 찾기
            temp += combinations(sorted(order),c)
            
        counter = Counter(temp)
        
        if counter:
            #제일 많이 주문된 것 뭐지?
            max_count = max(counter.values())
            if max_count >= 2:
                for menu,count in counter.items():
                    #제일 많이 주문된 것들 정답에 넣기
                    if count == max_count:
                        answer.append("".join(menu))
                
    return sorted(answer)

참고로 저는 성능 최적화? 신경 쓸 수 없습니다.
이 시리즈는 통과가 목적이기에 제 로직 -> 정확한 구현을 목표로 하고 있습니다. 성능 최적화와 모범 답안을 기대하신다면 다른 블로그를 참고하시는 것을 추천드립니다.

AI 코드는 생략하겠습니다. 취준생에게 시간은 금(포폴 제출할 게 있어서,,,

이 문제에서 얻어갈 것
조합(Combination) -> 조합을 이렇게 써먹게 될 줄 몰랐음


2. 프로그래머스 방문길이

내가 작성한 코드

def solution(dirs):
    answer = 0
    #U,D,R,L 정의
    moves={'U':(0,1),'D':(0,-1),'R':(1,0),'L':(-1,0)}
    #현재 위치
    curr_x, curr_y = 0,0
    visited = set() #중복된 길 하나로 합쳐줌
    
    for d in dirs:
        dx, dy = moves[d]
        nx, ny = curr_x + dx, curr_y + dy
        
        # 3. 경계 체크 (범위를 벗어나면 무시)
        if -5 <= nx <= 5 and -5 <= ny <= 5:
            # 4. "가본 길" 저장 (A->B와 B->A는 같은 길)
            visited.add((curr_x,curr_y,nx,ny))
            visited.add((nx,ny,curr_x,curr_y))
            
            curr_x, curr_y = nx, ny
            
        
    return len(visited) // 2

얻어갈 것
경로 저장 & 중복 제거
set(), tuple (리스트는 set에 못 넣음), 좌표 경계 체크


3. 프로그래머스 파일명 정렬

내가 작성한 코드

import re
def solution(files):
    
    #넣어둘 파일
    parsed_files = []
    
    for f in files:
        #HEAD,NUMBER나누는 것
        parts = re.split(r'(\d+)',f,1) #괄호
        
        #head,number정의
        head = parts[0]
        number = parts[1]
        
        #parsed_files에 어떻게 넣을지 -> append 사용
        #원본, lower로 만든 head, 숫자형 number넣어두기
        parsed_files.append((f, head.lower(),int(number)))
        
    #lambda활용해서 정렬 -> sort, key = lambda
    parsed_files.sort(key=lambda x:(x[1],x[2]))
    return [file[0] for file in parsed_files]

얻어갈 점
다중 조건 정렬
re.split(), sorted(key=lambda x: (x[1], x[2]))


4. 프로그래머스 캐시

내가 작성한 코드

from collections import deque
def solution(cacheSize, cities):
    answer = 0
    #큐(캐시 만듦)
    cache = deque(maxlen=cacheSize)
       
    for city in cities:
        city = city.lower()
        
        #캐시 안에 도시가 있다면?(Hit)
        if city in cache:
            answer += 1
            # 기존 위치에서 지우고 맨 뒤로 다시 보내서 '최신 상태' 만들기
            cache.remove(city)
            cache.append(city)
            # 점수 +1
        #Miss
        else:   
            answer += 5
            cache.append(city)
    return answer

오랜만에 반가웠던 LRU,,,
로직 생각할 때는 막히는 부분이 많은데 막상 다 짜면 뭐가 없음
그래서 코테가 어려운 거겠지,,,

얻어갈 점
LRU 알고리즘
collections.deque(maxlen=n), remove() & append()


5. 프로그래머스 괄호 변환

내가 작성한 코드

#올바른 함수인지 판단
def is_correct(s):
    stack = 0
    for char in s:
        if char == '(': stack += 1
        else:
            stack -=1
            if stack < 0: return False
    return stack == 0
    
#뒤집어주는 함수
def flip_brackets(s):
    flipped = ""
    for char in s:
        if char == '(': flipped += ')'
        else: flipped += '('
    return flipped

def split_uv(p):
    count = 0
    for i in range(len(p)):
        if p[i] == '(': count += 1
        else: count -= 1
        if count == 0:
            return p[:i+1], p[i+1:]    

def solution(p):
    answer = ''
    
    #빈 문자열 처리
    if not p: return ""
    
    #u,v로 분리
    u, v = split_uv(p)
    
    #u가 올바른 괄호인가?
    if is_correct(u):
        #맞다면 u에 재귀 돌려서 v를 붙이면 됨
        return u + solution(v)
    
    #u가 올바른 괄호가 아닐경우?
    else:
        #지문에 적힌 것 수행
        answer = "(" + solution(v) + ")"
        #u의 앞뒤 떼고 방향반대?
        answer += flip_brackets(u[1:-1])
    return answer

얻어갈 점
재귀(Recursion) & 구현
재귀 함수 구조, 문자열 슬라이싱 [1:-1]


Review

다중 조건 정렬 (Custom Sorting)

파일명 정렬과 메뉴 리뉴얼에서 사용
파이썬의 sort는 튜플을 이용해 1순위, 2순위 조건 달 수 있음

개념:
(조건1, 조건2) 순서로 튜플을 만들면, 조건1이 같을 때 조건2를 봄

Python

# (이름, 성적, 나이) 데이터가 있을 때
students = [("A", 90, 20), ("B", 90, 18), ("C", 80, 22)]

# 1순위 성적 내림차순(-), 2순위 나이 오름차순
students.sort(key=lambda x: (-x[1], x[2]))

# 결과: [('B', 90, 18), ('A', 90, 20), ('C', 80, 22)]

데이터 전처리 (Normalization)

파일명 정렬(대소문자 무시), 캐시(도시 이름 통일) 문제
비교하기 전에 데이터를 깨끗하게 만들기

개념:
입력받은 그대로 비교하지 말고, lower(), upper(), int() 등을 사용하여 비교 기준을 통일시킨 후 저장하거나 정렬

팁:
실제 정답은 '원본'을 출력해야 하므로, (원본, 가공데이터1, 가공데이터2) 형태의 튜플로 저장하는 습관

효율적인 중복 및 빈도 관리

메뉴 리뉴얼(Counter), 방문 길이(set)
for문으로 일일이 세는 것보다 훨씬 빠르고 정확

개념:
중복 제거/존재 여부 확인은 set

몇 개인지 카운팅할 때는 Counter

방문 길이 꿀팁: 길(Path)처럼 순서가 상관없는 데이터를 저장할 땐 sorted() 후 tuple로 만들어 set에 넣기

요령이 없고 그냥 묵묵히 내가 생각한 로직에 따라서 코드로 구현 시키는
그런 연습을 먼저 하는 중입니다...
그냥 합시다...완벽해야한다는 강박 버리기

profile
Challenging & Growing

0개의 댓글