[구현] 문자열 압축

알고리즘/프로그래머스
2024. 3. 11. 20:35
728x90

하루 걸렸음..

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

def solution(s):
#aabbaccc 해서 5개 테스트 통과 근테 틀림
#aaaaaaaaaaaaaaabbbbbbbbbbc 테스트 케이스 해보고 통과
#하루 걸림;;;
#접근 방식:
# 무슨 단위로 나눠야 가장 짧게 압축할 수 있는지 처음부터 알지 못하므로 1~최대(문자열 길이) 단위로 모두 나눠서 리스트에 저장.
# lst[0] 1단위로 나눠진 문자열, lst[1] 2단위로 나눠진 문자열, .. lst[len(s)-1] len(s) 단위로 나눠진 문자열
#lst에 각 단위로 나눠진 문자를 저장했으므로 문자열 압축할 차례
# lst[0].pop해서 잘라진 문자와 같으면 cnt하나씩 늘려서 같은 문자 수 세기(pop이 뒤에서 부터 나오는데 어차피 자를때 앞에서 부터 잘라서 pop해도 상관없음)
# count 리스트에 압축한 문자 저장 (count[0] 1단위로 압축한 문자 (aabbaccc인 경우 ['3c', 'a', 2b', '2a']이런식으로 저장됨.)) -> 비교 대상과 같으면 cnt 늘리고 pop.. 대상과 같으면 cnt 늘리고 pop... 반복, 다르면 cnt와 비교대상 count 에 저장)
# count 리스트에 저장할 때 예외 케이스 잘 작성해야함. (while 시작 할 때 lst[단위] 의 첫번째 인덱스 값을 비교 대상으로 놓고 for 문에서 pop을 하면서 비교 대상을 계속 바꿈) -> 중간중간 print해서 예외 작성함.
# 비교 대상과 다를때 예외
# 1. cnt==1일 때 1a이런식으로 저장하지 않으므로 cnt 가 1인 경우 알파벳만 저장 (ex. lst['c','c','c','a','b','b','a','a] 에서 c, c검사하고 lst[2] (start = c)가 비교 대상이고 a (v = a)와 비교할 때 start 까지 cnt 증가하고 count 리스트에 저장하고 cnt = 1로 변경하고 start = a로 변경. start = a로 변경되고 pop해서 v = b와 비교하는데 cnt == 1인 상태 그럼 count에 1빼고 a만 저장..)
# 공통 예외 (비교대상같을 때 다를 때)
# 1. 리스트 마지막 요소남을 때 그것도 count 리스트에 포함 시켜야함. lst.pop하면서 lst 가 줄어드는데['c','c','c','a','b','b','a','a] 에서 pop해서 ['b','a','a'] 만 남은 상황start = b가 되고 v = a 하면 비교 대상이 다른 쪽으로 가서 start = a로 바뀌고 pop해서 v = a로 바뀜. 그럼 비교 대상이 같은 블록으로 가게 되고 cnt가 늘어남 근데 cnt만 들어남. 근데 여기서 다시 while로 돌아가면 반복문이 끝나서 a를 count에 넣지 못함. 그래서 v = lst.pop하고 lst의 길이가 0이면 count에append되도록
answer = 0
plus = 1
lst = []
count = [[] for i in range(len(s))]
#각 단위로 나눈 문자 저장하는 과정
while plus != len(s):
chunk = [] #1, 2, 3, ... len(s) 단위로 자른거 저장하는 리스트
for k in range(0, len(s), plus):
chunk.append(s[k:k+plus])
lst.append(chunk)
plus += 1
copyLst = [[] for i in range(len(lst))] #숫자와 알파벳 합친 문자열 저장하기 위한 리스트
idx = 0
for i in range(len(lst)):
start = lst[i].pop()
cnt = 1
while lst[i]:
v = lst[i].pop()
if start == v: #비교대상 동일 할 때
cnt += 1
if len(lst[i]) < 1: # 테스트 실패 후 2에서 1로 변경 ['a', 'a'] 인 상황에서 이 예외가 있어야 2a가 들어감.
count[idx].append(str(cnt) + start)
else: #비교대상 다를때
if cnt == 1: # ['a','b','a'] 인 상황에서 1로 압축된거 알파벳만 넣어주고 비교대상 다음 꺼로 변경
count[idx].append(start)
start = v
else: # cnt가 1이 아닐 때 압축한거 저장(3c) 하고 비교 대상 바꾸고 cnt = 1초기화
count[idx].append(str(cnt) + start)
start = v
cnt = 1
if len(lst[i]) < 1: # 테스트 실패 후 2에서 1로 변경 ['a','b'] 일때 start = b, v = a인 상황 start는 if..else 문에서 저장이 되고 v는 여기서 저장이 된다.
count[idx].append(v)
copyLst[i].append(''.join(count[idx]))
idx += 1
min = len(s)
#여기는 압축된 문자 뭐가 제일 짧은지 비교해서 min 찾아내는 부분
for i in range(len(copyLst)):
string = ''.join(copyLst[i])
if min > len(string):
min = len(string)
answer = min
return answer

 


다른 사람 풀이

프래그래머스 정답 코드

보고 신선한 충격 받음... 이게 Pythonic한 코드구나..

zip(), range() 함수 사용 등등 모르는게 많았음

특히 zip()사용한게 대단하다고 생각...

def compress(text, tok_len):
words = [text[i:i+tok_len] for i in range(0, len(text), tok_len)] # 1:1+1, 2:2+1.... 1:1+2, 3:3+2 각 단위로 슬라이스해서 배열로 저장 -> words 초기화 [[a,a,b,b,a,c,c,c], [aa,bb,ac,cc], ...]
res = []
cur_word = words[0]
cur_cnt = 1
for a, b in zip(words, words[1:] + ['']): #zip() = (words[0], words[1:]
if a == b:
cur_cnt += 1
else:
res.append([cur_word, cur_cnt])
cur_word = b
cur_cnt = 1
print(len(word) + (len(str(cnt)) if cnt > 1 else 0) for word, cnt in res)
return sum(len(word) + (len(str(cnt)) if cnt > 1 else 0) for word, cnt in res) #문자열 압축한 길
def solution(text):
return min(compress(text, tok_len) for tok_len in list(range(1, int(len(text)/2) + 1)) + [len(text)])
#text = aabbaccc len(text) = 8, list(range(1, 5)) + [8] = [1,2,3,4] + [8]
# tok_len = 1, 2, 3, 4, 8
# min(compress("aabbaccc", 1))
a = [
"aabbaccc",
"ababcdcdababcdcd",
"abcabcdede",
"abcabcabcabcdededededede",
"xababcdcdababcdcd",
'aaaaaa',
]
for x in a:
print(solution(x))

 


새롭게 알게 된 것

range()

range객체를 반환한다. 일정 범위의 연속된 정수를 생성하는 데 사용

이걸 단독으로 사용해볼 생각은 못함.

 

zip()

여러개의 iterable한 객체를 인자로 받고, 각 객체가 담고 있는 원소 튜플 형태로 차례로 접근할 수 있는 반복자(iterator)를 반환.

>>> numbers = [1, 2, 3]
>>> letters = ["A", "B", "C"]
>>> for pair in zip(numbers, letters):
... print(pair)
...
(1, 'A')
(2, 'B')
(3, 'C')

 

 

참고한 글

  • https://www.daleseo.com/python-zip/
728x90

'알고리즘 > 프로그래머스' 카테고리의 다른 글

[이진탐색] 가사 검색 (bisect 라이브러리 사용)  (0) 2024.08.11
[구현] 연속된 부분 수열의 합 (투포인터에 대해서...)  (0) 2024.08.05
이코테 [구현] 기둥과 보 설치  (3) 2024.07.20
[구현] 자물쇠와 열쇠  (0) 2024.04.29
무지의 먹방 라이브  (0) 2023.10.02
'알고리즘/프로그래머스' 카테고리의 다른 글
  • [구현] 연속된 부분 수열의 합 (투포인터에 대해서...)
  • 이코테 [구현] 기둥과 보 설치
  • [구현] 자물쇠와 열쇠
  • 무지의 먹방 라이브
hapBday
hapBday
hapBday
개발자로 성장하기 위한 기록들
hapBday
전체
오늘
어제
  • 분류 전체보기 (203)
    • CS (12)
      • 컴퓨터네트워크 (11)
      • 운영체제 (0)
      • 분산 시스템 (0)
      • 데이터베이스 (1)
    • Spring (47)
      • Spring 핵심 원리 (13)
      • Spring MVC (15)
      • Spring DB (12)
      • Spring Security (6)
    • JPA (14)
    • 알고리즘 (30)
      • 프로그래머스 (6)
      • 백준 (20)
    • Design Pattern (0)
    • 언어 (5)
      • JAVA (5)
    • ASAC 웹 풀스택 (38)
      • Spring Boot (21)
      • React (0)
      • DevOps (8)
    • 트러블슈팅 (15)
    • DevOps (5)
      • Docker (5)
    • ETC (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • github

공지사항

  • 블로그 이전

인기 글

태그

  • multi-stage
  • 백준
  • 프로그래머스
  • Spring
  • 3-layerd 아키텍쳐 패턴
  • docker workflow
  • aws lambda
  • cookie
  • basicerrorcontroller
  • 트랜잭션
  • 티스토리챌린지
  • CSRF
  • jwt
  • 구현
  • 인프런
  • JPA
  • MVC
  • 오블완
  • x-lock
  • CORS
  • s-lock
  • Java
  • currency control
  • spring boot
  • spring security
  • docker
  • docker best practices
  • Session
  • 김영한
  • S3

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.3.0
hapBday
[구현] 문자열 압축
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.